summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-9xxx.c6
-rw-r--r--drivers/scsi/3w-sas.c6
-rw-r--r--drivers/scsi/3w-xxxx.c10
-rw-r--r--drivers/scsi/BusLogic.c4501
-rw-r--r--drivers/scsi/BusLogic.h1488
-rw-r--r--drivers/scsi/FlashPoint.c626
-rw-r--r--drivers/scsi/Kconfig24
-rw-r--r--drivers/scsi/NCR5380.c63
-rw-r--r--drivers/scsi/NCR5380.h6
-rw-r--r--drivers/scsi/NCR_D700.c12
-rw-r--r--drivers/scsi/NCR_Q720.c2
-rw-r--r--drivers/scsi/a100u2w.c8
-rw-r--r--drivers/scsi/a2091.c12
-rw-r--r--drivers/scsi/a3000.c16
-rw-r--r--drivers/scsi/a4000t.c15
-rw-r--r--drivers/scsi/aacraid/aacraid.h12
-rw-r--r--drivers/scsi/aacraid/commctrl.c3
-rw-r--r--drivers/scsi/aacraid/comminit.c13
-rw-r--r--drivers/scsi/aacraid/commsup.c3
-rw-r--r--drivers/scsi/aacraid/linit.c15
-rw-r--r--drivers/scsi/aacraid/src.c33
-rw-r--r--drivers/scsi/advansys.c1316
-rw-r--r--drivers/scsi/aha152x.c63
-rw-r--r--drivers/scsi/aha1740.c33
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c9
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h12
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_proc.c163
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c9
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h12
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_proc.c153
-rw-r--r--drivers/scsi/aic7xxx_old.c2
-rw-r--r--drivers/scsi/aic7xxx_old/aic7xxx.seq2
-rw-r--r--drivers/scsi/aic7xxx_old/aic7xxx_proc.c221
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dev.c24
-rw-r--r--drivers/scsi/aic94xx/aic94xx_hwi.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c23
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c3
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c2
-rw-r--r--drivers/scsi/arm/Kconfig10
-rw-r--r--drivers/scsi/arm/acornscsi.c65
-rw-r--r--drivers/scsi/arm/arxescsi.c47
-rw-r--r--drivers/scsi/arm/cumana_1.c9
-rw-r--r--drivers/scsi/arm/cumana_2.c51
-rw-r--r--drivers/scsi/arm/eesox.c49
-rw-r--r--drivers/scsi/arm/fas216.c31
-rw-r--r--drivers/scsi/arm/fas216.h6
-rw-r--r--drivers/scsi/arm/oak.c13
-rw-r--r--drivers/scsi/arm/powertec.c37
-rw-r--r--drivers/scsi/atari_NCR5380.c145
-rw-r--r--drivers/scsi/atari_scsi.c2
-rw-r--r--drivers/scsi/atari_scsi.h2
-rw-r--r--drivers/scsi/atp870u.c42
-rw-r--r--drivers/scsi/be2iscsi/be.h2
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c172
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h27
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c72
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.h2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c381
-rw-r--r--drivers/scsi/be2iscsi/be_main.h29
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c45
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h35
-rw-r--r--drivers/scsi/bfa/bfa_core.c3
-rw-r--r--drivers/scsi/bfa/bfa_defs.h103
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h77
-rw-r--r--drivers/scsi/bfa/bfa_fc.h15
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c2
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c62
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h34
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c209
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c11
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c74
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h9
-rw-r--r--drivers/scsi/bfa/bfa_ioc_cb.c86
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c46
-rw-r--r--drivers/scsi/bfa/bfa_svc.c700
-rw-r--r--drivers/scsi/bfa/bfa_svc.h34
-rw-r--r--drivers/scsi/bfa/bfad.c18
-rw-r--r--drivers/scsi/bfa/bfad_attr.c33
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c137
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h52
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c28
-rw-r--r--drivers/scsi/bfa/bfad_drv.h2
-rw-r--r--drivers/scsi/bfa/bfad_im.c25
-rw-r--r--drivers/scsi/bfa/bfi.h78
-rw-r--r--drivers/scsi/bfa/bfi_ms.h5
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h56
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c2
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c369
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c59
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c26
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c97
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h12
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c2
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c2
-rw-r--r--drivers/scsi/bvme6000_scsi.c6
-rw-r--r--drivers/scsi/ch.c21
-rw-r--r--drivers/scsi/constants.c235
-rw-r--r--drivers/scsi/csiostor/Makefile3
-rw-r--r--drivers/scsi/csiostor/csio_hw.c670
-rw-r--r--drivers/scsi/csiostor/csio_hw.h58
-rw-r--r--drivers/scsi/csiostor/csio_hw_chip.h175
-rw-r--r--drivers/scsi/csiostor/csio_hw_t4.c403
-rw-r--r--drivers/scsi/csiostor/csio_hw_t5.c397
-rw-r--r--drivers/scsi/csiostor/csio_init.c74
-rw-r--r--drivers/scsi/csiostor/csio_init.h29
-rw-r--r--drivers/scsi/csiostor/csio_lnode.h2
-rw-r--r--drivers/scsi/csiostor/csio_mb.c89
-rw-r--r--drivers/scsi/csiostor/csio_mb.h11
-rw-r--r--drivers/scsi/csiostor/csio_rnode.c10
-rw-r--r--drivers/scsi/csiostor/csio_rnode.h2
-rw-r--r--drivers/scsi/csiostor/csio_scsi.c4
-rw-r--r--drivers/scsi/csiostor/csio_wr.c60
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c162
-rw-r--r--drivers/scsi/dc395x.c73
-rw-r--r--drivers/scsi/device_handler/Kconfig4
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c17
-rw-r--r--drivers/scsi/dmx3191d.c8
-rw-r--r--drivers/scsi/dpt_i2o.c106
-rw-r--r--drivers/scsi/dtc.c3
-rw-r--r--drivers/scsi/dtc.h3
-rw-r--r--drivers/scsi/eata_pio.c56
-rw-r--r--drivers/scsi/fcoe/fcoe.c318
-rw-r--r--drivers/scsi/fcoe/fcoe.h6
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c114
-rw-r--r--drivers/scsi/fcoe/fcoe_sysfs.c208
-rw-r--r--drivers/scsi/fcoe/fcoe_transport.c185
-rw-r--r--drivers/scsi/fcoe/libfcoe.h20
-rw-r--r--drivers/scsi/fdomain.c2
-rw-r--r--drivers/scsi/fnic/Makefile2
-rw-r--r--drivers/scsi/fnic/fnic.h94
-rw-r--r--drivers/scsi/fnic/fnic_debugfs.c302
-rw-r--r--drivers/scsi/fnic/fnic_fcs.c570
-rw-r--r--drivers/scsi/fnic/fnic_fip.h68
-rw-r--r--drivers/scsi/fnic/fnic_io.h6
-rw-r--r--drivers/scsi/fnic/fnic_main.c75
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c719
-rw-r--r--drivers/scsi/fnic/fnic_trace.c273
-rw-r--r--drivers/scsi/fnic/fnic_trace.h90
-rw-r--r--drivers/scsi/fnic/vnic_dev.c10
-rw-r--r--drivers/scsi/fnic/vnic_dev.h2
-rw-r--r--drivers/scsi/fnic/vnic_devcmd.h67
-rw-r--r--drivers/scsi/g_NCR5380.c53
-rw-r--r--drivers/scsi/gdth.c30
-rw-r--r--drivers/scsi/gdth.h3
-rw-r--r--drivers/scsi/gdth_proc.c211
-rw-r--r--drivers/scsi/gdth_proc.h5
-rw-r--r--drivers/scsi/gvp11.c14
-rw-r--r--drivers/scsi/hosts.c4
-rw-r--r--drivers/scsi/hpsa.c209
-rw-r--r--drivers/scsi/hptiop.c3
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c87
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h7
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c4
-rw-r--r--drivers/scsi/ibmvscsi/ibmvstgt.c2
-rw-r--r--drivers/scsi/imm.c40
-rw-r--r--drivers/scsi/in2000.c178
-rw-r--r--drivers/scsi/initio.c2
-rw-r--r--drivers/scsi/ipr.c1442
-rw-r--r--drivers/scsi/ipr.h110
-rw-r--r--drivers/scsi/ips.c248
-rw-r--r--drivers/scsi/ips.h9
-rw-r--r--drivers/scsi/isci/init.c16
-rw-r--r--drivers/scsi/isci/remote_device.c4
-rw-r--r--drivers/scsi/isci/remote_device.h2
-rw-r--r--drivers/scsi/isci/request.c10
-rw-r--r--drivers/scsi/isci/task.c2
-rw-r--r--drivers/scsi/iscsi_tcp.c18
-rw-r--r--drivers/scsi/jazz_esp.c6
-rw-r--r--drivers/scsi/lasi700.c2
-rw-r--r--drivers/scsi/libfc/fc_disc.c26
-rw-r--r--drivers/scsi/libfc/fc_exch.c41
-rw-r--r--drivers/scsi/libfc/fc_fcp.c8
-rw-r--r--drivers/scsi/libfc/fc_libfc.h38
-rw-r--r--drivers/scsi/libfc/fc_rport.c31
-rw-r--r--drivers/scsi/libiscsi.c22
-rw-r--r--drivers/scsi/libiscsi_tcp.c3
-rw-r--r--drivers/scsi/libsas/sas_ata.c18
-rw-r--r--drivers/scsi/libsas/sas_discover.c34
-rw-r--r--drivers/scsi/libsas/sas_expander.c128
-rw-r--r--drivers/scsi/libsas/sas_internal.h10
-rw-r--r--drivers/scsi/libsas/sas_port.c2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c2
-rw-r--r--drivers/scsi/lpfc/lpfc.h43
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c201
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c1183
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h8
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c42
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c161
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c199
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h188
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c940
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c38
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c875
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c666
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h30
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c25
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.h1
-rw-r--r--drivers/scsi/mac_esp.c6
-rw-r--r--drivers/scsi/mac_scsi.c3
-rw-r--r--drivers/scsi/mac_scsi.h3
-rw-r--r--drivers/scsi/megaraid.c1048
-rw-r--r--drivers/scsi/megaraid.h17
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c6
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h189
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c251
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c784
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c153
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h36
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h6
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h4
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h8
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_raid.h9
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_tool.h10
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c86
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h14
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c14
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c147
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c10
-rw-r--r--drivers/scsi/mpt3sas/Kconfig2
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2.h12
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h15
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_init.h2
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_ioc.h10
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_raid.h10
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_sas.h2
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_tool.h10
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_type.h2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c27
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h8
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_config.c5
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c19
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.h2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_debug.h2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c62
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_transport.c2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c3
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h2
-rw-r--r--drivers/scsi/mvme147.c3
-rw-r--r--drivers/scsi/mvme16x_scsi.c8
-rw-r--r--drivers/scsi/mvsas/mv_64xx.c8
-rw-r--r--drivers/scsi/mvsas/mv_94xx.c7
-rw-r--r--drivers/scsi/mvsas/mv_chips.h2
-rw-r--r--drivers/scsi/mvsas/mv_init.c27
-rw-r--r--drivers/scsi/mvsas/mv_sas.c33
-rw-r--r--drivers/scsi/mvsas/mv_sas.h9
-rw-r--r--drivers/scsi/mvumi.c9
-rw-r--r--drivers/scsi/mvumi.h1
-rw-r--r--drivers/scsi/nsp32.c57
-rw-r--r--drivers/scsi/osd/osd_initiator.c6
-rw-r--r--drivers/scsi/osd/osd_uld.c28
-rw-r--r--drivers/scsi/pas16.c3
-rw-r--r--drivers/scsi/pas16.h3
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c36
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h9
-rw-r--r--drivers/scsi/pm8001/Makefile7
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c74
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h34
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c856
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.h4
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c415
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c119
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h181
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c4131
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.h1523
-rw-r--r--drivers/scsi/pmcraid.c47
-rw-r--r--drivers/scsi/ppa.c36
-rw-r--r--drivers/scsi/ps3rom.c2
-rw-r--r--drivers/scsi/qla1280.c8
-rw-r--r--drivers/scsi/qla2xxx/Kconfig4
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c80
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c389
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c47
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h287
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h59
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c112
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c260
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h80
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c108
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c126
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c173
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c3475
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.h510
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c39
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c369
-rw-r--r--drivers/scsi/qla2xxx/qla_settings.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c339
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h20
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h6
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c18
-rw-r--r--drivers/scsi/qla4xxx/ql4_83xx.c83
-rw-r--r--drivers/scsi/qla4xxx/ql4_83xx.h10
-rw-r--r--drivers/scsi/qla4xxx/ql4_attr.c16
-rw-r--r--drivers/scsi/qla4xxx/ql4_dbg.h7
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h29
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h44
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h15
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c17
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c3
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c111
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c187
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c35
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c1886
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
-rw-r--r--drivers/scsi/qlogicfas.c2
-rw-r--r--drivers/scsi/qlogicpti.c20
-rw-r--r--drivers/scsi/scsi.c8
-rw-r--r--drivers/scsi/scsi_debug.c372
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/scsi_error.c46
-rw-r--r--drivers/scsi/scsi_lib.c57
-rw-r--r--drivers/scsi/scsi_netlink.c4
-rw-r--r--drivers/scsi/scsi_pm.c87
-rw-r--r--drivers/scsi/scsi_proc.c75
-rw-r--r--drivers/scsi/scsi_scan.c5
-rw-r--r--drivers/scsi/scsi_sysfs.c30
-rw-r--r--drivers/scsi/scsi_transport_fc.c27
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c1100
-rw-r--r--drivers/scsi/sd.c122
-rw-r--r--drivers/scsi/sd.h2
-rw-r--r--drivers/scsi/sd_dif.c8
-rw-r--r--drivers/scsi/sg.c44
-rw-r--r--drivers/scsi/sgiwd93.c4
-rw-r--r--drivers/scsi/sim710.c11
-rw-r--r--drivers/scsi/sni_53c710.c4
-rw-r--r--drivers/scsi/sr.c49
-rw-r--r--drivers/scsi/st.c37
-rw-r--r--drivers/scsi/stex.c5
-rw-r--r--drivers/scsi/storvsc_drv.c496
-rw-r--r--drivers/scsi/sun3_NCR5380.c183
-rw-r--r--drivers/scsi/sun3_scsi.c1
-rw-r--r--drivers/scsi/sun3_scsi.h2
-rw-r--r--drivers/scsi/sun3x_esp.c6
-rw-r--r--drivers/scsi/sun_esp.c30
-rw-r--r--drivers/scsi/sym53c416.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c138
-rw-r--r--drivers/scsi/t128.c3
-rw-r--r--drivers/scsi/t128.h3
-rw-r--r--drivers/scsi/tmscsim.c23
-rw-r--r--drivers/scsi/ufs/Kconfig87
-rw-r--r--drivers/scsi/ufs/Makefile2
-rw-r--r--drivers/scsi/ufs/ufs.h44
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c210
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c179
-rw-r--r--drivers/scsi/ufs/ufshcd.c933
-rw-r--r--drivers/scsi/ufs/ufshcd.h211
-rw-r--r--drivers/scsi/ufs/ufshci.h49
-rw-r--r--drivers/scsi/virtio_scsi.c493
-rw-r--r--drivers/scsi/vmw_pvscsi.c9
-rw-r--r--drivers/scsi/wd33c93.c194
-rw-r--r--drivers/scsi/wd33c93.h3
-rw-r--r--drivers/scsi/wd7000.c31
-rw-r--r--drivers/scsi/zalon.c2
-rw-r--r--drivers/scsi/zorro7xx.c12
368 files changed, 37142 insertions, 14246 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3868ab2..5e1e12c 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -640,7 +640,7 @@ out:
/* This function handles ioctl for the character device */
static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
long timeout;
unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0;
dma_addr_t dma_handle;
@@ -2029,7 +2029,7 @@ static struct scsi_host_template driver_template = {
};
/* This function will probe and initialize a card */
-static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
{
struct Scsi_Host *host = NULL;
TW_Device_Extension *tw_dev;
@@ -2305,7 +2305,7 @@ out_disable_device:
#endif
/* PCI Devices supported by this driver */
-static struct pci_device_id twa_pci_tbl[] __devinitdata = {
+static struct pci_device_id twa_pci_tbl[] = {
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX,
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 13e39e1..c845bdb 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -757,7 +757,7 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
dma_addr_t dma_handle;
int request_id = 0;
TW_Ioctl_Driver_Command driver_command;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file_inode(file);
TW_Ioctl_Buf_Apache *tw_ioctl;
TW_Command_Full *full_command_packet;
TW_Device_Extension *tw_dev = twl_device_extension_list[iminor(inode)];
@@ -1604,7 +1604,7 @@ static struct scsi_host_template driver_template = {
};
/* This function will probe and initialize a card */
-static int __devinit twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
{
struct Scsi_Host *host = NULL;
TW_Device_Extension *tw_dev;
@@ -1893,7 +1893,7 @@ out_disable_device:
#endif
/* PCI Devices supported by this driver */
-static struct pci_device_id twl_pci_tbl[] __devinitdata = {
+static struct pci_device_id twl_pci_tbl[] = {
{ PCI_VDEVICE(3WARE, PCI_DEVICE_ID_3WARE_9750) },
{ }
};
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 7fe96ff..b9276d1 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -216,6 +216,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
#include "3w-xxxx.h"
/* Globals */
@@ -889,7 +890,7 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
unsigned long flags;
unsigned int data_buffer_length = 0;
unsigned long data_buffer_length_adjusted = 0;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file_inode(file);
unsigned long *cpu_addr;
long timeout;
TW_New_Ioctl *tw_ioctl;
@@ -2009,7 +2010,8 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
tw_dev->state[request_id] = TW_S_COMPLETED;
tw_state_request_finish(tw_dev, request_id);
- SCpnt->result = (DID_BAD_TARGET << 16);
+ SCpnt->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+ scsi_build_sense_buffer(1, SCpnt->sense_buffer, ILLEGAL_REQUEST, 0x20, 0);
done(SCpnt);
retval = 0;
}
@@ -2281,7 +2283,7 @@ static struct scsi_host_template driver_template = {
};
/* This function will probe and initialize a card */
-static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
{
struct Scsi_Host *host = NULL;
TW_Device_Extension *tw_dev;
@@ -2422,7 +2424,7 @@ static void tw_remove(struct pci_dev *pdev)
} /* End tw_remove() */
/* PCI Devices supported by this driver */
-static struct pci_device_id tw_pci_tbl[] __devinitdata = {
+static struct pci_device_id tw_pci_tbl[] = {
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_1000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_7000,
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index d4da370..feab3a5 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -26,8 +26,8 @@
*/
-#define BusLogic_DriverVersion "2.1.16"
-#define BusLogic_DriverDate "18 July 2002"
+#define blogic_drvr_version "2.1.16"
+#define blogic_drvr_date "18 July 2002"
#include <linux/module.h>
#include <linux/init.h>
@@ -60,24 +60,24 @@
#define FAILURE (-1)
#endif
-static struct scsi_host_template Bus_Logic_template;
+static struct scsi_host_template blogic_template;
/*
- BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
+ blogic_drvr_options_count is a count of the number of BusLogic Driver
Options specifications provided via the Linux Kernel Command Line or via
the Loadable Kernel Module Installation Facility.
*/
-static int BusLogic_DriverOptionsCount;
+static int blogic_drvr_options_count;
/*
- BusLogic_DriverOptions is an array of Driver Options structures representing
+ blogic_drvr_options is an array of Driver Options structures representing
BusLogic Driver Options specifications provided via the Linux Kernel Command
Line or via the Loadable Kernel Module Installation Facility.
*/
-static struct BusLogic_DriverOptions BusLogic_DriverOptions[BusLogic_MaxHostAdapters];
+static struct blogic_drvr_options blogic_drvr_options[BLOGIC_MAX_ADAPTERS];
/*
@@ -92,241 +92,251 @@ module_param(BusLogic, charp, 0);
/*
- BusLogic_ProbeOptions is a set of Probe Options to be applied across
+ blogic_probe_options is a set of Probe Options to be applied across
all BusLogic Host Adapters.
*/
-static struct BusLogic_ProbeOptions BusLogic_ProbeOptions;
+static struct blogic_probe_options blogic_probe_options;
/*
- BusLogic_GlobalOptions is a set of Global Options to be applied across
+ blogic_global_options is a set of Global Options to be applied across
all BusLogic Host Adapters.
*/
-static struct BusLogic_GlobalOptions BusLogic_GlobalOptions;
+static struct blogic_global_options blogic_global_options;
-static LIST_HEAD(BusLogic_host_list);
+static LIST_HEAD(blogic_host_list);
/*
- BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
+ blogic_probeinfo_count is the number of entries in blogic_probeinfo_list.
*/
-static int BusLogic_ProbeInfoCount;
+static int blogic_probeinfo_count;
/*
- BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information
+ blogic_probeinfo_list is the list of I/O Addresses and Bus Probe Information
to be checked for potential BusLogic Host Adapters. It is initialized by
interrogating the PCI Configuration Space on PCI machines as well as from the
list of standard BusLogic I/O Addresses.
*/
-static struct BusLogic_ProbeInfo *BusLogic_ProbeInfoList;
+static struct blogic_probeinfo *blogic_probeinfo_list;
/*
- BusLogic_CommandFailureReason holds a string identifying the reason why a
- call to BusLogic_Command failed. It is only non-NULL when BusLogic_Command
+ blogic_cmd_failure_reason holds a string identifying the reason why a
+ call to blogic_cmd failed. It is only non-NULL when blogic_cmd
returns a failure code.
*/
-static char *BusLogic_CommandFailureReason;
+static char *blogic_cmd_failure_reason;
/*
- BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
+ blogic_announce_drvr announces the Driver Version and Date, Author's
Name, Copyright Notice, and Electronic Mail Address.
*/
-static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter)
+static void blogic_announce_drvr(struct blogic_adapter *adapter)
{
- BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n", HostAdapter);
- BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", HostAdapter);
+ blogic_announce("***** BusLogic SCSI Driver Version " blogic_drvr_version " of " blogic_drvr_date " *****\n", adapter);
+ blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", adapter);
}
/*
- BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI
+ blogic_drvr_info returns the Host Adapter Name to identify this SCSI
Driver and Host Adapter.
*/
-static const char *BusLogic_DriverInfo(struct Scsi_Host *Host)
+static const char *blogic_drvr_info(struct Scsi_Host *host)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
- return HostAdapter->FullModelName;
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) host->hostdata;
+ return adapter->full_model;
}
/*
- BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
- for Host Adapter from the BlockSize bytes located at BlockPointer. The newly
+ blogic_init_ccbs initializes a group of Command Control Blocks (CCBs)
+ for Host Adapter from the blk_size bytes located at blk_pointer. The newly
created CCBs are added to Host Adapter's free list.
*/
-static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, void *BlockPointer, int BlockSize, dma_addr_t BlockPointerHandle)
+static void blogic_init_ccbs(struct blogic_adapter *adapter, void *blk_pointer,
+ int blk_size, dma_addr_t blkp)
{
- struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;
+ struct blogic_ccb *ccb = (struct blogic_ccb *) blk_pointer;
unsigned int offset = 0;
- memset(BlockPointer, 0, BlockSize);
- CCB->AllocationGroupHead = BlockPointerHandle;
- CCB->AllocationGroupSize = BlockSize;
- while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) {
- CCB->Status = BusLogic_CCB_Free;
- CCB->HostAdapter = HostAdapter;
- CCB->DMA_Handle = (u32) BlockPointerHandle + offset;
- if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
- CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
- CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
+ memset(blk_pointer, 0, blk_size);
+ ccb->allocgrp_head = blkp;
+ ccb->allocgrp_size = blk_size;
+ while ((blk_size -= sizeof(struct blogic_ccb)) >= 0) {
+ ccb->status = BLOGIC_CCB_FREE;
+ ccb->adapter = adapter;
+ ccb->dma_handle = (u32) blkp + offset;
+ if (blogic_flashpoint_type(adapter)) {
+ ccb->callback = blogic_qcompleted_ccb;
+ ccb->base_addr = adapter->fpinfo.base_addr;
}
- CCB->Next = HostAdapter->Free_CCBs;
- CCB->NextAll = HostAdapter->All_CCBs;
- HostAdapter->Free_CCBs = CCB;
- HostAdapter->All_CCBs = CCB;
- HostAdapter->AllocatedCCBs++;
- CCB++;
- offset += sizeof(struct BusLogic_CCB);
+ ccb->next = adapter->free_ccbs;
+ ccb->next_all = adapter->all_ccbs;
+ adapter->free_ccbs = ccb;
+ adapter->all_ccbs = ccb;
+ adapter->alloc_ccbs++;
+ ccb++;
+ offset += sizeof(struct blogic_ccb);
}
}
/*
- BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
+ blogic_create_initccbs allocates the initial CCBs for Host Adapter.
*/
-static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init blogic_create_initccbs(struct blogic_adapter *adapter)
{
- int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
- void *BlockPointer;
- dma_addr_t BlockPointerHandle;
- while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) {
- BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
- if (BlockPointer == NULL) {
- BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", HostAdapter);
+ int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
+ void *blk_pointer;
+ dma_addr_t blkp;
+
+ while (adapter->alloc_ccbs < adapter->initccbs) {
+ blk_pointer = pci_alloc_consistent(adapter->pci_device,
+ blk_size, &blkp);
+ if (blk_pointer == NULL) {
+ blogic_err("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
+ adapter);
return false;
}
- BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
+ blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
}
return true;
}
/*
- BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.
+ blogic_destroy_ccbs deallocates the CCBs for Host Adapter.
*/
-static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter)
+static void blogic_destroy_ccbs(struct blogic_adapter *adapter)
{
- struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;
- HostAdapter->All_CCBs = NULL;
- HostAdapter->Free_CCBs = NULL;
- while ((CCB = NextCCB) != NULL) {
- NextCCB = CCB->NextAll;
- if (CCB->AllocationGroupHead) {
- if (Last_CCB)
- pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
- Last_CCB = CCB;
+ struct blogic_ccb *next_ccb = adapter->all_ccbs, *ccb, *lastccb = NULL;
+ adapter->all_ccbs = NULL;
+ adapter->free_ccbs = NULL;
+ while ((ccb = next_ccb) != NULL) {
+ next_ccb = ccb->next_all;
+ if (ccb->allocgrp_head) {
+ if (lastccb)
+ pci_free_consistent(adapter->pci_device,
+ lastccb->allocgrp_size, lastccb,
+ lastccb->allocgrp_head);
+ lastccb = ccb;
}
}
- if (Last_CCB)
- pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
+ if (lastccb)
+ pci_free_consistent(adapter->pci_device, lastccb->allocgrp_size,
+ lastccb, lastccb->allocgrp_head);
}
/*
- BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter. If
+ blogic_create_addlccbs allocates Additional CCBs for Host Adapter. If
allocation fails and there are no remaining CCBs available, the Driver Queue
Depth is decreased to a known safe value to avoid potential deadlocks when
multiple host adapters share the same IRQ Channel.
*/
-static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP)
+static void blogic_create_addlccbs(struct blogic_adapter *adapter,
+ int addl_ccbs, bool print_success)
{
- int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
- int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
- void *BlockPointer;
- dma_addr_t BlockPointerHandle;
- if (AdditionalCCBs <= 0)
+ int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
+ int prev_alloc = adapter->alloc_ccbs;
+ void *blk_pointer;
+ dma_addr_t blkp;
+ if (addl_ccbs <= 0)
return;
- while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) {
- BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
- if (BlockPointer == NULL)
+ while (adapter->alloc_ccbs - prev_alloc < addl_ccbs) {
+ blk_pointer = pci_alloc_consistent(adapter->pci_device,
+ blk_size, &blkp);
+ if (blk_pointer == NULL)
break;
- BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
+ blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
}
- if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) {
- if (SuccessMessageP)
- BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", HostAdapter, HostAdapter->AllocatedCCBs - PreviouslyAllocated, HostAdapter->AllocatedCCBs);
+ if (adapter->alloc_ccbs > prev_alloc) {
+ if (print_success)
+ blogic_notice("Allocated %d additional CCBs (total now %d)\n", adapter, adapter->alloc_ccbs - prev_alloc, adapter->alloc_ccbs);
return;
}
- BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
- if (HostAdapter->DriverQueueDepth > HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) {
- HostAdapter->DriverQueueDepth = HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
- HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
+ blogic_notice("Failed to allocate additional CCBs\n", adapter);
+ if (adapter->drvr_qdepth > adapter->alloc_ccbs - adapter->tgt_count) {
+ adapter->drvr_qdepth = adapter->alloc_ccbs - adapter->tgt_count;
+ adapter->scsi_host->can_queue = adapter->drvr_qdepth;
}
}
/*
- BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list,
+ blogic_alloc_ccb allocates a CCB from Host Adapter's free list,
allocating more memory from the Kernel if necessary. The Host Adapter's
Lock should already have been acquired by the caller.
*/
-static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter
- *HostAdapter)
+static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter)
{
- static unsigned long SerialNumber = 0;
- struct BusLogic_CCB *CCB;
- CCB = HostAdapter->Free_CCBs;
- if (CCB != NULL) {
- CCB->SerialNumber = ++SerialNumber;
- HostAdapter->Free_CCBs = CCB->Next;
- CCB->Next = NULL;
- if (HostAdapter->Free_CCBs == NULL)
- BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
- return CCB;
- }
- BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
- CCB = HostAdapter->Free_CCBs;
- if (CCB == NULL)
+ static unsigned long serial;
+ struct blogic_ccb *ccb;
+ ccb = adapter->free_ccbs;
+ if (ccb != NULL) {
+ ccb->serial = ++serial;
+ adapter->free_ccbs = ccb->next;
+ ccb->next = NULL;
+ if (adapter->free_ccbs == NULL)
+ blogic_create_addlccbs(adapter, adapter->inc_ccbs,
+ true);
+ return ccb;
+ }
+ blogic_create_addlccbs(adapter, adapter->inc_ccbs, true);
+ ccb = adapter->free_ccbs;
+ if (ccb == NULL)
return NULL;
- CCB->SerialNumber = ++SerialNumber;
- HostAdapter->Free_CCBs = CCB->Next;
- CCB->Next = NULL;
- return CCB;
+ ccb->serial = ++serial;
+ adapter->free_ccbs = ccb->next;
+ ccb->next = NULL;
+ return ccb;
}
/*
- BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's
+ blogic_dealloc_ccb deallocates a CCB, returning it to the Host Adapter's
free list. The Host Adapter's Lock should already have been acquired by the
caller.
*/
-static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
+static void blogic_dealloc_ccb(struct blogic_ccb *ccb)
{
- struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
+ struct blogic_adapter *adapter = ccb->adapter;
- scsi_dma_unmap(CCB->Command);
- pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
- CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+ scsi_dma_unmap(ccb->command);
+ pci_unmap_single(adapter->pci_device, ccb->sensedata,
+ ccb->sense_datalen, PCI_DMA_FROMDEVICE);
- CCB->Command = NULL;
- CCB->Status = BusLogic_CCB_Free;
- CCB->Next = HostAdapter->Free_CCBs;
- HostAdapter->Free_CCBs = CCB;
+ ccb->command = NULL;
+ ccb->status = BLOGIC_CCB_FREE;
+ ccb->next = adapter->free_ccbs;
+ adapter->free_ccbs = ccb;
}
/*
- BusLogic_Command sends the command OperationCode to HostAdapter, optionally
- providing ParameterLength bytes of ParameterData and receiving at most
- ReplyLength bytes of ReplyData; any excess reply data is received but
+ blogic_cmd sends the command opcode to adapter, optionally
+ providing paramlen bytes of param and receiving at most
+ replylen bytes of reply; any excess reply data is received but
discarded.
On success, this function returns the number of reply bytes read from
the Host Adapter (including any discarded data); on failure, it returns
-1 if the command was invalid, or -2 if a timeout occurred.
- BusLogic_Command is called exclusively during host adapter detection and
+ blogic_cmd is called exclusively during host adapter detection and
initialization, so performance and latency are not critical, and exclusive
access to the Host Adapter hardware is assumed. Once the host adapter and
driver are initialized, the only Host Adapter command that is issued is the
@@ -334,255 +344,274 @@ static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
waiting for the Host Adapter Ready bit to be set in the Status Register.
*/
-static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_OperationCode OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength)
+static int blogic_cmd(struct blogic_adapter *adapter, enum blogic_opcode opcode,
+ void *param, int paramlen, void *reply, int replylen)
{
- unsigned char *ParameterPointer = (unsigned char *) ParameterData;
- unsigned char *ReplyPointer = (unsigned char *) ReplyData;
- union BusLogic_StatusRegister StatusRegister;
- union BusLogic_InterruptRegister InterruptRegister;
- unsigned long ProcessorFlags = 0;
- int ReplyBytes = 0, Result;
- long TimeoutCounter;
+ unsigned char *param_p = (unsigned char *) param;
+ unsigned char *reply_p = (unsigned char *) reply;
+ union blogic_stat_reg statusreg;
+ union blogic_int_reg intreg;
+ unsigned long processor_flag = 0;
+ int reply_b = 0, result;
+ long timeout;
/*
Clear out the Reply Data if provided.
*/
- if (ReplyLength > 0)
- memset(ReplyData, 0, ReplyLength);
+ if (replylen > 0)
+ memset(reply, 0, replylen);
/*
- If the IRQ Channel has not yet been acquired, then interrupts must be
- disabled while issuing host adapter commands since a Command Complete
- interrupt could occur if the IRQ Channel was previously enabled by another
- BusLogic Host Adapter or another driver sharing the same IRQ Channel.
+ If the IRQ Channel has not yet been acquired, then interrupts
+ must be disabled while issuing host adapter commands since a
+ Command Complete interrupt could occur if the IRQ Channel was
+ previously enabled by another BusLogic Host Adapter or another
+ driver sharing the same IRQ Channel.
*/
- if (!HostAdapter->IRQ_ChannelAcquired)
- local_irq_save(ProcessorFlags);
+ if (!adapter->irq_acquired)
+ local_irq_save(processor_flag);
/*
- Wait for the Host Adapter Ready bit to be set and the Command/Parameter
- Register Busy bit to be reset in the Status Register.
+ Wait for the Host Adapter Ready bit to be set and the
+ Command/Parameter Register Busy bit to be reset in the Status
+ Register.
*/
- TimeoutCounter = 10000;
- while (--TimeoutCounter >= 0) {
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (StatusRegister.sr.HostAdapterReady && !StatusRegister.sr.CommandParameterRegisterBusy)
+ timeout = 10000;
+ while (--timeout >= 0) {
+ statusreg.all = blogic_rdstatus(adapter);
+ if (statusreg.sr.adapter_ready && !statusreg.sr.cmd_param_busy)
break;
udelay(100);
}
- if (TimeoutCounter < 0) {
- BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
- Result = -2;
- goto Done;
+ if (timeout < 0) {
+ blogic_cmd_failure_reason =
+ "Timeout waiting for Host Adapter Ready";
+ result = -2;
+ goto done;
}
/*
- Write the OperationCode to the Command/Parameter Register.
+ Write the opcode to the Command/Parameter Register.
*/
- HostAdapter->HostAdapterCommandCompleted = false;
- BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
+ adapter->adapter_cmd_complete = false;
+ blogic_setcmdparam(adapter, opcode);
/*
Write any additional Parameter Bytes.
*/
- TimeoutCounter = 10000;
- while (ParameterLength > 0 && --TimeoutCounter >= 0) {
+ timeout = 10000;
+ while (paramlen > 0 && --timeout >= 0) {
/*
- Wait 100 microseconds to give the Host Adapter enough time to determine
- whether the last value written to the Command/Parameter Register was
- valid or not. If the Command Complete bit is set in the Interrupt
- Register, then the Command Invalid bit in the Status Register will be
- reset if the Operation Code or Parameter was valid and the command
- has completed, or set if the Operation Code or Parameter was invalid.
- If the Data In Register Ready bit is set in the Status Register, then
- the Operation Code was valid, and data is waiting to be read back
- from the Host Adapter. Otherwise, wait for the Command/Parameter
- Register Busy bit in the Status Register to be reset.
+ Wait 100 microseconds to give the Host Adapter enough
+ time to determine whether the last value written to the
+ Command/Parameter Register was valid or not. If the
+ Command Complete bit is set in the Interrupt Register,
+ then the Command Invalid bit in the Status Register will
+ be reset if the Operation Code or Parameter was valid
+ and the command has completed, or set if the Operation
+ Code or Parameter was invalid. If the Data In Register
+ Ready bit is set in the Status Register, then the
+ Operation Code was valid, and data is waiting to be read
+ back from the Host Adapter. Otherwise, wait for the
+ Command/Parameter Register Busy bit in the Status
+ Register to be reset.
*/
udelay(100);
- InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (InterruptRegister.ir.CommandComplete)
+ intreg.all = blogic_rdint(adapter);
+ statusreg.all = blogic_rdstatus(adapter);
+ if (intreg.ir.cmd_complete)
break;
- if (HostAdapter->HostAdapterCommandCompleted)
+ if (adapter->adapter_cmd_complete)
break;
- if (StatusRegister.sr.DataInRegisterReady)
+ if (statusreg.sr.datain_ready)
break;
- if (StatusRegister.sr.CommandParameterRegisterBusy)
+ if (statusreg.sr.cmd_param_busy)
continue;
- BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
- ParameterLength--;
- }
- if (TimeoutCounter < 0) {
- BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance";
- Result = -2;
- goto Done;
- }
- /*
- The Modify I/O Address command does not cause a Command Complete Interrupt.
- */
- if (OperationCode == BusLogic_ModifyIOAddress) {
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (StatusRegister.sr.CommandInvalid) {
- BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
- Result = -1;
- goto Done;
+ blogic_setcmdparam(adapter, *param_p++);
+ paramlen--;
+ }
+ if (timeout < 0) {
+ blogic_cmd_failure_reason =
+ "Timeout waiting for Parameter Acceptance";
+ result = -2;
+ goto done;
+ }
+ /*
+ The Modify I/O Address command does not cause a Command Complete
+ Interrupt.
+ */
+ if (opcode == BLOGIC_MOD_IOADDR) {
+ statusreg.all = blogic_rdstatus(adapter);
+ if (statusreg.sr.cmd_invalid) {
+ blogic_cmd_failure_reason =
+ "Modify I/O Address Invalid";
+ result = -1;
+ goto done;
}
- if (BusLogic_GlobalOptions.TraceConfiguration)
- BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " "(Modify I/O Address)\n", HostAdapter, OperationCode, StatusRegister.All);
- Result = 0;
- goto Done;
+ if (blogic_global_options.trace_config)
+ blogic_notice("blogic_cmd(%02X) Status = %02X: " "(Modify I/O Address)\n", adapter, opcode, statusreg.all);
+ result = 0;
+ goto done;
}
/*
Select an appropriate timeout value for awaiting command completion.
*/
- switch (OperationCode) {
- case BusLogic_InquireInstalledDevicesID0to7:
- case BusLogic_InquireInstalledDevicesID8to15:
- case BusLogic_InquireTargetDevices:
+ switch (opcode) {
+ case BLOGIC_INQ_DEV0TO7:
+ case BLOGIC_INQ_DEV8TO15:
+ case BLOGIC_INQ_DEV:
/* Approximately 60 seconds. */
- TimeoutCounter = 60 * 10000;
+ timeout = 60 * 10000;
break;
default:
/* Approximately 1 second. */
- TimeoutCounter = 10000;
+ timeout = 10000;
break;
}
/*
- Receive any Reply Bytes, waiting for either the Command Complete bit to
- be set in the Interrupt Register, or for the Interrupt Handler to set the
- Host Adapter Command Completed bit in the Host Adapter structure.
+ Receive any Reply Bytes, waiting for either the Command
+ Complete bit to be set in the Interrupt Register, or for the
+ Interrupt Handler to set the Host Adapter Command Completed
+ bit in the Host Adapter structure.
*/
- while (--TimeoutCounter >= 0) {
- InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (InterruptRegister.ir.CommandComplete)
+ while (--timeout >= 0) {
+ intreg.all = blogic_rdint(adapter);
+ statusreg.all = blogic_rdstatus(adapter);
+ if (intreg.ir.cmd_complete)
break;
- if (HostAdapter->HostAdapterCommandCompleted)
+ if (adapter->adapter_cmd_complete)
break;
- if (StatusRegister.sr.DataInRegisterReady) {
- if (++ReplyBytes <= ReplyLength)
- *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
+ if (statusreg.sr.datain_ready) {
+ if (++reply_b <= replylen)
+ *reply_p++ = blogic_rddatain(adapter);
else
- BusLogic_ReadDataInRegister(HostAdapter);
+ blogic_rddatain(adapter);
}
- if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.sr.HostAdapterReady)
+ if (opcode == BLOGIC_FETCH_LOCALRAM &&
+ statusreg.sr.adapter_ready)
break;
udelay(100);
}
- if (TimeoutCounter < 0) {
- BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
- Result = -2;
- goto Done;
+ if (timeout < 0) {
+ blogic_cmd_failure_reason =
+ "Timeout waiting for Command Complete";
+ result = -2;
+ goto done;
}
/*
Clear any pending Command Complete Interrupt.
*/
- BusLogic_InterruptReset(HostAdapter);
+ blogic_intreset(adapter);
/*
Provide tracing information if requested.
*/
- if (BusLogic_GlobalOptions.TraceConfiguration) {
+ if (blogic_global_options.trace_config) {
int i;
- BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", HostAdapter, OperationCode, StatusRegister.All, ReplyLength, ReplyBytes);
- if (ReplyLength > ReplyBytes)
- ReplyLength = ReplyBytes;
- for (i = 0; i < ReplyLength; i++)
- BusLogic_Notice(" %02X", HostAdapter, ((unsigned char *) ReplyData)[i]);
- BusLogic_Notice("\n", HostAdapter);
+ blogic_notice("blogic_cmd(%02X) Status = %02X: %2d ==> %2d:",
+ adapter, opcode, statusreg.all, replylen,
+ reply_b);
+ if (replylen > reply_b)
+ replylen = reply_b;
+ for (i = 0; i < replylen; i++)
+ blogic_notice(" %02X", adapter,
+ ((unsigned char *) reply)[i]);
+ blogic_notice("\n", adapter);
}
/*
Process Command Invalid conditions.
*/
- if (StatusRegister.sr.CommandInvalid) {
+ if (statusreg.sr.cmd_invalid) {
/*
- Some early BusLogic Host Adapters may not recover properly from
- a Command Invalid condition, so if this appears to be the case,
- a Soft Reset is issued to the Host Adapter. Potentially invalid
- commands are never attempted after Mailbox Initialization is
- performed, so there should be no Host Adapter state lost by a
+ Some early BusLogic Host Adapters may not recover
+ properly from a Command Invalid condition, so if this
+ appears to be the case, a Soft Reset is issued to the
+ Host Adapter. Potentially invalid commands are never
+ attempted after Mailbox Initialization is performed,
+ so there should be no Host Adapter state lost by a
Soft Reset in response to a Command Invalid condition.
*/
udelay(1000);
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (StatusRegister.sr.CommandInvalid ||
- StatusRegister.sr.Reserved ||
- StatusRegister.sr.DataInRegisterReady ||
- StatusRegister.sr.CommandParameterRegisterBusy || !StatusRegister.sr.HostAdapterReady || !StatusRegister.sr.InitializationRequired || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.DiagnosticFailure) {
- BusLogic_SoftReset(HostAdapter);
+ statusreg.all = blogic_rdstatus(adapter);
+ if (statusreg.sr.cmd_invalid || statusreg.sr.rsvd ||
+ statusreg.sr.datain_ready ||
+ statusreg.sr.cmd_param_busy ||
+ !statusreg.sr.adapter_ready ||
+ !statusreg.sr.init_reqd ||
+ statusreg.sr.diag_active ||
+ statusreg.sr.diag_failed) {
+ blogic_softreset(adapter);
udelay(1000);
}
- BusLogic_CommandFailureReason = "Command Invalid";
- Result = -1;
- goto Done;
+ blogic_cmd_failure_reason = "Command Invalid";
+ result = -1;
+ goto done;
}
/*
Handle Excess Parameters Supplied conditions.
*/
- if (ParameterLength > 0) {
- BusLogic_CommandFailureReason = "Excess Parameters Supplied";
- Result = -1;
- goto Done;
+ if (paramlen > 0) {
+ blogic_cmd_failure_reason = "Excess Parameters Supplied";
+ result = -1;
+ goto done;
}
/*
Indicate the command completed successfully.
*/
- BusLogic_CommandFailureReason = NULL;
- Result = ReplyBytes;
+ blogic_cmd_failure_reason = NULL;
+ result = reply_b;
/*
Restore the interrupt status if necessary and return.
*/
- Done:
- if (!HostAdapter->IRQ_ChannelAcquired)
- local_irq_restore(ProcessorFlags);
- return Result;
+done:
+ if (!adapter->irq_acquired)
+ local_irq_restore(processor_flag);
+ return result;
}
/*
- BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list
+ blogic_add_probeaddr_isa appends a single ISA I/O Address to the list
of I/O Address and Bus Probe Information to be checked for potential BusLogic
Host Adapters.
*/
-static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address)
+static void __init blogic_add_probeaddr_isa(unsigned long io_addr)
{
- struct BusLogic_ProbeInfo *ProbeInfo;
- if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
+ struct blogic_probeinfo *probeinfo;
+ if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
return;
- ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
- ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
- ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
- ProbeInfo->IO_Address = IO_Address;
- ProbeInfo->PCI_Device = NULL;
+ probeinfo = &blogic_probeinfo_list[blogic_probeinfo_count++];
+ probeinfo->adapter_type = BLOGIC_MULTIMASTER;
+ probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
+ probeinfo->io_addr = io_addr;
+ probeinfo->pci_device = NULL;
}
/*
- BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and
+ blogic_init_probeinfo_isa initializes the list of I/O Address and
Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
*/
-static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapter
- *PrototypeHostAdapter)
+static void __init blogic_init_probeinfo_isa(struct blogic_adapter *adapter)
{
/*
- If BusLogic Driver Options specifications requested that ISA Bus Probes
- be inhibited, do not proceed further.
+ If BusLogic Driver Options specifications requested that ISA
+ Bus Probes be inhibited, do not proceed further.
*/
- if (BusLogic_ProbeOptions.NoProbeISA)
+ if (blogic_probe_options.noprobe_isa)
return;
/*
Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
*/
- if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe330)
- BusLogic_AppendProbeAddressISA(0x330);
- if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334)
- BusLogic_AppendProbeAddressISA(0x334);
- if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230)
- BusLogic_AppendProbeAddressISA(0x230);
- if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234)
- BusLogic_AppendProbeAddressISA(0x234);
- if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130)
- BusLogic_AppendProbeAddressISA(0x130);
- if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134)
- BusLogic_AppendProbeAddressISA(0x134);
+ if (!blogic_probe_options.limited_isa || blogic_probe_options.probe330)
+ blogic_add_probeaddr_isa(0x330);
+ if (!blogic_probe_options.limited_isa || blogic_probe_options.probe334)
+ blogic_add_probeaddr_isa(0x334);
+ if (!blogic_probe_options.limited_isa || blogic_probe_options.probe230)
+ blogic_add_probeaddr_isa(0x230);
+ if (!blogic_probe_options.limited_isa || blogic_probe_options.probe234)
+ blogic_add_probeaddr_isa(0x234);
+ if (!blogic_probe_options.limited_isa || blogic_probe_options.probe130)
+ blogic_add_probeaddr_isa(0x130);
+ if (!blogic_probe_options.limited_isa || blogic_probe_options.probe134)
+ blogic_add_probeaddr_isa(0x134);
}
@@ -590,25 +619,35 @@ static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapt
/*
- BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order
+ blogic_sort_probeinfo sorts a section of blogic_probeinfo_list in order
of increasing PCI Bus and Device Number.
*/
-static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, int ProbeInfoCount)
+static void __init blogic_sort_probeinfo(struct blogic_probeinfo
+ *probeinfo_list, int probeinfo_cnt)
{
- int LastInterchange = ProbeInfoCount - 1, Bound, j;
- while (LastInterchange > 0) {
- Bound = LastInterchange;
- LastInterchange = 0;
- for (j = 0; j < Bound; j++) {
- struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];
- struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j + 1];
- if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) {
- struct BusLogic_ProbeInfo TempProbeInfo;
- memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));
- memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));
- memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));
- LastInterchange = j;
+ int last_exchange = probeinfo_cnt - 1, bound, j;
+
+ while (last_exchange > 0) {
+ bound = last_exchange;
+ last_exchange = 0;
+ for (j = 0; j < bound; j++) {
+ struct blogic_probeinfo *probeinfo1 =
+ &probeinfo_list[j];
+ struct blogic_probeinfo *probeinfo2 =
+ &probeinfo_list[j + 1];
+ if (probeinfo1->bus > probeinfo2->bus ||
+ (probeinfo1->bus == probeinfo2->bus &&
+ (probeinfo1->dev > probeinfo2->dev))) {
+ struct blogic_probeinfo tmp_probeinfo;
+
+ memcpy(&tmp_probeinfo, probeinfo1,
+ sizeof(struct blogic_probeinfo));
+ memcpy(probeinfo1, probeinfo2,
+ sizeof(struct blogic_probeinfo));
+ memcpy(probeinfo2, &tmp_probeinfo,
+ sizeof(struct blogic_probeinfo));
+ last_exchange = j;
}
}
}
@@ -616,84 +655,88 @@ static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoLi
/*
- BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address
+ blogic_init_mm_probeinfo initializes the list of I/O Address
and Bus Probe Information to be checked for potential BusLogic MultiMaster
SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
machines as well as from the list of standard BusLogic MultiMaster ISA
I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found.
*/
-static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAdapter
- *PrototypeHostAdapter)
+static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
{
- struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
- int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
- int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
- bool ForceBusDeviceScanningOrder = false;
- bool ForceBusDeviceScanningOrderChecked = false;
- bool StandardAddressSeen[6];
- struct pci_dev *PCI_Device = NULL;
+ struct blogic_probeinfo *pr_probeinfo =
+ &blogic_probeinfo_list[blogic_probeinfo_count];
+ int nonpr_mmindex = blogic_probeinfo_count + 1;
+ int nonpr_mmcount = 0, mmcount = 0;
+ bool force_scan_order = false;
+ bool force_scan_order_checked = false;
+ bool addr_seen[6];
+ struct pci_dev *pci_device = NULL;
int i;
- if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
+ if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
return 0;
- BusLogic_ProbeInfoCount++;
+ blogic_probeinfo_count++;
for (i = 0; i < 6; i++)
- StandardAddressSeen[i] = false;
- /*
- Iterate over the MultiMaster PCI Host Adapters. For each enumerated host
- adapter, determine whether its ISA Compatible I/O Port is enabled and if
- so, whether it is assigned the Primary I/O Address. A host adapter that is
- assigned the Primary I/O Address will always be the preferred boot device.
- The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
- Address, then any other PCI host adapters, and finally any host adapters
- located at the remaining standard ISA I/O Addresses. When a PCI host
- adapter is found with its ISA Compatible I/O Port enabled, a command is
- issued to disable the ISA Compatible I/O Port, and it is noted that the
+ addr_seen[i] = false;
+ /*
+ Iterate over the MultiMaster PCI Host Adapters. For each
+ enumerated host adapter, determine whether its ISA Compatible
+ I/O Port is enabled and if so, whether it is assigned the
+ Primary I/O Address. A host adapter that is assigned the
+ Primary I/O Address will always be the preferred boot device.
+ The MultiMaster BIOS will first recognize a host adapter at
+ the Primary I/O Address, then any other PCI host adapters,
+ and finally any host adapters located at the remaining
+ standard ISA I/O Addresses. When a PCI host adapter is found
+ with its ISA Compatible I/O Port enabled, a command is issued
+ to disable the ISA Compatible I/O Port, and it is noted that the
particular standard ISA I/O Address need not be probed.
*/
- PrimaryProbeInfo->IO_Address = 0;
- while ((PCI_Device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, PCI_Device)) != NULL) {
- struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
- struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
- enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest;
- unsigned char Bus;
- unsigned char Device;
- unsigned int IRQ_Channel;
- unsigned long BaseAddress0;
- unsigned long BaseAddress1;
- unsigned long IO_Address;
- unsigned long PCI_Address;
-
- if (pci_enable_device(PCI_Device))
+ pr_probeinfo->io_addr = 0;
+ while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
+ PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
+ pci_device)) != NULL) {
+ struct blogic_adapter *adapter = adapter;
+ struct blogic_adapter_info adapter_info;
+ enum blogic_isa_ioport mod_ioaddr_req;
+ unsigned char bus;
+ unsigned char device;
+ unsigned int irq_ch;
+ unsigned long base_addr0;
+ unsigned long base_addr1;
+ unsigned long io_addr;
+ unsigned long pci_addr;
+
+ if (pci_enable_device(pci_device))
continue;
- if (pci_set_dma_mask(PCI_Device, DMA_BIT_MASK(32) ))
+ if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
continue;
- Bus = PCI_Device->bus->number;
- Device = PCI_Device->devfn >> 3;
- IRQ_Channel = PCI_Device->irq;
- IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
- PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+ bus = pci_device->bus->number;
+ device = pci_device->devfn >> 3;
+ irq_ch = pci_device->irq;
+ io_addr = base_addr0 = pci_resource_start(pci_device, 0);
+ pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
- if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
- BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0);
- BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+ if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
+ blogic_err("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, base_addr0);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
continue;
}
- if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
- BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1);
- BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
+ if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
+ blogic_err("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, base_addr1);
+ blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
continue;
}
- if (IRQ_Channel == 0) {
- BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
- BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+ if (irq_ch == 0) {
+ blogic_err("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, irq_ch);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
continue;
}
- if (BusLogic_GlobalOptions.TraceProbe) {
- BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
- BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
+ if (blogic_global_options.trace_probe) {
+ blogic_notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
+ blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
}
/*
Issue the Inquire PCI Host Adapter Information command to determine
@@ -701,238 +744,258 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
known and enabled, note that the particular Standard ISA I/O
Address should not be probed.
*/
- HostAdapter->IO_Address = IO_Address;
- BusLogic_InterruptReset(HostAdapter);
- if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
- == sizeof(PCIHostAdapterInformation)) {
- if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
- StandardAddressSeen[PCIHostAdapterInformation.ISACompatibleIOPort] = true;
+ adapter->io_addr = io_addr;
+ blogic_intreset(adapter);
+ if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
+ &adapter_info, sizeof(adapter_info)) ==
+ sizeof(adapter_info)) {
+ if (adapter_info.isa_port < 6)
+ addr_seen[adapter_info.isa_port] = true;
} else
- PCIHostAdapterInformation.ISACompatibleIOPort = BusLogic_IO_Disable;
+ adapter_info.isa_port = BLOGIC_IO_DISABLE;
/*
- * Issue the Modify I/O Address command to disable the ISA Compatible
- * I/O Port. On PCI Host Adapters, the Modify I/O Address command
- * allows modification of the ISA compatible I/O Address that the Host
- * Adapter responds to; it does not affect the PCI compliant I/O Address
- * assigned at system initialization.
+ Issue the Modify I/O Address command to disable the
+ ISA Compatible I/O Port. On PCI Host Adapters, the
+ Modify I/O Address command allows modification of the
+ ISA compatible I/O Address that the Host Adapter
+ responds to; it does not affect the PCI compliant
+ I/O Address assigned at system initialization.
*/
- ModifyIOAddressRequest = BusLogic_IO_Disable;
- BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, &ModifyIOAddressRequest, sizeof(ModifyIOAddressRequest), NULL, 0);
+ mod_ioaddr_req = BLOGIC_IO_DISABLE;
+ blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
+ sizeof(mod_ioaddr_req), NULL, 0);
/*
- For the first MultiMaster Host Adapter enumerated, issue the Fetch
- Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
- for the setting of the "Use Bus And Device # For PCI Scanning Seq."
- option. Issue the Inquire Board ID command since this option is
+ For the first MultiMaster Host Adapter enumerated,
+ issue the Fetch Host Adapter Local RAM command to read
+ byte 45 of the AutoSCSI area, for the setting of the
+ "Use Bus And Device # For PCI Scanning Seq." option.
+ Issue the Inquire Board ID command since this option is
only valid for the BT-948/958/958D.
*/
- if (!ForceBusDeviceScanningOrderChecked) {
- struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
- struct BusLogic_AutoSCSIByte45 AutoSCSIByte45;
- struct BusLogic_BoardID BoardID;
- FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset + 45;
- FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte45);
- BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIByte45, sizeof(AutoSCSIByte45));
- BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID));
- if (BoardID.FirmwareVersion1stDigit == '5')
- ForceBusDeviceScanningOrder = AutoSCSIByte45.ForceBusDeviceScanningOrder;
- ForceBusDeviceScanningOrderChecked = true;
+ if (!force_scan_order_checked) {
+ struct blogic_fetch_localram fetch_localram;
+ struct blogic_autoscsi_byte45 autoscsi_byte45;
+ struct blogic_board_id id;
+
+ fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
+ fetch_localram.count = sizeof(autoscsi_byte45);
+ blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM,
+ &fetch_localram, sizeof(fetch_localram),
+ &autoscsi_byte45,
+ sizeof(autoscsi_byte45));
+ blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
+ sizeof(id));
+ if (id.fw_ver_digit1 == '5')
+ force_scan_order =
+ autoscsi_byte45.force_scan_order;
+ force_scan_order_checked = true;
}
/*
- Determine whether this MultiMaster Host Adapter has its ISA
- Compatible I/O Port enabled and is assigned the Primary I/O Address.
- If it does, then it is the Primary MultiMaster Host Adapter and must
- be recognized first. If it does not, then it is added to the list
- for probing after any Primary MultiMaster Host Adapter is probed.
+ Determine whether this MultiMaster Host Adapter has its
+ ISA Compatible I/O Port enabled and is assigned the
+ Primary I/O Address. If it does, then it is the Primary
+ MultiMaster Host Adapter and must be recognized first.
+ If it does not, then it is added to the list for probing
+ after any Primary MultiMaster Host Adapter is probed.
*/
- if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) {
- PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
- PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
- PrimaryProbeInfo->IO_Address = IO_Address;
- PrimaryProbeInfo->PCI_Address = PCI_Address;
- PrimaryProbeInfo->Bus = Bus;
- PrimaryProbeInfo->Device = Device;
- PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
- PrimaryProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
- PCIMultiMasterCount++;
- } else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
- struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
- ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
- ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
- ProbeInfo->IO_Address = IO_Address;
- ProbeInfo->PCI_Address = PCI_Address;
- ProbeInfo->Bus = Bus;
- ProbeInfo->Device = Device;
- ProbeInfo->IRQ_Channel = IRQ_Channel;
- ProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
- NonPrimaryPCIMultiMasterCount++;
- PCIMultiMasterCount++;
+ if (adapter_info.isa_port == BLOGIC_IO_330) {
+ pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
+ pr_probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
+ pr_probeinfo->io_addr = io_addr;
+ pr_probeinfo->pci_addr = pci_addr;
+ pr_probeinfo->bus = bus;
+ pr_probeinfo->dev = device;
+ pr_probeinfo->irq_ch = irq_ch;
+ pr_probeinfo->pci_device = pci_dev_get(pci_device);
+ mmcount++;
+ } else if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
+ struct blogic_probeinfo *probeinfo =
+ &blogic_probeinfo_list[blogic_probeinfo_count++];
+ probeinfo->adapter_type = BLOGIC_MULTIMASTER;
+ probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
+ probeinfo->io_addr = io_addr;
+ probeinfo->pci_addr = pci_addr;
+ probeinfo->bus = bus;
+ probeinfo->dev = device;
+ probeinfo->irq_ch = irq_ch;
+ probeinfo->pci_device = pci_dev_get(pci_device);
+ nonpr_mmcount++;
+ mmcount++;
} else
- BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
- }
- /*
- If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
- for the first enumerated MultiMaster Host Adapter, and if that host adapter
- is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
- Host Adapters in the order of increasing PCI Bus and Device Number. In
- that case, sort the probe information into the same order the BIOS uses.
- If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
- Host Adapters in the order they are enumerated by the PCI BIOS, and hence
- no sorting is necessary.
- */
- if (ForceBusDeviceScanningOrder)
- BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[NonPrimaryPCIMultiMasterIndex], NonPrimaryPCIMultiMasterCount);
- /*
- If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
- then the Primary I/O Address must be probed explicitly before any PCI
- host adapters are probed.
- */
- if (!BusLogic_ProbeOptions.NoProbeISA)
- if (PrimaryProbeInfo->IO_Address == 0 &&
- (!BusLogic_ProbeOptions.LimitedProbeISA ||
- BusLogic_ProbeOptions.Probe330)) {
- PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
- PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
- PrimaryProbeInfo->IO_Address = 0x330;
+ blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
+ }
+ /*
+ If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq."
+ option is ON for the first enumerated MultiMaster Host Adapter,
+ and if that host adapter is a BT-948/958/958D, then the
+ MultiMaster BIOS will recognize MultiMaster Host Adapters in
+ the order of increasing PCI Bus and Device Number. In that case,
+ sort the probe information into the same order the BIOS uses.
+ If this option is OFF, then the MultiMaster BIOS will recognize
+ MultiMaster Host Adapters in the order they are enumerated by
+ the PCI BIOS, and hence no sorting is necessary.
+ */
+ if (force_scan_order)
+ blogic_sort_probeinfo(&blogic_probeinfo_list[nonpr_mmindex],
+ nonpr_mmcount);
+ /*
+ If no PCI MultiMaster Host Adapter is assigned the Primary
+ I/O Address, then the Primary I/O Address must be probed
+ explicitly before any PCI host adapters are probed.
+ */
+ if (!blogic_probe_options.noprobe_isa)
+ if (pr_probeinfo->io_addr == 0 &&
+ (!blogic_probe_options.limited_isa ||
+ blogic_probe_options.probe330)) {
+ pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
+ pr_probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
+ pr_probeinfo->io_addr = 0x330;
}
/*
Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
omitting the Primary I/O Address which has already been handled.
*/
- if (!BusLogic_ProbeOptions.NoProbeISA) {
- if (!StandardAddressSeen[1] &&
- (!BusLogic_ProbeOptions.LimitedProbeISA ||
- BusLogic_ProbeOptions.Probe334))
- BusLogic_AppendProbeAddressISA(0x334);
- if (!StandardAddressSeen[2] &&
- (!BusLogic_ProbeOptions.LimitedProbeISA ||
- BusLogic_ProbeOptions.Probe230))
- BusLogic_AppendProbeAddressISA(0x230);
- if (!StandardAddressSeen[3] &&
- (!BusLogic_ProbeOptions.LimitedProbeISA ||
- BusLogic_ProbeOptions.Probe234))
- BusLogic_AppendProbeAddressISA(0x234);
- if (!StandardAddressSeen[4] &&
- (!BusLogic_ProbeOptions.LimitedProbeISA ||
- BusLogic_ProbeOptions.Probe130))
- BusLogic_AppendProbeAddressISA(0x130);
- if (!StandardAddressSeen[5] &&
- (!BusLogic_ProbeOptions.LimitedProbeISA ||
- BusLogic_ProbeOptions.Probe134))
- BusLogic_AppendProbeAddressISA(0x134);
+ if (!blogic_probe_options.noprobe_isa) {
+ if (!addr_seen[1] &&
+ (!blogic_probe_options.limited_isa ||
+ blogic_probe_options.probe334))
+ blogic_add_probeaddr_isa(0x334);
+ if (!addr_seen[2] &&
+ (!blogic_probe_options.limited_isa ||
+ blogic_probe_options.probe230))
+ blogic_add_probeaddr_isa(0x230);
+ if (!addr_seen[3] &&
+ (!blogic_probe_options.limited_isa ||
+ blogic_probe_options.probe234))
+ blogic_add_probeaddr_isa(0x234);
+ if (!addr_seen[4] &&
+ (!blogic_probe_options.limited_isa ||
+ blogic_probe_options.probe130))
+ blogic_add_probeaddr_isa(0x130);
+ if (!addr_seen[5] &&
+ (!blogic_probe_options.limited_isa ||
+ blogic_probe_options.probe134))
+ blogic_add_probeaddr_isa(0x134);
}
/*
Iterate over the older non-compliant MultiMaster PCI Host Adapters,
noting the PCI bus location and assigned IRQ Channel.
*/
- PCI_Device = NULL;
- while ((PCI_Device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, PCI_Device)) != NULL) {
- unsigned char Bus;
- unsigned char Device;
- unsigned int IRQ_Channel;
- unsigned long IO_Address;
+ pci_device = NULL;
+ while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
+ PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
+ pci_device)) != NULL) {
+ unsigned char bus;
+ unsigned char device;
+ unsigned int irq_ch;
+ unsigned long io_addr;
- if (pci_enable_device(PCI_Device))
+ if (pci_enable_device(pci_device))
continue;
- if (pci_set_dma_mask(PCI_Device, DMA_BIT_MASK(32)))
+ if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
continue;
- Bus = PCI_Device->bus->number;
- Device = PCI_Device->devfn >> 3;
- IRQ_Channel = PCI_Device->irq;
- IO_Address = pci_resource_start(PCI_Device, 0);
+ bus = pci_device->bus->number;
+ device = pci_device->devfn >> 3;
+ irq_ch = pci_device->irq;
+ io_addr = pci_resource_start(pci_device, 0);
- if (IO_Address == 0 || IRQ_Channel == 0)
+ if (io_addr == 0 || irq_ch == 0)
continue;
- for (i = 0; i < BusLogic_ProbeInfoCount; i++) {
- struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i];
- if (ProbeInfo->IO_Address == IO_Address && ProbeInfo->HostAdapterType == BusLogic_MultiMaster) {
- ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
- ProbeInfo->PCI_Address = 0;
- ProbeInfo->Bus = Bus;
- ProbeInfo->Device = Device;
- ProbeInfo->IRQ_Channel = IRQ_Channel;
- ProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
+ for (i = 0; i < blogic_probeinfo_count; i++) {
+ struct blogic_probeinfo *probeinfo =
+ &blogic_probeinfo_list[i];
+ if (probeinfo->io_addr == io_addr &&
+ probeinfo->adapter_type == BLOGIC_MULTIMASTER) {
+ probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
+ probeinfo->pci_addr = 0;
+ probeinfo->bus = bus;
+ probeinfo->dev = device;
+ probeinfo->irq_ch = irq_ch;
+ probeinfo->pci_device = pci_dev_get(pci_device);
break;
}
}
}
- return PCIMultiMasterCount;
+ return mmcount;
}
/*
- BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address
+ blogic_init_fp_probeinfo initializes the list of I/O Address
and Bus Probe Information to be checked for potential BusLogic FlashPoint
Host Adapters by interrogating the PCI Configuration Space. It returns the
number of FlashPoint Host Adapters found.
*/
-static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAdapter
- *PrototypeHostAdapter)
+static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter)
{
- int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
- struct pci_dev *PCI_Device = NULL;
+ int fpindex = blogic_probeinfo_count, fpcount = 0;
+ struct pci_dev *pci_device = NULL;
/*
Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
*/
- while ((PCI_Device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, PCI_Device)) != NULL) {
- unsigned char Bus;
- unsigned char Device;
- unsigned int IRQ_Channel;
- unsigned long BaseAddress0;
- unsigned long BaseAddress1;
- unsigned long IO_Address;
- unsigned long PCI_Address;
-
- if (pci_enable_device(PCI_Device))
+ while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
+ PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
+ pci_device)) != NULL) {
+ unsigned char bus;
+ unsigned char device;
+ unsigned int irq_ch;
+ unsigned long base_addr0;
+ unsigned long base_addr1;
+ unsigned long io_addr;
+ unsigned long pci_addr;
+
+ if (pci_enable_device(pci_device))
continue;
- if (pci_set_dma_mask(PCI_Device, DMA_BIT_MASK(32)))
+ if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
continue;
- Bus = PCI_Device->bus->number;
- Device = PCI_Device->devfn >> 3;
- IRQ_Channel = PCI_Device->irq;
- IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
- PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+ bus = pci_device->bus->number;
+ device = pci_device->devfn >> 3;
+ irq_ch = pci_device->irq;
+ io_addr = base_addr0 = pci_resource_start(pci_device, 0);
+ pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
#ifdef CONFIG_SCSI_FLASHPOINT
- if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
- BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
- BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+ if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
+ blogic_err("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, base_addr0);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
continue;
}
- if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
- BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1);
- BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
+ if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
+ blogic_err("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, base_addr1);
+ blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
continue;
}
- if (IRQ_Channel == 0) {
- BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
- BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+ if (irq_ch == 0) {
+ blogic_err("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, irq_ch);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
continue;
}
- if (BusLogic_GlobalOptions.TraceProbe) {
- BusLogic_Notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
- BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
+ if (blogic_global_options.trace_probe) {
+ blogic_notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
+ blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
}
- if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
- struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
- ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
- ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
- ProbeInfo->IO_Address = IO_Address;
- ProbeInfo->PCI_Address = PCI_Address;
- ProbeInfo->Bus = Bus;
- ProbeInfo->Device = Device;
- ProbeInfo->IRQ_Channel = IRQ_Channel;
- ProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
- FlashPointCount++;
+ if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
+ struct blogic_probeinfo *probeinfo =
+ &blogic_probeinfo_list[blogic_probeinfo_count++];
+ probeinfo->adapter_type = BLOGIC_FLASHPOINT;
+ probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
+ probeinfo->io_addr = io_addr;
+ probeinfo->pci_addr = pci_addr;
+ probeinfo->bus = bus;
+ probeinfo->dev = device;
+ probeinfo->irq_ch = irq_ch;
+ probeinfo->pci_device = pci_dev_get(pci_device);
+ fpcount++;
} else
- BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
+ blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
#else
- BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, Bus, Device);
- BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel);
- BusLogic_Error("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
+ blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, bus, device);
+ blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
+ blogic_err("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
#endif
}
/*
@@ -940,13 +1003,13 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
increasing PCI Bus and Device Number, so sort the probe information into
the same order the BIOS uses.
*/
- BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], FlashPointCount);
- return FlashPointCount;
+ blogic_sort_probeinfo(&blogic_probeinfo_list[fpindex], fpcount);
+ return fpcount;
}
/*
- BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus
+ blogic_init_probeinfo_list initializes the list of I/O Address and Bus
Probe Information to be checked for potential BusLogic SCSI Host Adapters by
interrogating the PCI Configuration Space on PCI machines as well as from the
list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both
@@ -958,104 +1021,125 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
a particular probe order.
*/
-static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
- *PrototypeHostAdapter)
+static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter)
{
/*
- If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
- Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
- */
- if (!BusLogic_ProbeOptions.NoProbePCI) {
- if (BusLogic_ProbeOptions.MultiMasterFirst) {
- BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
- BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
- } else if (BusLogic_ProbeOptions.FlashPointFirst) {
- BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
- BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+ If a PCI BIOS is present, interrogate it for MultiMaster and
+ FlashPoint Host Adapters; otherwise, default to the standard
+ ISA MultiMaster probe.
+ */
+ if (!blogic_probe_options.noprobe_pci) {
+ if (blogic_probe_options.multimaster_first) {
+ blogic_init_mm_probeinfo(adapter);
+ blogic_init_fp_probeinfo(adapter);
+ } else if (blogic_probe_options.flashpoint_first) {
+ blogic_init_fp_probeinfo(adapter);
+ blogic_init_mm_probeinfo(adapter);
} else {
- int FlashPointCount = BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
- int PCIMultiMasterCount = BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
- if (FlashPointCount > 0 && PCIMultiMasterCount > 0) {
- struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[FlashPointCount];
- struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
- struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
- struct BusLogic_BIOSDriveMapByte Drive0MapByte;
- while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
- ProbeInfo++;
- HostAdapter->IO_Address = ProbeInfo->IO_Address;
- FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
- FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(Drive0MapByte);
- BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &Drive0MapByte, sizeof(Drive0MapByte));
+ int fpcount = blogic_init_fp_probeinfo(adapter);
+ int mmcount = blogic_init_mm_probeinfo(adapter);
+ if (fpcount > 0 && mmcount > 0) {
+ struct blogic_probeinfo *probeinfo =
+ &blogic_probeinfo_list[fpcount];
+ struct blogic_adapter *myadapter = adapter;
+ struct blogic_fetch_localram fetch_localram;
+ struct blogic_bios_drvmap d0_mapbyte;
+
+ while (probeinfo->adapter_bus_type !=
+ BLOGIC_PCI_BUS)
+ probeinfo++;
+ myadapter->io_addr = probeinfo->io_addr;
+ fetch_localram.offset =
+ BLOGIC_BIOS_BASE + BLOGIC_BIOS_DRVMAP;
+ fetch_localram.count = sizeof(d0_mapbyte);
+ blogic_cmd(myadapter, BLOGIC_FETCH_LOCALRAM,
+ &fetch_localram,
+ sizeof(fetch_localram),
+ &d0_mapbyte,
+ sizeof(d0_mapbyte));
/*
- If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
- is controlled by this PCI MultiMaster Host Adapter, then
- reverse the probe order so that MultiMaster Host Adapters are
- probed before FlashPoint Host Adapters.
+ If the Map Byte for BIOS Drive 0 indicates
+ that BIOS Drive 0 is controlled by this
+ PCI MultiMaster Host Adapter, then reverse
+ the probe order so that MultiMaster Host
+ Adapters are probed before FlashPoint Host
+ Adapters.
*/
- if (Drive0MapByte.DiskGeometry != BusLogic_BIOS_Disk_Not_Installed) {
- struct BusLogic_ProbeInfo SavedProbeInfo[BusLogic_MaxHostAdapters];
- int MultiMasterCount = BusLogic_ProbeInfoCount - FlashPointCount;
- memcpy(SavedProbeInfo, BusLogic_ProbeInfoList, BusLogic_ProbeInfoCount * sizeof(struct BusLogic_ProbeInfo));
- memcpy(&BusLogic_ProbeInfoList[0], &SavedProbeInfo[FlashPointCount], MultiMasterCount * sizeof(struct BusLogic_ProbeInfo));
- memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], &SavedProbeInfo[0], FlashPointCount * sizeof(struct BusLogic_ProbeInfo));
+ if (d0_mapbyte.diskgeom != BLOGIC_BIOS_NODISK) {
+ struct blogic_probeinfo saved_probeinfo[BLOGIC_MAX_ADAPTERS];
+ int mmcount = blogic_probeinfo_count - fpcount;
+
+ memcpy(saved_probeinfo,
+ blogic_probeinfo_list,
+ blogic_probeinfo_count * sizeof(struct blogic_probeinfo));
+ memcpy(&blogic_probeinfo_list[0],
+ &saved_probeinfo[fpcount],
+ mmcount * sizeof(struct blogic_probeinfo));
+ memcpy(&blogic_probeinfo_list[mmcount],
+ &saved_probeinfo[0],
+ fpcount * sizeof(struct blogic_probeinfo));
}
}
}
- } else
- BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
+ } else {
+ blogic_init_probeinfo_isa(adapter);
+ }
}
#else
-#define BusLogic_InitializeProbeInfoList(adapter) \
- BusLogic_InitializeProbeInfoListISA(adapter)
+#define blogic_init_probeinfo_list(adapter) \
+ blogic_init_probeinfo_isa(adapter)
#endif /* CONFIG_PCI */
/*
- BusLogic_Failure prints a standardized error message, and then returns false.
+ blogic_failure prints a standardized error message, and then returns false.
*/
-static bool BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
+static bool blogic_failure(struct blogic_adapter *adapter, char *msg)
{
- BusLogic_AnnounceDriver(HostAdapter);
- if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) {
- BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", HostAdapter);
- BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device, HostAdapter->IO_Address, HostAdapter->PCI_Address);
+ blogic_announce_drvr(adapter);
+ if (adapter->adapter_bus_type == BLOGIC_PCI_BUS) {
+ blogic_err("While configuring BusLogic PCI Host Adapter at\n",
+ adapter);
+ blogic_err("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", adapter, adapter->bus, adapter->dev, adapter->io_addr, adapter->pci_addr);
} else
- BusLogic_Error("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", HostAdapter, HostAdapter->IO_Address);
- BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
- if (BusLogic_CommandFailureReason != NULL)
- BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, BusLogic_CommandFailureReason);
+ blogic_err("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", adapter, adapter->io_addr);
+ blogic_err("%s FAILED - DETACHING\n", adapter, msg);
+ if (blogic_cmd_failure_reason != NULL)
+ blogic_err("ADDITIONAL FAILURE INFO - %s\n", adapter,
+ blogic_cmd_failure_reason);
return false;
}
/*
- BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
+ blogic_probe probes for a BusLogic Host Adapter.
*/
-static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init blogic_probe(struct blogic_adapter *adapter)
{
- union BusLogic_StatusRegister StatusRegister;
- union BusLogic_InterruptRegister InterruptRegister;
- union BusLogic_GeometryRegister GeometryRegister;
+ union blogic_stat_reg statusreg;
+ union blogic_int_reg intreg;
+ union blogic_geo_reg georeg;
/*
FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
*/
- if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
- struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
- FlashPointInfo->BaseAddress = (u32) HostAdapter->IO_Address;
- FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
- FlashPointInfo->Present = false;
- if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && FlashPointInfo->Present)) {
- BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
- BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", HostAdapter, HostAdapter->IO_Address, HostAdapter->PCI_Address);
- BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", HostAdapter);
+ if (blogic_flashpoint_type(adapter)) {
+ struct fpoint_info *fpinfo = &adapter->fpinfo;
+ fpinfo->base_addr = (u32) adapter->io_addr;
+ fpinfo->irq_ch = adapter->irq_ch;
+ fpinfo->present = false;
+ if (!(FlashPoint_ProbeHostAdapter(fpinfo) == 0 &&
+ fpinfo->present)) {
+ blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
+ blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
+ blogic_err("BusLogic: Probe Function failed to validate it.\n", adapter);
return false;
}
- if (BusLogic_GlobalOptions.TraceProbe)
- BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", HostAdapter, HostAdapter->IO_Address);
+ if (blogic_global_options.trace_probe)
+ blogic_notice("BusLogic_Probe(0x%X): FlashPoint Found\n", adapter, adapter->io_addr);
/*
Indicate the Host Adapter Probe completed successfully.
*/
@@ -1068,28 +1152,32 @@ static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAd
case there is definitely no BusLogic Host Adapter at this base I/O Address.
The test here is a subset of that used by the BusLogic Host Adapter BIOS.
*/
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
- GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
- if (BusLogic_GlobalOptions.TraceProbe)
- BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All, InterruptRegister.All, GeometryRegister.All);
- if (StatusRegister.All == 0 || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.CommandParameterRegisterBusy || StatusRegister.sr.Reserved || StatusRegister.sr.CommandInvalid || InterruptRegister.ir.Reserved != 0)
+ statusreg.all = blogic_rdstatus(adapter);
+ intreg.all = blogic_rdint(adapter);
+ georeg.all = blogic_rdgeom(adapter);
+ if (blogic_global_options.trace_probe)
+ blogic_notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", adapter, adapter->io_addr, statusreg.all, intreg.all, georeg.all);
+ if (statusreg.all == 0 || statusreg.sr.diag_active ||
+ statusreg.sr.cmd_param_busy || statusreg.sr.rsvd ||
+ statusreg.sr.cmd_invalid || intreg.ir.rsvd != 0)
return false;
/*
- Check the undocumented Geometry Register to test if there is an I/O port
- that responded. Adaptec Host Adapters do not implement the Geometry
- Register, so this test helps serve to avoid incorrectly recognizing an
- Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C
- series does respond to the Geometry Register I/O port, but it will be
- rejected later when the Inquire Extended Setup Information command is
- issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a
- BusLogic clone that implements the same interface as earlier BusLogic
- Host Adapters, including the undocumented commands, and is therefore
- supported by this driver. However, the AMI FastDisk always returns 0x00
- upon reading the Geometry Register, so the extended translation option
- should always be left disabled on the AMI FastDisk.
- */
- if (GeometryRegister.All == 0xFF)
+ Check the undocumented Geometry Register to test if there is
+ an I/O port that responded. Adaptec Host Adapters do not
+ implement the Geometry Register, so this test helps serve to
+ avoid incorrectly recognizing an Adaptec 1542A or 1542B as a
+ BusLogic. Unfortunately, the Adaptec 1542C series does respond
+ to the Geometry Register I/O port, but it will be rejected
+ later when the Inquire Extended Setup Information command is
+ issued in blogic_checkadapter. The AMI FastDisk Host Adapter
+ is a BusLogic clone that implements the same interface as
+ earlier BusLogic Host Adapters, including the undocumented
+ commands, and is therefore supported by this driver. However,
+ the AMI FastDisk always returns 0x00 upon reading the Geometry
+ Register, so the extended translation option should always be
+ left disabled on the AMI FastDisk.
+ */
+ if (georeg.all == 0xFF)
return false;
/*
Indicate the Host Adapter Probe completed successfully.
@@ -1099,27 +1187,28 @@ static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAd
/*
- BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter
- and waits for Host Adapter Diagnostics to complete. If HardReset is true, a
+ blogic_hwreset issues a Hardware Reset to the Host Adapter
+ and waits for Host Adapter Diagnostics to complete. If hard_reset is true, a
Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a
Soft Reset is performed which only resets the Host Adapter without forcing a
SCSI Bus Reset.
*/
-static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
- *HostAdapter, bool HardReset)
+static bool blogic_hwreset(struct blogic_adapter *adapter, bool hard_reset)
{
- union BusLogic_StatusRegister StatusRegister;
- int TimeoutCounter;
+ union blogic_stat_reg statusreg;
+ int timeout;
/*
- FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
+ FlashPoint Host Adapters are Hard Reset by the FlashPoint
+ SCCB Manager.
*/
- if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
- struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
- FlashPointInfo->HostSoftReset = !HardReset;
- FlashPointInfo->ReportDataUnderrun = true;
- HostAdapter->CardHandle = FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
- if (HostAdapter->CardHandle == FlashPoint_BadCardHandle)
+ if (blogic_flashpoint_type(adapter)) {
+ struct fpoint_info *fpinfo = &adapter->fpinfo;
+ fpinfo->softreset = !hard_reset;
+ fpinfo->report_underrun = true;
+ adapter->cardhandle =
+ FlashPoint_HardwareResetHostAdapter(fpinfo);
+ if (adapter->cardhandle == (void *)FPOINT_BADCARD_HANDLE)
return false;
/*
Indicate the Host Adapter Hard Reset completed successfully.
@@ -1127,26 +1216,27 @@ static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
return true;
}
/*
- Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host
- Adapter should respond by setting Diagnostic Active in the Status Register.
+ Issue a Hard Reset or Soft Reset Command to the Host Adapter.
+ The Host Adapter should respond by setting Diagnostic Active in
+ the Status Register.
*/
- if (HardReset)
- BusLogic_HardReset(HostAdapter);
+ if (hard_reset)
+ blogic_hardreset(adapter);
else
- BusLogic_SoftReset(HostAdapter);
+ blogic_softreset(adapter);
/*
Wait until Diagnostic Active is set in the Status Register.
*/
- TimeoutCounter = 5 * 10000;
- while (--TimeoutCounter >= 0) {
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (StatusRegister.sr.DiagnosticActive)
+ timeout = 5 * 10000;
+ while (--timeout >= 0) {
+ statusreg.all = blogic_rdstatus(adapter);
+ if (statusreg.sr.diag_active)
break;
udelay(100);
}
- if (BusLogic_GlobalOptions.TraceHardwareReset)
- BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
- if (TimeoutCounter < 0)
+ if (blogic_global_options.trace_hw_reset)
+ blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
+ if (timeout < 0)
return false;
/*
Wait 100 microseconds to allow completion of any initial diagnostic
@@ -1157,45 +1247,47 @@ static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
/*
Wait until Diagnostic Active is reset in the Status Register.
*/
- TimeoutCounter = 10 * 10000;
- while (--TimeoutCounter >= 0) {
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (!StatusRegister.sr.DiagnosticActive)
+ timeout = 10 * 10000;
+ while (--timeout >= 0) {
+ statusreg.all = blogic_rdstatus(adapter);
+ if (!statusreg.sr.diag_active)
break;
udelay(100);
}
- if (BusLogic_GlobalOptions.TraceHardwareReset)
- BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
- if (TimeoutCounter < 0)
+ if (blogic_global_options.trace_hw_reset)
+ blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
+ if (timeout < 0)
return false;
/*
- Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
- or Data In Register Ready bits is set in the Status Register.
+ Wait until at least one of the Diagnostic Failure, Host Adapter
+ Ready, or Data In Register Ready bits is set in the Status Register.
*/
- TimeoutCounter = 10000;
- while (--TimeoutCounter >= 0) {
- StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
- if (StatusRegister.sr.DiagnosticFailure || StatusRegister.sr.HostAdapterReady || StatusRegister.sr.DataInRegisterReady)
+ timeout = 10000;
+ while (--timeout >= 0) {
+ statusreg.all = blogic_rdstatus(adapter);
+ if (statusreg.sr.diag_failed || statusreg.sr.adapter_ready ||
+ statusreg.sr.datain_ready)
break;
udelay(100);
}
- if (BusLogic_GlobalOptions.TraceHardwareReset)
- BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
- if (TimeoutCounter < 0)
+ if (blogic_global_options.trace_hw_reset)
+ blogic_notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
+ if (timeout < 0)
return false;
/*
- If Diagnostic Failure is set or Host Adapter Ready is reset, then an
- error occurred during the Host Adapter diagnostics. If Data In Register
- Ready is set, then there is an Error Code available.
- */
- if (StatusRegister.sr.DiagnosticFailure || !StatusRegister.sr.HostAdapterReady) {
- BusLogic_CommandFailureReason = NULL;
- BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
- BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", HostAdapter, StatusRegister.All);
- if (StatusRegister.sr.DataInRegisterReady) {
- unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
- BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", HostAdapter, ErrorCode);
- }
+ If Diagnostic Failure is set or Host Adapter Ready is reset,
+ then an error occurred during the Host Adapter diagnostics.
+ If Data In Register Ready is set, then there is an Error Code
+ available.
+ */
+ if (statusreg.sr.diag_failed || !statusreg.sr.adapter_ready) {
+ blogic_cmd_failure_reason = NULL;
+ blogic_failure(adapter, "HARD RESET DIAGNOSTICS");
+ blogic_err("HOST ADAPTER STATUS REGISTER = %02X\n", adapter,
+ statusreg.all);
+ if (statusreg.sr.datain_ready)
+ blogic_err("HOST ADAPTER ERROR CODE = %d\n", adapter,
+ blogic_rddatain(adapter));
return false;
}
/*
@@ -1206,161 +1298,175 @@ static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
/*
- BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
+ blogic_checkadapter checks to be sure this really is a BusLogic
Host Adapter.
*/
-static bool __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init blogic_checkadapter(struct blogic_adapter *adapter)
{
- struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
- unsigned char RequestedReplyLength;
- bool Result = true;
+ struct blogic_ext_setup ext_setupinfo;
+ unsigned char req_replylen;
+ bool result = true;
/*
FlashPoint Host Adapters do not require this protection.
*/
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+ if (blogic_flashpoint_type(adapter))
return true;
/*
- Issue the Inquire Extended Setup Information command. Only genuine
- BusLogic Host Adapters and true clones support this command. Adaptec 1542C
- series Host Adapters that respond to the Geometry Register I/O port will
- fail this command.
+ Issue the Inquire Extended Setup Information command. Only genuine
+ BusLogic Host Adapters and true clones support this command.
+ Adaptec 1542C series Host Adapters that respond to the Geometry
+ Register I/O port will fail this command.
*/
- RequestedReplyLength = sizeof(ExtendedSetupInformation);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
- != sizeof(ExtendedSetupInformation))
- Result = false;
+ req_replylen = sizeof(ext_setupinfo);
+ if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
+ sizeof(req_replylen), &ext_setupinfo,
+ sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
+ result = false;
/*
Provide tracing information if requested and return.
*/
- if (BusLogic_GlobalOptions.TraceProbe)
- BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
- return Result;
+ if (blogic_global_options.trace_probe)
+ blogic_notice("BusLogic_Check(0x%X): MultiMaster %s\n", adapter,
+ adapter->io_addr,
+ (result ? "Found" : "Not Found"));
+ return result;
}
/*
- BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
+ blogic_rdconfig reads the Configuration Information
from Host Adapter and initializes the Host Adapter structure.
*/
-static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
- *HostAdapter)
+static bool __init blogic_rdconfig(struct blogic_adapter *adapter)
{
- struct BusLogic_BoardID BoardID;
- struct BusLogic_Configuration Configuration;
- struct BusLogic_SetupInformation SetupInformation;
- struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
- unsigned char HostAdapterModelNumber[5];
- unsigned char FirmwareVersion3rdDigit;
- unsigned char FirmwareVersionLetter;
- struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
- struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
- struct BusLogic_AutoSCSIData AutoSCSIData;
- union BusLogic_GeometryRegister GeometryRegister;
- unsigned char RequestedReplyLength;
- unsigned char *TargetPointer, Character;
- int TargetID, i;
- /*
- Configuration Information for FlashPoint Host Adapters is provided in the
- FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
- Initialize fields in the Host Adapter structure from the FlashPoint_Info
- structure.
- */
- if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
- struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
- TargetPointer = HostAdapter->ModelName;
- *TargetPointer++ = 'B';
- *TargetPointer++ = 'T';
- *TargetPointer++ = '-';
- for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
- *TargetPointer++ = FlashPointInfo->ModelNumber[i];
- *TargetPointer++ = '\0';
- strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
- HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
- HostAdapter->ExtendedTranslationEnabled = FlashPointInfo->ExtendedTranslationEnabled;
- HostAdapter->ParityCheckingEnabled = FlashPointInfo->ParityCheckingEnabled;
- HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
- HostAdapter->LevelSensitiveInterrupt = true;
- HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
- HostAdapter->HostDifferentialSCSI = false;
- HostAdapter->HostSupportsSCAM = true;
- HostAdapter->HostUltraSCSI = true;
- HostAdapter->ExtendedLUNSupport = true;
- HostAdapter->TerminationInfoValid = true;
- HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
- HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
- HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
- HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
- HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
- HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
- HostAdapter->MaxLogicalUnits = 32;
- HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
- HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
- HostAdapter->DriverQueueDepth = 255;
- HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
- HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
- HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
- HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
- HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
- HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
- HostAdapter->TaggedQueuingPermitted = 0xFFFF;
- goto Common;
+ struct blogic_board_id id;
+ struct blogic_config config;
+ struct blogic_setup_info setupinfo;
+ struct blogic_ext_setup ext_setupinfo;
+ unsigned char model[5];
+ unsigned char fw_ver_digit3;
+ unsigned char fw_ver_letter;
+ struct blogic_adapter_info adapter_info;
+ struct blogic_fetch_localram fetch_localram;
+ struct blogic_autoscsi autoscsi;
+ union blogic_geo_reg georeg;
+ unsigned char req_replylen;
+ unsigned char *tgt, ch;
+ int tgt_id, i;
+ /*
+ Configuration Information for FlashPoint Host Adapters is
+ provided in the fpoint_info structure by the FlashPoint
+ SCCB Manager's Probe Function. Initialize fields in the
+ Host Adapter structure from the fpoint_info structure.
+ */
+ if (blogic_flashpoint_type(adapter)) {
+ struct fpoint_info *fpinfo = &adapter->fpinfo;
+ tgt = adapter->model;
+ *tgt++ = 'B';
+ *tgt++ = 'T';
+ *tgt++ = '-';
+ for (i = 0; i < sizeof(fpinfo->model); i++)
+ *tgt++ = fpinfo->model[i];
+ *tgt++ = '\0';
+ strcpy(adapter->fw_ver, FLASHPOINT_FW_VER);
+ adapter->scsi_id = fpinfo->scsi_id;
+ adapter->ext_trans_enable = fpinfo->ext_trans_enable;
+ adapter->parity = fpinfo->parity;
+ adapter->reset_enabled = !fpinfo->softreset;
+ adapter->level_int = true;
+ adapter->wide = fpinfo->wide;
+ adapter->differential = false;
+ adapter->scam = true;
+ adapter->ultra = true;
+ adapter->ext_lun = true;
+ adapter->terminfo_valid = true;
+ adapter->low_term = fpinfo->low_term;
+ adapter->high_term = fpinfo->high_term;
+ adapter->scam_enabled = fpinfo->scam_enabled;
+ adapter->scam_lev2 = fpinfo->scam_lev2;
+ adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
+ adapter->maxdev = (adapter->wide ? 16 : 8);
+ adapter->maxlun = 32;
+ adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
+ adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
+ adapter->drvr_qdepth = 255;
+ adapter->adapter_qdepth = adapter->drvr_qdepth;
+ adapter->sync_ok = fpinfo->sync_ok;
+ adapter->fast_ok = fpinfo->fast_ok;
+ adapter->ultra_ok = fpinfo->ultra_ok;
+ adapter->wide_ok = fpinfo->wide_ok;
+ adapter->discon_ok = fpinfo->discon_ok;
+ adapter->tagq_ok = 0xFFFF;
+ goto common;
}
/*
Issue the Inquire Board ID command.
*/
- if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID)) != sizeof(BoardID))
- return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
+ if (blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
+ sizeof(id)) != sizeof(id))
+ return blogic_failure(adapter, "INQUIRE BOARD ID");
/*
Issue the Inquire Configuration command.
*/
- if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, &Configuration, sizeof(Configuration))
- != sizeof(Configuration))
- return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
+ if (blogic_cmd(adapter, BLOGIC_INQ_CONFIG, NULL, 0, &config,
+ sizeof(config))
+ != sizeof(config))
+ return blogic_failure(adapter, "INQUIRE CONFIGURATION");
/*
Issue the Inquire Setup Information command.
*/
- RequestedReplyLength = sizeof(SetupInformation);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
- != sizeof(SetupInformation))
- return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
+ req_replylen = sizeof(setupinfo);
+ if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
+ sizeof(req_replylen), &setupinfo,
+ sizeof(setupinfo)) != sizeof(setupinfo))
+ return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
/*
Issue the Inquire Extended Setup Information command.
*/
- RequestedReplyLength = sizeof(ExtendedSetupInformation);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
- != sizeof(ExtendedSetupInformation))
- return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
+ req_replylen = sizeof(ext_setupinfo);
+ if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
+ sizeof(req_replylen), &ext_setupinfo,
+ sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
+ return blogic_failure(adapter,
+ "INQUIRE EXTENDED SETUP INFORMATION");
/*
Issue the Inquire Firmware Version 3rd Digit command.
*/
- FirmwareVersion3rdDigit = '\0';
- if (BoardID.FirmwareVersion1stDigit > '0')
- if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, NULL, 0, &FirmwareVersion3rdDigit, sizeof(FirmwareVersion3rdDigit))
- != sizeof(FirmwareVersion3rdDigit))
- return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
+ fw_ver_digit3 = '\0';
+ if (id.fw_ver_digit1 > '0')
+ if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_D3, NULL, 0,
+ &fw_ver_digit3,
+ sizeof(fw_ver_digit3)) != sizeof(fw_ver_digit3))
+ return blogic_failure(adapter,
+ "INQUIRE FIRMWARE 3RD DIGIT");
/*
Issue the Inquire Host Adapter Model Number command.
*/
- if (ExtendedSetupInformation.BusType == 'A' && BoardID.FirmwareVersion1stDigit == '2')
+ if (ext_setupinfo.bus_type == 'A' && id.fw_ver_digit1 == '2')
/* BusLogic BT-542B ISA 2.xx */
- strcpy(HostAdapterModelNumber, "542B");
- else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '2' && (BoardID.FirmwareVersion2ndDigit <= '1' || (BoardID.FirmwareVersion2ndDigit == '2' && FirmwareVersion3rdDigit == '0')))
+ strcpy(model, "542B");
+ else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '2' &&
+ (id.fw_ver_digit2 <= '1' || (id.fw_ver_digit2 == '2' &&
+ fw_ver_digit3 == '0')))
/* BusLogic BT-742A EISA 2.1x or 2.20 */
- strcpy(HostAdapterModelNumber, "742A");
- else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '0')
+ strcpy(model, "742A");
+ else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '0')
/* AMI FastDisk EISA Series 441 0.x */
- strcpy(HostAdapterModelNumber, "747A");
+ strcpy(model, "747A");
else {
- RequestedReplyLength = sizeof(HostAdapterModelNumber);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, &RequestedReplyLength, sizeof(RequestedReplyLength), &HostAdapterModelNumber, sizeof(HostAdapterModelNumber))
- != sizeof(HostAdapterModelNumber))
- return BusLogic_Failure(HostAdapter, "INQUIRE HOST ADAPTER MODEL NUMBER");
+ req_replylen = sizeof(model);
+ if (blogic_cmd(adapter, BLOGIC_INQ_MODELNO, &req_replylen,
+ sizeof(req_replylen), &model,
+ sizeof(model)) != sizeof(model))
+ return blogic_failure(adapter,
+ "INQUIRE HOST ADAPTER MODEL NUMBER");
}
/*
- BusLogic MultiMaster Host Adapters can be identified by their model number
- and the major version number of their firmware as follows:
+ BusLogic MultiMaster Host Adapters can be identified by their
+ model number and the major version number of their firmware
+ as follows:
5.xx BusLogic "W" Series Host Adapters:
BT-948/958/958D
@@ -1374,497 +1480,535 @@ static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAda
0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
*/
/*
- Save the Model Name and Host Adapter Name in the Host Adapter structure.
+ Save the Model Name and Host Adapter Name in the Host Adapter
+ structure.
*/
- TargetPointer = HostAdapter->ModelName;
- *TargetPointer++ = 'B';
- *TargetPointer++ = 'T';
- *TargetPointer++ = '-';
- for (i = 0; i < sizeof(HostAdapterModelNumber); i++) {
- Character = HostAdapterModelNumber[i];
- if (Character == ' ' || Character == '\0')
+ tgt = adapter->model;
+ *tgt++ = 'B';
+ *tgt++ = 'T';
+ *tgt++ = '-';
+ for (i = 0; i < sizeof(model); i++) {
+ ch = model[i];
+ if (ch == ' ' || ch == '\0')
break;
- *TargetPointer++ = Character;
+ *tgt++ = ch;
}
- *TargetPointer++ = '\0';
+ *tgt++ = '\0';
/*
Save the Firmware Version in the Host Adapter structure.
*/
- TargetPointer = HostAdapter->FirmwareVersion;
- *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
- *TargetPointer++ = '.';
- *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
- if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
- *TargetPointer++ = FirmwareVersion3rdDigit;
- *TargetPointer = '\0';
+ tgt = adapter->fw_ver;
+ *tgt++ = id.fw_ver_digit1;
+ *tgt++ = '.';
+ *tgt++ = id.fw_ver_digit2;
+ if (fw_ver_digit3 != ' ' && fw_ver_digit3 != '\0')
+ *tgt++ = fw_ver_digit3;
+ *tgt = '\0';
/*
Issue the Inquire Firmware Version Letter command.
*/
- if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) {
- if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, NULL, 0, &FirmwareVersionLetter, sizeof(FirmwareVersionLetter))
- != sizeof(FirmwareVersionLetter))
- return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER");
- if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
- *TargetPointer++ = FirmwareVersionLetter;
- *TargetPointer = '\0';
+ if (strcmp(adapter->fw_ver, "3.3") >= 0) {
+ if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_LETTER, NULL, 0,
+ &fw_ver_letter,
+ sizeof(fw_ver_letter)) != sizeof(fw_ver_letter))
+ return blogic_failure(adapter,
+ "INQUIRE FIRMWARE VERSION LETTER");
+ if (fw_ver_letter != ' ' && fw_ver_letter != '\0')
+ *tgt++ = fw_ver_letter;
+ *tgt = '\0';
}
/*
Save the Host Adapter SCSI ID in the Host Adapter structure.
*/
- HostAdapter->SCSI_ID = Configuration.HostAdapterID;
- /*
- Determine the Bus Type and save it in the Host Adapter structure, determine
- and save the IRQ Channel if necessary, and determine and save the DMA
- Channel for ISA Host Adapters.
- */
- HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
- if (HostAdapter->IRQ_Channel == 0) {
- if (Configuration.IRQ_Channel9)
- HostAdapter->IRQ_Channel = 9;
- else if (Configuration.IRQ_Channel10)
- HostAdapter->IRQ_Channel = 10;
- else if (Configuration.IRQ_Channel11)
- HostAdapter->IRQ_Channel = 11;
- else if (Configuration.IRQ_Channel12)
- HostAdapter->IRQ_Channel = 12;
- else if (Configuration.IRQ_Channel14)
- HostAdapter->IRQ_Channel = 14;
- else if (Configuration.IRQ_Channel15)
- HostAdapter->IRQ_Channel = 15;
- }
- if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) {
- if (Configuration.DMA_Channel5)
- HostAdapter->DMA_Channel = 5;
- else if (Configuration.DMA_Channel6)
- HostAdapter->DMA_Channel = 6;
- else if (Configuration.DMA_Channel7)
- HostAdapter->DMA_Channel = 7;
+ adapter->scsi_id = config.id;
+ /*
+ Determine the Bus Type and save it in the Host Adapter structure,
+ determine and save the IRQ Channel if necessary, and determine
+ and save the DMA Channel for ISA Host Adapters.
+ */
+ adapter->adapter_bus_type =
+ blogic_adater_bus_types[adapter->model[3] - '4'];
+ if (adapter->irq_ch == 0) {
+ if (config.irq_ch9)
+ adapter->irq_ch = 9;
+ else if (config.irq_ch10)
+ adapter->irq_ch = 10;
+ else if (config.irq_ch11)
+ adapter->irq_ch = 11;
+ else if (config.irq_ch12)
+ adapter->irq_ch = 12;
+ else if (config.irq_ch14)
+ adapter->irq_ch = 14;
+ else if (config.irq_ch15)
+ adapter->irq_ch = 15;
+ }
+ if (adapter->adapter_bus_type == BLOGIC_ISA_BUS) {
+ if (config.dma_ch5)
+ adapter->dma_ch = 5;
+ else if (config.dma_ch6)
+ adapter->dma_ch = 6;
+ else if (config.dma_ch7)
+ adapter->dma_ch = 7;
}
/*
Determine whether Extended Translation is enabled and save it in
the Host Adapter structure.
*/
- GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
- HostAdapter->ExtendedTranslationEnabled = GeometryRegister.gr.ExtendedTranslationEnabled;
+ georeg.all = blogic_rdgeom(adapter);
+ adapter->ext_trans_enable = georeg.gr.ext_trans_enable;
/*
Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
SCSI flag, Differential SCSI flag, SCAM Supported flag, and
Ultra SCSI flag in the Host Adapter structure.
*/
- HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit;
- HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit;
- if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
- HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
- if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
- HostAdapter->LevelSensitiveInterrupt = true;
- HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
- HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI;
- HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
- HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
+ adapter->adapter_sglimit = ext_setupinfo.sg_limit;
+ adapter->drvr_sglimit = adapter->adapter_sglimit;
+ if (adapter->adapter_sglimit > BLOGIC_SG_LIMIT)
+ adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
+ if (ext_setupinfo.misc.level_int)
+ adapter->level_int = true;
+ adapter->wide = ext_setupinfo.wide;
+ adapter->differential = ext_setupinfo.differential;
+ adapter->scam = ext_setupinfo.scam;
+ adapter->ultra = ext_setupinfo.ultra;
/*
Determine whether Extended LUN Format CCBs are supported and save the
information in the Host Adapter structure.
*/
- if (HostAdapter->FirmwareVersion[0] == '5' || (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
- HostAdapter->ExtendedLUNSupport = true;
+ if (adapter->fw_ver[0] == '5' || (adapter->fw_ver[0] == '4' &&
+ adapter->wide))
+ adapter->ext_lun = true;
/*
Issue the Inquire PCI Host Adapter Information command to read the
Termination Information from "W" series MultiMaster Host Adapters.
*/
- if (HostAdapter->FirmwareVersion[0] == '5') {
- if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
- != sizeof(PCIHostAdapterInformation))
- return BusLogic_Failure(HostAdapter, "INQUIRE PCI HOST ADAPTER INFORMATION");
+ if (adapter->fw_ver[0] == '5') {
+ if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
+ &adapter_info,
+ sizeof(adapter_info)) != sizeof(adapter_info))
+ return blogic_failure(adapter,
+ "INQUIRE PCI HOST ADAPTER INFORMATION");
/*
- Save the Termination Information in the Host Adapter structure.
+ Save the Termination Information in the Host Adapter
+ structure.
*/
- if (PCIHostAdapterInformation.GenericInfoValid) {
- HostAdapter->TerminationInfoValid = true;
- HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated;
- HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated;
+ if (adapter_info.genericinfo_valid) {
+ adapter->terminfo_valid = true;
+ adapter->low_term = adapter_info.low_term;
+ adapter->high_term = adapter_info.high_term;
}
}
/*
- Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
- from "W" and "C" series MultiMaster Host Adapters.
+ Issue the Fetch Host Adapter Local RAM command to read the
+ AutoSCSI data from "W" and "C" series MultiMaster Host Adapters.
*/
- if (HostAdapter->FirmwareVersion[0] >= '4') {
- FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset;
- FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
- if (BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIData, sizeof(AutoSCSIData))
- != sizeof(AutoSCSIData))
- return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
+ if (adapter->fw_ver[0] >= '4') {
+ fetch_localram.offset = BLOGIC_AUTOSCSI_BASE;
+ fetch_localram.count = sizeof(autoscsi);
+ if (blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, &fetch_localram,
+ sizeof(fetch_localram), &autoscsi,
+ sizeof(autoscsi)) != sizeof(autoscsi))
+ return blogic_failure(adapter,
+ "FETCH HOST ADAPTER LOCAL RAM");
/*
- Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
- Information in the Host Adapter structure.
+ Save the Parity Checking Enabled, Bus Reset Enabled,
+ and Termination Information in the Host Adapter structure.
*/
- HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
- HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
- if (HostAdapter->FirmwareVersion[0] == '4') {
- HostAdapter->TerminationInfoValid = true;
- HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
- HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
+ adapter->parity = autoscsi.parity;
+ adapter->reset_enabled = autoscsi.reset_enabled;
+ if (adapter->fw_ver[0] == '4') {
+ adapter->terminfo_valid = true;
+ adapter->low_term = autoscsi.low_term;
+ adapter->high_term = autoscsi.high_term;
}
/*
- Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
- Disconnect Permitted, Ultra Permitted, and SCAM Information in the
- Host Adapter structure.
+ Save the Wide Permitted, Fast Permitted, Synchronous
+ Permitted, Disconnect Permitted, Ultra Permitted, and
+ SCAM Information in the Host Adapter structure.
*/
- HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
- HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
- HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted;
- HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted;
- if (HostAdapter->HostUltraSCSI)
- HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
- if (HostAdapter->HostSupportsSCAM) {
- HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
- HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
+ adapter->wide_ok = autoscsi.wide_ok;
+ adapter->fast_ok = autoscsi.fast_ok;
+ adapter->sync_ok = autoscsi.sync_ok;
+ adapter->discon_ok = autoscsi.discon_ok;
+ if (adapter->ultra)
+ adapter->ultra_ok = autoscsi.ultra_ok;
+ if (adapter->scam) {
+ adapter->scam_enabled = autoscsi.scam_enabled;
+ adapter->scam_lev2 = autoscsi.scam_lev2;
}
}
/*
- Initialize fields in the Host Adapter structure for "S" and "A" series
- MultiMaster Host Adapters.
+ Initialize fields in the Host Adapter structure for "S" and "A"
+ series MultiMaster Host Adapters.
*/
- if (HostAdapter->FirmwareVersion[0] < '4') {
- if (SetupInformation.SynchronousInitiationEnabled) {
- HostAdapter->SynchronousPermitted = 0xFF;
- if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) {
- if (ExtendedSetupInformation.Misc.FastOnEISA)
- HostAdapter->FastPermitted = 0xFF;
- if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
- HostAdapter->WidePermitted = 0xFF;
+ if (adapter->fw_ver[0] < '4') {
+ if (setupinfo.sync) {
+ adapter->sync_ok = 0xFF;
+ if (adapter->adapter_bus_type == BLOGIC_EISA_BUS) {
+ if (ext_setupinfo.misc.fast_on_eisa)
+ adapter->fast_ok = 0xFF;
+ if (strcmp(adapter->model, "BT-757") == 0)
+ adapter->wide_ok = 0xFF;
}
}
- HostAdapter->DisconnectPermitted = 0xFF;
- HostAdapter->ParityCheckingEnabled = SetupInformation.ParityCheckingEnabled;
- HostAdapter->BusResetEnabled = true;
+ adapter->discon_ok = 0xFF;
+ adapter->parity = setupinfo.parity;
+ adapter->reset_enabled = true;
}
/*
- Determine the maximum number of Target IDs and Logical Units supported by
- this driver for Wide and Narrow Host Adapters.
+ Determine the maximum number of Target IDs and Logical Units
+ supported by this driver for Wide and Narrow Host Adapters.
*/
- HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
- HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
+ adapter->maxdev = (adapter->wide ? 16 : 8);
+ adapter->maxlun = (adapter->ext_lun ? 32 : 8);
/*
Select appropriate values for the Mailbox Count, Driver Queue Depth,
- Initial CCBs, and Incremental CCBs variables based on whether or not Strict
- Round Robin Mode is supported. If Strict Round Robin Mode is supported,
- then there is no performance degradation in using the maximum possible
- number of Outgoing and Incoming Mailboxes and allowing the Tagged and
- Untagged Queue Depths to determine the actual utilization. If Strict Round
- Robin Mode is not supported, then the Host Adapter must scan all the
- Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
- cause a substantial performance penalty. The host adapters actually have
- room to store the following number of CCBs internally; that is, they can
- internally queue and manage this many active commands on the SCSI bus
- simultaneously. Performance measurements demonstrate that the Driver Queue
- Depth should be set to the Mailbox Count, rather than the Host Adapter
- Queue Depth (internal CCB capacity), as it is more efficient to have the
- queued commands waiting in Outgoing Mailboxes if necessary than to block
- the process in the higher levels of the SCSI Subsystem.
+ Initial CCBs, and Incremental CCBs variables based on whether
+ or not Strict Round Robin Mode is supported. If Strict Round
+ Robin Mode is supported, then there is no performance degradation
+ in using the maximum possible number of Outgoing and Incoming
+ Mailboxes and allowing the Tagged and Untagged Queue Depths to
+ determine the actual utilization. If Strict Round Robin Mode is
+ not supported, then the Host Adapter must scan all the Outgoing
+ Mailboxes whenever an Outgoing Mailbox entry is made, which can
+ cause a substantial performance penalty. The host adapters
+ actually have room to store the following number of CCBs
+ internally; that is, they can internally queue and manage this
+ many active commands on the SCSI bus simultaneously. Performance
+ measurements demonstrate that the Driver Queue Depth should be
+ set to the Mailbox Count, rather than the Host Adapter Queue
+ Depth (internal CCB capacity), as it is more efficient to have the
+ queued commands waiting in Outgoing Mailboxes if necessary than
+ to block the process in the higher levels of the SCSI Subsystem.
192 BT-948/958/958D
100 BT-946C/956C/956CD/747C/757C/757CD/445C
50 BT-545C/540CF
30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
*/
- if (HostAdapter->FirmwareVersion[0] == '5')
- HostAdapter->HostAdapterQueueDepth = 192;
- else if (HostAdapter->FirmwareVersion[0] == '4')
- HostAdapter->HostAdapterQueueDepth = (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
+ if (adapter->fw_ver[0] == '5')
+ adapter->adapter_qdepth = 192;
+ else if (adapter->fw_ver[0] == '4')
+ adapter->adapter_qdepth = (adapter->adapter_bus_type !=
+ BLOGIC_ISA_BUS ? 100 : 50);
else
- HostAdapter->HostAdapterQueueDepth = 30;
- if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) {
- HostAdapter->StrictRoundRobinModeSupport = true;
- HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
+ adapter->adapter_qdepth = 30;
+ if (strcmp(adapter->fw_ver, "3.31") >= 0) {
+ adapter->strict_rr = true;
+ adapter->mbox_count = BLOGIC_MAX_MAILBOX;
} else {
- HostAdapter->StrictRoundRobinModeSupport = false;
- HostAdapter->MailboxCount = 32;
+ adapter->strict_rr = false;
+ adapter->mbox_count = 32;
}
- HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
- HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
- HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
+ adapter->drvr_qdepth = adapter->mbox_count;
+ adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
+ adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
/*
- Tagged Queuing support is available and operates properly on all "W" series
- MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
- firmware version 4.22 and above, and on "S" series MultiMaster Host
- Adapters with firmware version 3.35 and above.
+ Tagged Queuing support is available and operates properly on
+ all "W" series MultiMaster Host Adapters, on "C" series
+ MultiMaster Host Adapters with firmware version 4.22 and above,
+ and on "S" series MultiMaster Host Adapters with firmware version
+ 3.35 and above.
*/
- HostAdapter->TaggedQueuingPermitted = 0;
- switch (HostAdapter->FirmwareVersion[0]) {
+ adapter->tagq_ok = 0;
+ switch (adapter->fw_ver[0]) {
case '5':
- HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+ adapter->tagq_ok = 0xFFFF;
break;
case '4':
- if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
- HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+ if (strcmp(adapter->fw_ver, "4.22") >= 0)
+ adapter->tagq_ok = 0xFFFF;
break;
case '3':
- if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
- HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+ if (strcmp(adapter->fw_ver, "3.35") >= 0)
+ adapter->tagq_ok = 0xFFFF;
break;
}
/*
Determine the Host Adapter BIOS Address if the BIOS is enabled and
save it in the Host Adapter structure. The BIOS is disabled if the
- BIOS_Address is 0.
+ bios_addr is 0.
*/
- HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
+ adapter->bios_addr = ext_setupinfo.bios_addr << 12;
/*
- ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
+ ISA Host Adapters require Bounce Buffers if there is more than
+ 16MB memory.
*/
- if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
- HostAdapter->BounceBuffersRequired = true;
+ if (adapter->adapter_bus_type == BLOGIC_ISA_BUS &&
+ (void *) high_memory > (void *) MAX_DMA_ADDRESS)
+ adapter->need_bouncebuf = true;
/*
- BusLogic BT-445S Host Adapters prior to board revision E have a hardware
- bug whereby when the BIOS is enabled, transfers to/from the same address
- range the BIOS occupies modulo 16MB are handled incorrectly. Only properly
- functioning BT-445S Host Adapters have firmware version 3.37, so require
- that ISA Bounce Buffers be used for the buggy BT-445S models if there is
- more than 16MB memory.
+ BusLogic BT-445S Host Adapters prior to board revision E have a
+ hardware bug whereby when the BIOS is enabled, transfers to/from
+ the same address range the BIOS occupies modulo 16MB are handled
+ incorrectly. Only properly functioning BT-445S Host Adapters
+ have firmware version 3.37, so require that ISA Bounce Buffers
+ be used for the buggy BT-445S models if there is more than 16MB
+ memory.
*/
- if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
- HostAdapter->BounceBuffersRequired = true;
+ if (adapter->bios_addr > 0 && strcmp(adapter->model, "BT-445S") == 0 &&
+ strcmp(adapter->fw_ver, "3.37") < 0 &&
+ (void *) high_memory > (void *) MAX_DMA_ADDRESS)
+ adapter->need_bouncebuf = true;
/*
- Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
+ Initialize parameters common to MultiMaster and FlashPoint
+ Host Adapters.
*/
- Common:
+common:
/*
Initialize the Host Adapter Full Model Name from the Model Name.
*/
- strcpy(HostAdapter->FullModelName, "BusLogic ");
- strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
+ strcpy(adapter->full_model, "BusLogic ");
+ strcat(adapter->full_model, adapter->model);
/*
Select an appropriate value for the Tagged Queue Depth either from a
BusLogic Driver Options specification, or based on whether this Host
- Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth
- is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
- Initialize the Untagged Queue Depth.
- */
- for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
- unsigned char QueueDepth = 0;
- if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
- QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
- else if (HostAdapter->BounceBuffersRequired)
- QueueDepth = BusLogic_TaggedQueueDepthBB;
- HostAdapter->QueueDepth[TargetID] = QueueDepth;
- }
- if (HostAdapter->BounceBuffersRequired)
- HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
+ Adapter requires that ISA Bounce Buffers be used. The Tagged Queue
+ Depth is left at 0 for automatic determination in
+ BusLogic_SelectQueueDepths. Initialize the Untagged Queue Depth.
+ */
+ for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
+ unsigned char qdepth = 0;
+ if (adapter->drvr_opts != NULL &&
+ adapter->drvr_opts->qdepth[tgt_id] > 0)
+ qdepth = adapter->drvr_opts->qdepth[tgt_id];
+ else if (adapter->need_bouncebuf)
+ qdepth = BLOGIC_TAG_DEPTH_BB;
+ adapter->qdepth[tgt_id] = qdepth;
+ }
+ if (adapter->need_bouncebuf)
+ adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH_BB;
else
- HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
- if (HostAdapter->DriverOptions != NULL)
- HostAdapter->CommonQueueDepth = HostAdapter->DriverOptions->CommonQueueDepth;
- if (HostAdapter->CommonQueueDepth > 0 && HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
- HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
+ adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH;
+ if (adapter->drvr_opts != NULL)
+ adapter->common_qdepth = adapter->drvr_opts->common_qdepth;
+ if (adapter->common_qdepth > 0 &&
+ adapter->common_qdepth < adapter->untag_qdepth)
+ adapter->untag_qdepth = adapter->common_qdepth;
/*
Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
Therefore, mask the Tagged Queuing Permitted Default bits with the
Disconnect/Reconnect Permitted bits.
*/
- HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
+ adapter->tagq_ok &= adapter->discon_ok;
/*
- Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
- Options Tagged Queuing specification.
+ Combine the default Tagged Queuing Permitted bits with any
+ BusLogic Driver Options Tagged Queuing specification.
*/
- if (HostAdapter->DriverOptions != NULL)
- HostAdapter->TaggedQueuingPermitted =
- (HostAdapter->DriverOptions->TaggedQueuingPermitted & HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | (HostAdapter->TaggedQueuingPermitted & ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
+ if (adapter->drvr_opts != NULL)
+ adapter->tagq_ok = (adapter->drvr_opts->tagq_ok &
+ adapter->drvr_opts->tagq_ok_mask) |
+ (adapter->tagq_ok & ~adapter->drvr_opts->tagq_ok_mask);
/*
- Select an appropriate value for Bus Settle Time either from a BusLogic
- Driver Options specification, or from BusLogic_DefaultBusSettleTime.
+ Select an appropriate value for Bus Settle Time either from a
+ BusLogic Driver Options specification, or from
+ BLOGIC_BUS_SETTLE_TIME.
*/
- if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->BusSettleTime > 0)
- HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
+ if (adapter->drvr_opts != NULL &&
+ adapter->drvr_opts->bus_settle_time > 0)
+ adapter->bus_settle_time = adapter->drvr_opts->bus_settle_time;
else
- HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
+ adapter->bus_settle_time = BLOGIC_BUS_SETTLE_TIME;
/*
- Indicate reading the Host Adapter Configuration completed successfully.
+ Indicate reading the Host Adapter Configuration completed
+ successfully.
*/
return true;
}
/*
- BusLogic_ReportHostAdapterConfiguration reports the configuration of
- Host Adapter.
+ blogic_reportconfig reports the configuration of Host Adapter.
*/
-static bool __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
- *HostAdapter)
+static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
{
- unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
- unsigned short SynchronousPermitted, FastPermitted;
- unsigned short UltraPermitted, WidePermitted;
- unsigned short DisconnectPermitted, TaggedQueuingPermitted;
- bool CommonSynchronousNegotiation, CommonTaggedQueueDepth;
- char SynchronousString[BusLogic_MaxTargetDevices + 1];
- char WideString[BusLogic_MaxTargetDevices + 1];
- char DisconnectString[BusLogic_MaxTargetDevices + 1];
- char TaggedQueuingString[BusLogic_MaxTargetDevices + 1];
- char *SynchronousMessage = SynchronousString;
- char *WideMessage = WideString;
- char *DisconnectMessage = DisconnectString;
- char *TaggedQueuingMessage = TaggedQueuingString;
- int TargetID;
- BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
- HostAdapter, HostAdapter->ModelName,
- BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], (HostAdapter->HostWideSCSI ? " Wide" : ""), (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
- BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", HostAdapter, HostAdapter->FirmwareVersion, HostAdapter->IO_Address, HostAdapter->IRQ_Channel, (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
- if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) {
- BusLogic_Info(" DMA Channel: ", HostAdapter);
- if (HostAdapter->DMA_Channel > 0)
- BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
+ unsigned short alltgt_mask = (1 << adapter->maxdev) - 1;
+ unsigned short sync_ok, fast_ok;
+ unsigned short ultra_ok, wide_ok;
+ unsigned short discon_ok, tagq_ok;
+ bool common_syncneg, common_tagq_depth;
+ char syncstr[BLOGIC_MAXDEV + 1];
+ char widestr[BLOGIC_MAXDEV + 1];
+ char discon_str[BLOGIC_MAXDEV + 1];
+ char tagq_str[BLOGIC_MAXDEV + 1];
+ char *syncmsg = syncstr;
+ char *widemsg = widestr;
+ char *discon_msg = discon_str;
+ char *tagq_msg = tagq_str;
+ int tgt_id;
+
+ blogic_info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", adapter, adapter->model, blogic_adapter_busnames[adapter->adapter_bus_type], (adapter->wide ? " Wide" : ""), (adapter->differential ? " Differential" : ""), (adapter->ultra ? " Ultra" : ""));
+ blogic_info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", adapter, adapter->fw_ver, adapter->io_addr, adapter->irq_ch, (adapter->level_int ? "Level" : "Edge"));
+ if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
+ blogic_info(" DMA Channel: ", adapter);
+ if (adapter->dma_ch > 0)
+ blogic_info("%d, ", adapter, adapter->dma_ch);
else
- BusLogic_Info("None, ", HostAdapter);
- if (HostAdapter->BIOS_Address > 0)
- BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, HostAdapter->BIOS_Address);
+ blogic_info("None, ", adapter);
+ if (adapter->bios_addr > 0)
+ blogic_info("BIOS Address: 0x%X, ", adapter,
+ adapter->bios_addr);
else
- BusLogic_Info("BIOS Address: None, ", HostAdapter);
+ blogic_info("BIOS Address: None, ", adapter);
} else {
- BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
- if (HostAdapter->PCI_Address > 0)
- BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
+ blogic_info(" PCI Bus: %d, Device: %d, Address: ", adapter,
+ adapter->bus, adapter->dev);
+ if (adapter->pci_addr > 0)
+ blogic_info("0x%X, ", adapter, adapter->pci_addr);
else
- BusLogic_Info("Unassigned, ", HostAdapter);
- }
- BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, HostAdapter->SCSI_ID);
- BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", HostAdapter, (HostAdapter->ParityCheckingEnabled ? "Enabled" : "Disabled"), (HostAdapter->ExtendedTranslationEnabled ? "Enabled" : "Disabled"));
- AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
- SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
- FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
- UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
- if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && (HostAdapter->FirmwareVersion[0] >= '4' || HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || BusLogic_FlashPointHostAdapterP(HostAdapter)) {
- CommonSynchronousNegotiation = false;
- if (SynchronousPermitted == 0) {
- SynchronousMessage = "Disabled";
- CommonSynchronousNegotiation = true;
- } else if (SynchronousPermitted == AllTargetsMask) {
- if (FastPermitted == 0) {
- SynchronousMessage = "Slow";
- CommonSynchronousNegotiation = true;
- } else if (FastPermitted == AllTargetsMask) {
- if (UltraPermitted == 0) {
- SynchronousMessage = "Fast";
- CommonSynchronousNegotiation = true;
- } else if (UltraPermitted == AllTargetsMask) {
- SynchronousMessage = "Ultra";
- CommonSynchronousNegotiation = true;
+ blogic_info("Unassigned, ", adapter);
+ }
+ blogic_info("Host Adapter SCSI ID: %d\n", adapter, adapter->scsi_id);
+ blogic_info(" Parity Checking: %s, Extended Translation: %s\n",
+ adapter, (adapter->parity ? "Enabled" : "Disabled"),
+ (adapter->ext_trans_enable ? "Enabled" : "Disabled"));
+ alltgt_mask &= ~(1 << adapter->scsi_id);
+ sync_ok = adapter->sync_ok & alltgt_mask;
+ fast_ok = adapter->fast_ok & alltgt_mask;
+ ultra_ok = adapter->ultra_ok & alltgt_mask;
+ if ((blogic_multimaster_type(adapter) &&
+ (adapter->fw_ver[0] >= '4' ||
+ adapter->adapter_bus_type == BLOGIC_EISA_BUS)) ||
+ blogic_flashpoint_type(adapter)) {
+ common_syncneg = false;
+ if (sync_ok == 0) {
+ syncmsg = "Disabled";
+ common_syncneg = true;
+ } else if (sync_ok == alltgt_mask) {
+ if (fast_ok == 0) {
+ syncmsg = "Slow";
+ common_syncneg = true;
+ } else if (fast_ok == alltgt_mask) {
+ if (ultra_ok == 0) {
+ syncmsg = "Fast";
+ common_syncneg = true;
+ } else if (ultra_ok == alltgt_mask) {
+ syncmsg = "Ultra";
+ common_syncneg = true;
}
}
}
- if (!CommonSynchronousNegotiation) {
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- SynchronousString[TargetID] = ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : (!(FastPermitted & (1 << TargetID)) ? 'S' : (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
- SynchronousString[HostAdapter->SCSI_ID] = '#';
- SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
+ if (!common_syncneg) {
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ syncstr[tgt_id] = ((!(sync_ok & (1 << tgt_id))) ? 'N' : (!(fast_ok & (1 << tgt_id)) ? 'S' : (!(ultra_ok & (1 << tgt_id)) ? 'F' : 'U')));
+ syncstr[adapter->scsi_id] = '#';
+ syncstr[adapter->maxdev] = '\0';
}
} else
- SynchronousMessage = (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
- WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
- if (WidePermitted == 0)
- WideMessage = "Disabled";
- else if (WidePermitted == AllTargetsMask)
- WideMessage = "Enabled";
+ syncmsg = (sync_ok == 0 ? "Disabled" : "Enabled");
+ wide_ok = adapter->wide_ok & alltgt_mask;
+ if (wide_ok == 0)
+ widemsg = "Disabled";
+ else if (wide_ok == alltgt_mask)
+ widemsg = "Enabled";
else {
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- WideString[TargetID] = ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
- WideString[HostAdapter->SCSI_ID] = '#';
- WideString[HostAdapter->MaxTargetDevices] = '\0';
- }
- DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
- if (DisconnectPermitted == 0)
- DisconnectMessage = "Disabled";
- else if (DisconnectPermitted == AllTargetsMask)
- DisconnectMessage = "Enabled";
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ widestr[tgt_id] = ((wide_ok & (1 << tgt_id)) ? 'Y' : 'N');
+ widestr[adapter->scsi_id] = '#';
+ widestr[adapter->maxdev] = '\0';
+ }
+ discon_ok = adapter->discon_ok & alltgt_mask;
+ if (discon_ok == 0)
+ discon_msg = "Disabled";
+ else if (discon_ok == alltgt_mask)
+ discon_msg = "Enabled";
else {
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- DisconnectString[TargetID] = ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
- DisconnectString[HostAdapter->SCSI_ID] = '#';
- DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
- }
- TaggedQueuingPermitted = HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
- if (TaggedQueuingPermitted == 0)
- TaggedQueuingMessage = "Disabled";
- else if (TaggedQueuingPermitted == AllTargetsMask)
- TaggedQueuingMessage = "Enabled";
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ discon_str[tgt_id] = ((discon_ok & (1 << tgt_id)) ? 'Y' : 'N');
+ discon_str[adapter->scsi_id] = '#';
+ discon_str[adapter->maxdev] = '\0';
+ }
+ tagq_ok = adapter->tagq_ok & alltgt_mask;
+ if (tagq_ok == 0)
+ tagq_msg = "Disabled";
+ else if (tagq_ok == alltgt_mask)
+ tagq_msg = "Enabled";
else {
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- TaggedQueuingString[TargetID] = ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
- TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
- TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
- }
- BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", HostAdapter, SynchronousMessage, WideMessage);
- BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", HostAdapter, DisconnectMessage, TaggedQueuingMessage);
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
- BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", HostAdapter, HostAdapter->DriverScatterGatherLimit, HostAdapter->HostAdapterScatterGatherLimit, HostAdapter->MailboxCount);
- BusLogic_Info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->HostAdapterQueueDepth);
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ tagq_str[tgt_id] = ((tagq_ok & (1 << tgt_id)) ? 'Y' : 'N');
+ tagq_str[adapter->scsi_id] = '#';
+ tagq_str[adapter->maxdev] = '\0';
+ }
+ blogic_info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
+ adapter, syncmsg, widemsg);
+ blogic_info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", adapter,
+ discon_msg, tagq_msg);
+ if (blogic_multimaster_type(adapter)) {
+ blogic_info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
+ blogic_info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
} else
- BusLogic_Info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->DriverScatterGatherLimit);
- BusLogic_Info(" Tagged Queue Depth: ", HostAdapter);
- CommonTaggedQueueDepth = true;
- for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) {
- CommonTaggedQueueDepth = false;
+ blogic_info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
+ blogic_info(" Tagged Queue Depth: ", adapter);
+ common_tagq_depth = true;
+ for (tgt_id = 1; tgt_id < adapter->maxdev; tgt_id++)
+ if (adapter->qdepth[tgt_id] != adapter->qdepth[0]) {
+ common_tagq_depth = false;
break;
}
- if (CommonTaggedQueueDepth) {
- if (HostAdapter->QueueDepth[0] > 0)
- BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
+ if (common_tagq_depth) {
+ if (adapter->qdepth[0] > 0)
+ blogic_info("%d", adapter, adapter->qdepth[0]);
else
- BusLogic_Info("Automatic", HostAdapter);
+ blogic_info("Automatic", adapter);
} else
- BusLogic_Info("Individual", HostAdapter);
- BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, HostAdapter->UntaggedQueueDepth);
- if (HostAdapter->TerminationInfoValid) {
- if (HostAdapter->HostWideSCSI)
- BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? (HostAdapter->HighByteTerminated ? "Both Enabled" : "Low Enabled")
- : (HostAdapter->HighByteTerminated ? "High Enabled" : "Both Disabled")));
+ blogic_info("Individual", adapter);
+ blogic_info(", Untagged Queue Depth: %d\n", adapter,
+ adapter->untag_qdepth);
+ if (adapter->terminfo_valid) {
+ if (adapter->wide)
+ blogic_info(" SCSI Bus Termination: %s", adapter,
+ (adapter->low_term ? (adapter->high_term ? "Both Enabled" : "Low Enabled") : (adapter->high_term ? "High Enabled" : "Both Disabled")));
else
- BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled"));
- if (HostAdapter->HostSupportsSCAM)
- BusLogic_Info(", SCAM: %s", HostAdapter, (HostAdapter->SCAM_Enabled ? (HostAdapter->SCAM_Level2 ? "Enabled, Level 2" : "Enabled, Level 1")
- : "Disabled"));
- BusLogic_Info("\n", HostAdapter);
+ blogic_info(" SCSI Bus Termination: %s", adapter,
+ (adapter->low_term ? "Enabled" : "Disabled"));
+ if (adapter->scam)
+ blogic_info(", SCAM: %s", adapter,
+ (adapter->scam_enabled ? (adapter->scam_lev2 ? "Enabled, Level 2" : "Enabled, Level 1") : "Disabled"));
+ blogic_info("\n", adapter);
}
/*
- Indicate reporting the Host Adapter configuration completed successfully.
+ Indicate reporting the Host Adapter configuration completed
+ successfully.
*/
return true;
}
/*
- BusLogic_AcquireResources acquires the system resources necessary to use
+ blogic_getres acquires the system resources necessary to use
Host Adapter.
*/
-static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init blogic_getres(struct blogic_adapter *adapter)
{
- if (HostAdapter->IRQ_Channel == 0) {
- BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter);
+ if (adapter->irq_ch == 0) {
+ blogic_err("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
+ adapter);
return false;
}
/*
Acquire shared access to the IRQ Channel.
*/
- if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, IRQF_SHARED, HostAdapter->FullModelName, HostAdapter) < 0) {
- BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->IRQ_Channel);
+ if (request_irq(adapter->irq_ch, blogic_inthandler, IRQF_SHARED,
+ adapter->full_model, adapter) < 0) {
+ blogic_err("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
+ adapter, adapter->irq_ch);
return false;
}
- HostAdapter->IRQ_ChannelAcquired = true;
+ adapter->irq_acquired = true;
/*
Acquire exclusive access to the DMA Channel.
*/
- if (HostAdapter->DMA_Channel > 0) {
- if (request_dma(HostAdapter->DMA_Channel, HostAdapter->FullModelName) < 0) {
- BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->DMA_Channel);
+ if (adapter->dma_ch > 0) {
+ if (request_dma(adapter->dma_ch, adapter->full_model) < 0) {
+ blogic_err("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", adapter, adapter->dma_ch);
return false;
}
- set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
- enable_dma(HostAdapter->DMA_Channel);
- HostAdapter->DMA_ChannelAcquired = true;
+ set_dma_mode(adapter->dma_ch, DMA_MODE_CASCADE);
+ enable_dma(adapter->dma_ch);
+ adapter->dma_chan_acquired = true;
}
/*
Indicate the System Resource Acquisition completed successfully,
@@ -1874,127 +2018,146 @@ static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAd
/*
- BusLogic_ReleaseResources releases any system resources previously acquired
- by BusLogic_AcquireResources.
+ blogic_relres releases any system resources previously acquired
+ by blogic_getres.
*/
-static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter)
+static void blogic_relres(struct blogic_adapter *adapter)
{
/*
Release shared access to the IRQ Channel.
*/
- if (HostAdapter->IRQ_ChannelAcquired)
- free_irq(HostAdapter->IRQ_Channel, HostAdapter);
+ if (adapter->irq_acquired)
+ free_irq(adapter->irq_ch, adapter);
/*
Release exclusive access to the DMA Channel.
*/
- if (HostAdapter->DMA_ChannelAcquired)
- free_dma(HostAdapter->DMA_Channel);
+ if (adapter->dma_chan_acquired)
+ free_dma(adapter->dma_ch);
/*
Release any allocated memory structs not released elsewhere
*/
- if (HostAdapter->MailboxSpace)
- pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, HostAdapter->MailboxSpace, HostAdapter->MailboxSpaceHandle);
- pci_dev_put(HostAdapter->PCI_Device);
- HostAdapter->MailboxSpace = NULL;
- HostAdapter->MailboxSpaceHandle = 0;
- HostAdapter->MailboxSize = 0;
+ if (adapter->mbox_space)
+ pci_free_consistent(adapter->pci_device, adapter->mbox_sz,
+ adapter->mbox_space, adapter->mbox_space_handle);
+ pci_dev_put(adapter->pci_device);
+ adapter->mbox_space = NULL;
+ adapter->mbox_space_handle = 0;
+ adapter->mbox_sz = 0;
}
/*
- BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only
+ blogic_initadapter initializes Host Adapter. This is the only
function called during SCSI Host Adapter detection which modifies the state
of the Host Adapter from its initial power on or hard reset state.
*/
-static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
- *HostAdapter)
+static bool blogic_initadapter(struct blogic_adapter *adapter)
{
- struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
- enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest;
- enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest;
- int TargetID;
+ struct blogic_extmbox_req extmbox_req;
+ enum blogic_rr_req rr_req;
+ enum blogic_setccb_fmt setccb_fmt;
+ int tgt_id;
+
/*
- Initialize the pointers to the first and last CCBs that are queued for
- completion processing.
+ Initialize the pointers to the first and last CCBs that are
+ queued for completion processing.
*/
- HostAdapter->FirstCompletedCCB = NULL;
- HostAdapter->LastCompletedCCB = NULL;
+ adapter->firstccb = NULL;
+ adapter->lastccb = NULL;
+
/*
Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
Command Successful Flag, Active Commands, and Commands Since Reset
for each Target Device.
*/
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
- HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
- HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
- HostAdapter->ActiveCommands[TargetID] = 0;
- HostAdapter->CommandsSinceReset[TargetID] = 0;
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
+ adapter->bdr_pend[tgt_id] = NULL;
+ adapter->tgt_flags[tgt_id].tagq_active = false;
+ adapter->tgt_flags[tgt_id].cmd_good = false;
+ adapter->active_cmds[tgt_id] = 0;
+ adapter->cmds_since_rst[tgt_id] = 0;
}
+
/*
FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
*/
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
- goto Done;
+ if (blogic_flashpoint_type(adapter))
+ goto done;
+
/*
Initialize the Outgoing and Incoming Mailbox pointers.
*/
- HostAdapter->MailboxSize = HostAdapter->MailboxCount * (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox));
- HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle);
- if (HostAdapter->MailboxSpace == NULL)
- return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION");
- HostAdapter->FirstOutgoingMailbox = (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace;
- HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
- HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
- HostAdapter->FirstIncomingMailbox = (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1);
- HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
- HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
+ adapter->mbox_sz = adapter->mbox_count * (sizeof(struct blogic_outbox) + sizeof(struct blogic_inbox));
+ adapter->mbox_space = pci_alloc_consistent(adapter->pci_device,
+ adapter->mbox_sz, &adapter->mbox_space_handle);
+ if (adapter->mbox_space == NULL)
+ return blogic_failure(adapter, "MAILBOX ALLOCATION");
+ adapter->first_outbox = (struct blogic_outbox *) adapter->mbox_space;
+ adapter->last_outbox = adapter->first_outbox + adapter->mbox_count - 1;
+ adapter->next_outbox = adapter->first_outbox;
+ adapter->first_inbox = (struct blogic_inbox *) (adapter->last_outbox + 1);
+ adapter->last_inbox = adapter->first_inbox + adapter->mbox_count - 1;
+ adapter->next_inbox = adapter->first_inbox;
/*
Initialize the Outgoing and Incoming Mailbox structures.
*/
- memset(HostAdapter->FirstOutgoingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox));
- memset(HostAdapter->FirstIncomingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox));
+ memset(adapter->first_outbox, 0,
+ adapter->mbox_count * sizeof(struct blogic_outbox));
+ memset(adapter->first_inbox, 0,
+ adapter->mbox_count * sizeof(struct blogic_inbox));
+
/*
- Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
+ Initialize the Host Adapter's Pointer to the Outgoing/Incoming
+ Mailboxes.
*/
- ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
- ExtendedMailboxRequest.BaseMailboxAddress = (u32) HostAdapter->MailboxSpaceHandle;
- if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, &ExtendedMailboxRequest, sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
- return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
+ extmbox_req.mbox_count = adapter->mbox_count;
+ extmbox_req.base_mbox_addr = (u32) adapter->mbox_space_handle;
+ if (blogic_cmd(adapter, BLOGIC_INIT_EXT_MBOX, &extmbox_req,
+ sizeof(extmbox_req), NULL, 0) < 0)
+ return blogic_failure(adapter, "MAILBOX INITIALIZATION");
/*
- Enable Strict Round Robin Mode if supported by the Host Adapter. In
- Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
- Mailbox for each new command, rather than scanning through all the
- Outgoing Mailboxes to find any that have new commands in them. Strict
- Round Robin Mode is significantly more efficient.
+ Enable Strict Round Robin Mode if supported by the Host Adapter. In
+ Strict Round Robin Mode, the Host Adapter only looks at the next
+ Outgoing Mailbox for each new command, rather than scanning
+ through all the Outgoing Mailboxes to find any that have new
+ commands in them. Strict Round Robin Mode is significantly more
+ efficient.
*/
- if (HostAdapter->StrictRoundRobinModeSupport) {
- RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
- if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, &RoundRobinModeRequest, sizeof(RoundRobinModeRequest), NULL, 0) < 0)
- return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
+ if (adapter->strict_rr) {
+ rr_req = BLOGIC_STRICT_RR_MODE;
+ if (blogic_cmd(adapter, BLOGIC_STRICT_RR, &rr_req,
+ sizeof(rr_req), NULL, 0) < 0)
+ return blogic_failure(adapter,
+ "ENABLE STRICT ROUND ROBIN MODE");
}
+
/*
- For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
- Format command to allow 32 Logical Units per Target Device.
+ For Host Adapters that support Extended LUN Format CCBs, issue the
+ Set CCB Format command to allow 32 Logical Units per Target Device.
*/
- if (HostAdapter->ExtendedLUNSupport) {
- SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
- if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), NULL, 0) < 0)
- return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
+ if (adapter->ext_lun) {
+ setccb_fmt = BLOGIC_EXT_LUN_CCB;
+ if (blogic_cmd(adapter, BLOGIC_SETCCB_FMT, &setccb_fmt,
+ sizeof(setccb_fmt), NULL, 0) < 0)
+ return blogic_failure(adapter, "SET CCB FORMAT");
}
+
/*
Announce Successful Initialization.
*/
- Done:
- if (!HostAdapter->HostAdapterInitialized) {
- BusLogic_Info("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
- BusLogic_Info("\n", HostAdapter);
+done:
+ if (!adapter->adapter_initd) {
+ blogic_info("*** %s Initialized Successfully ***\n", adapter,
+ adapter->full_model);
+ blogic_info("\n", adapter);
} else
- BusLogic_Warning("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
- HostAdapter->HostAdapterInitialized = true;
+ blogic_warn("*** %s Initialized Successfully ***\n", adapter,
+ adapter->full_model);
+ adapter->adapter_initd = true;
+
/*
Indicate the Host Adapter Initialization completed successfully.
*/
@@ -2003,109 +2166,116 @@ static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
/*
- BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
+ blogic_inquiry inquires about the Target Devices accessible
through Host Adapter.
*/
-static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
- *HostAdapter)
+static bool __init blogic_inquiry(struct blogic_adapter *adapter)
{
- u16 InstalledDevices;
- u8 InstalledDevicesID0to7[8];
- struct BusLogic_SetupInformation SetupInformation;
- u8 SynchronousPeriod[BusLogic_MaxTargetDevices];
- unsigned char RequestedReplyLength;
- int TargetID;
+ u16 installed_devs;
+ u8 installed_devs0to7[8];
+ struct blogic_setup_info setupinfo;
+ u8 sync_period[BLOGIC_MAXDEV];
+ unsigned char req_replylen;
+ int tgt_id;
+
/*
- Wait a few seconds between the Host Adapter Hard Reset which initiates
- a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
- confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
+ Wait a few seconds between the Host Adapter Hard Reset which
+ initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
+ SCSI devices get confused if they receive SCSI Commands too soon
+ after a SCSI Bus Reset.
*/
- BusLogic_Delay(HostAdapter->BusSettleTime);
+ blogic_delay(adapter->bus_settle_time);
/*
FlashPoint Host Adapters do not provide for Target Device Inquiry.
*/
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+ if (blogic_flashpoint_type(adapter))
return true;
/*
Inhibit the Target Device Inquiry if requested.
*/
- if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
+ if (adapter->drvr_opts != NULL && adapter->drvr_opts->stop_tgt_inquiry)
return true;
/*
- Issue the Inquire Target Devices command for host adapters with firmware
- version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
- for older host adapters. This is necessary to force Synchronous Transfer
- Negotiation so that the Inquire Setup Information and Inquire Synchronous
- Period commands will return valid data. The Inquire Target Devices command
- is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
- Logical Unit 0 of each Target Device.
+ Issue the Inquire Target Devices command for host adapters with
+ firmware version 4.25 or later, or the Inquire Installed Devices
+ ID 0 to 7 command for older host adapters. This is necessary to
+ force Synchronous Transfer Negotiation so that the Inquire Setup
+ Information and Inquire Synchronous Period commands will return
+ valid data. The Inquire Target Devices command is preferable to
+ Inquire Installed Devices ID 0 to 7 since it only probes Logical
+ Unit 0 of each Target Device.
*/
- if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) {
+ if (strcmp(adapter->fw_ver, "4.25") >= 0) {
/*
- * Issue a Inquire Target Devices command. Inquire Target Devices only
- * tests Logical Unit 0 of each Target Device unlike the Inquire Installed
- * Devices commands which test Logical Units 0 - 7. Two bytes are
- * returned, where byte 0 bit 0 set indicates that Target Device 0 exists,
- * and so on.
+ Issue a Inquire Target Devices command. Inquire Target
+ Devices only tests Logical Unit 0 of each Target Device
+ unlike the Inquire Installed Devices commands which test
+ Logical Units 0 - 7. Two bytes are returned, where byte
+ 0 bit 0 set indicates that Target Device 0 exists, and so on.
*/
- if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, &InstalledDevices, sizeof(InstalledDevices))
- != sizeof(InstalledDevices))
- return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? true : false);
+ if (blogic_cmd(adapter, BLOGIC_INQ_DEV, NULL, 0,
+ &installed_devs, sizeof(installed_devs))
+ != sizeof(installed_devs))
+ return blogic_failure(adapter, "INQUIRE TARGET DEVICES");
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ adapter->tgt_flags[tgt_id].tgt_exists =
+ (installed_devs & (1 << tgt_id) ? true : false);
} else {
/*
- * Issue an Inquire Installed Devices command. For each Target Device,
- * a byte is returned where bit 0 set indicates that Logical Unit 0
- * exists, bit 1 set indicates that Logical Unit 1 exists, and so on.
+ Issue an Inquire Installed Devices command. For each
+ Target Device, a byte is returned where bit 0 set
+ indicates that Logical Unit 0 * exists, bit 1 set
+ indicates that Logical Unit 1 exists, and so on.
*/
- if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, NULL, 0, &InstalledDevicesID0to7, sizeof(InstalledDevicesID0to7))
- != sizeof(InstalledDevicesID0to7))
- return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7");
- for (TargetID = 0; TargetID < 8; TargetID++)
- HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
+ if (blogic_cmd(adapter, BLOGIC_INQ_DEV0TO7, NULL, 0,
+ &installed_devs0to7, sizeof(installed_devs0to7))
+ != sizeof(installed_devs0to7))
+ return blogic_failure(adapter,
+ "INQUIRE INSTALLED DEVICES ID 0 TO 7");
+ for (tgt_id = 0; tgt_id < 8; tgt_id++)
+ adapter->tgt_flags[tgt_id].tgt_exists =
+ (installed_devs0to7[tgt_id] != 0 ? true : false);
}
/*
Issue the Inquire Setup Information command.
*/
- RequestedReplyLength = sizeof(SetupInformation);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
- != sizeof(SetupInformation))
- return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset : SetupInformation.SynchronousValuesID8to15[TargetID - 8].Offset);
- if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
- ? true : false)
- : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID - 8))
- ? true : false));
+ req_replylen = sizeof(setupinfo);
+ if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
+ sizeof(req_replylen), &setupinfo, sizeof(setupinfo))
+ != sizeof(setupinfo))
+ return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ adapter->sync_offset[tgt_id] = (tgt_id < 8 ? setupinfo.sync0to7[tgt_id].offset : setupinfo.sync8to15[tgt_id - 8].offset);
+ if (strcmp(adapter->fw_ver, "5.06L") >= 0)
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ adapter->tgt_flags[tgt_id].wide_active = (tgt_id < 8 ? (setupinfo.wide_tx_active0to7 & (1 << tgt_id) ? true : false) : (setupinfo.wide_tx_active8to15 & (1 << (tgt_id - 8)) ? true : false));
/*
Issue the Inquire Synchronous Period command.
*/
- if (HostAdapter->FirmwareVersion[0] >= '3') {
+ if (adapter->fw_ver[0] >= '3') {
- /* Issue a Inquire Synchronous Period command. For each Target Device,
- * a byte is returned which represents the Synchronous Transfer Period
- * in units of 10 nanoseconds.
+ /* Issue a Inquire Synchronous Period command. For each
+ Target Device, a byte is returned which represents the
+ Synchronous Transfer Period in units of 10 nanoseconds.
*/
- RequestedReplyLength = sizeof(SynchronousPeriod);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, &RequestedReplyLength, sizeof(RequestedReplyLength), &SynchronousPeriod, sizeof(SynchronousPeriod))
- != sizeof(SynchronousPeriod))
- return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
+ req_replylen = sizeof(sync_period);
+ if (blogic_cmd(adapter, BLOGIC_INQ_SYNC_PERIOD, &req_replylen,
+ sizeof(req_replylen), &sync_period,
+ sizeof(sync_period)) != sizeof(sync_period))
+ return blogic_failure(adapter,
+ "INQUIRE SYNCHRONOUS PERIOD");
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ adapter->sync_period[tgt_id] = sync_period[tgt_id];
} else
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
- HostAdapter->SynchronousPeriod[TargetID] = 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
- .TransferPeriod;
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ if (setupinfo.sync0to7[tgt_id].offset > 0)
+ adapter->sync_period[tgt_id] = 20 + 5 * setupinfo.sync0to7[tgt_id].tx_period;
/*
Indicate the Target Device Inquiry completed successfully.
*/
@@ -2113,7 +2283,7 @@ static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
}
/*
- BusLogic_InitializeHostStructure initializes the fields in the SCSI Host
+ blogic_inithoststruct initializes the fields in the SCSI Host
structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
SCSI Host structure are intentionally left uninitialized, as this driver
handles acquisition and release of these resources explicitly, as well as
@@ -2121,517 +2291,555 @@ static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
through explicit acquisition and release of the Host Adapter's Lock.
*/
-static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter
- *HostAdapter, struct Scsi_Host *Host)
+static void __init blogic_inithoststruct(struct blogic_adapter *adapter,
+ struct Scsi_Host *host)
{
- Host->max_id = HostAdapter->MaxTargetDevices;
- Host->max_lun = HostAdapter->MaxLogicalUnits;
- Host->max_channel = 0;
- Host->unique_id = HostAdapter->IO_Address;
- Host->this_id = HostAdapter->SCSI_ID;
- Host->can_queue = HostAdapter->DriverQueueDepth;
- Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
- Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
- Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
+ host->max_id = adapter->maxdev;
+ host->max_lun = adapter->maxlun;
+ host->max_channel = 0;
+ host->unique_id = adapter->io_addr;
+ host->this_id = adapter->scsi_id;
+ host->can_queue = adapter->drvr_qdepth;
+ host->sg_tablesize = adapter->drvr_sglimit;
+ host->unchecked_isa_dma = adapter->need_bouncebuf;
+ host->cmd_per_lun = adapter->untag_qdepth;
}
/*
- BusLogic_SlaveConfigure will actually set the queue depth on individual
+ blogic_slaveconfig will actually set the queue depth on individual
scsi devices as they are permanently added to the device chain. We
shamelessly rip off the SelectQueueDepths code to make this work mostly
like it used to. Since we don't get called once at the end of the scan
but instead get called for each device, we have to do things a bit
differently.
*/
-static int BusLogic_SlaveConfigure(struct scsi_device *Device)
+static int blogic_slaveconfig(struct scsi_device *dev)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Device->host->hostdata;
- int TargetID = Device->id;
- int QueueDepth = HostAdapter->QueueDepth[TargetID];
-
- if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
- if (QueueDepth == 0)
- QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
- HostAdapter->QueueDepth[TargetID] = QueueDepth;
- scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth);
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) dev->host->hostdata;
+ int tgt_id = dev->id;
+ int qdepth = adapter->qdepth[tgt_id];
+
+ if (adapter->tgt_flags[tgt_id].tagq_ok &&
+ (adapter->tagq_ok & (1 << tgt_id))) {
+ if (qdepth == 0)
+ qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
+ adapter->qdepth[tgt_id] = qdepth;
+ scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, qdepth);
} else {
- HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
- QueueDepth = HostAdapter->UntaggedQueueDepth;
- HostAdapter->QueueDepth[TargetID] = QueueDepth;
- scsi_adjust_queue_depth(Device, 0, QueueDepth);
- }
- QueueDepth = 0;
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- if (HostAdapter->TargetFlags[TargetID].TargetExists) {
- QueueDepth += HostAdapter->QueueDepth[TargetID];
- }
- if (QueueDepth > HostAdapter->AllocatedCCBs)
- BusLogic_CreateAdditionalCCBs(HostAdapter, QueueDepth - HostAdapter->AllocatedCCBs, false);
+ adapter->tagq_ok &= ~(1 << tgt_id);
+ qdepth = adapter->untag_qdepth;
+ adapter->qdepth[tgt_id] = qdepth;
+ scsi_adjust_queue_depth(dev, 0, qdepth);
+ }
+ qdepth = 0;
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
+ if (adapter->tgt_flags[tgt_id].tgt_exists)
+ qdepth += adapter->qdepth[tgt_id];
+ if (qdepth > adapter->alloc_ccbs)
+ blogic_create_addlccbs(adapter, qdepth - adapter->alloc_ccbs,
+ false);
return 0;
}
/*
- BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
+ blogic_init probes for BusLogic Host Adapters at the standard
I/O Addresses where they may be located, initializing, registering, and
reporting the configuration of each BusLogic Host Adapter it finds. It
returns the number of BusLogic Host Adapters successfully initialized and
registered.
*/
-static int __init BusLogic_init(void)
+static int __init blogic_init(void)
{
- int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
- struct BusLogic_HostAdapter *PrototypeHostAdapter;
+ int adapter_count = 0, drvr_optindex = 0, probeindex;
+ struct blogic_adapter *adapter;
int ret = 0;
#ifdef MODULE
if (BusLogic)
- BusLogic_Setup(BusLogic);
+ blogic_setup(BusLogic);
#endif
- if (BusLogic_ProbeOptions.NoProbe)
+ if (blogic_probe_options.noprobe)
return -ENODEV;
- BusLogic_ProbeInfoList =
- kzalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_KERNEL);
- if (BusLogic_ProbeInfoList == NULL) {
- BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
+ blogic_probeinfo_list =
+ kzalloc(BLOGIC_MAX_ADAPTERS * sizeof(struct blogic_probeinfo),
+ GFP_KERNEL);
+ if (blogic_probeinfo_list == NULL) {
+ blogic_err("BusLogic: Unable to allocate Probe Info List\n",
+ NULL);
return -ENOMEM;
}
- PrototypeHostAdapter =
- kzalloc(sizeof(struct BusLogic_HostAdapter), GFP_KERNEL);
- if (PrototypeHostAdapter == NULL) {
- kfree(BusLogic_ProbeInfoList);
- BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
+ adapter = kzalloc(sizeof(struct blogic_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ kfree(blogic_probeinfo_list);
+ blogic_err("BusLogic: Unable to allocate Prototype Host Adapter\n", NULL);
return -ENOMEM;
}
#ifdef MODULE
if (BusLogic != NULL)
- BusLogic_Setup(BusLogic);
+ blogic_setup(BusLogic);
#endif
- BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
- for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) {
- struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
- struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
- struct Scsi_Host *Host;
- if (ProbeInfo->IO_Address == 0)
+ blogic_init_probeinfo_list(adapter);
+ for (probeindex = 0; probeindex < blogic_probeinfo_count; probeindex++) {
+ struct blogic_probeinfo *probeinfo =
+ &blogic_probeinfo_list[probeindex];
+ struct blogic_adapter *myadapter = adapter;
+ struct Scsi_Host *host;
+
+ if (probeinfo->io_addr == 0)
continue;
- memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
- HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
- HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
- HostAdapter->IO_Address = ProbeInfo->IO_Address;
- HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
- HostAdapter->Bus = ProbeInfo->Bus;
- HostAdapter->Device = ProbeInfo->Device;
- HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
- HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
- HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
+ memset(myadapter, 0, sizeof(struct blogic_adapter));
+ myadapter->adapter_type = probeinfo->adapter_type;
+ myadapter->adapter_bus_type = probeinfo->adapter_bus_type;
+ myadapter->io_addr = probeinfo->io_addr;
+ myadapter->pci_addr = probeinfo->pci_addr;
+ myadapter->bus = probeinfo->bus;
+ myadapter->dev = probeinfo->dev;
+ myadapter->pci_device = probeinfo->pci_device;
+ myadapter->irq_ch = probeinfo->irq_ch;
+ myadapter->addr_count =
+ blogic_adapter_addr_count[myadapter->adapter_type];
/*
Make sure region is free prior to probing.
*/
- if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
+ if (!request_region(myadapter->io_addr, myadapter->addr_count,
"BusLogic"))
continue;
/*
- Probe the Host Adapter. If unsuccessful, abort further initialization.
+ Probe the Host Adapter. If unsuccessful, abort further
+ initialization.
*/
- if (!BusLogic_ProbeHostAdapter(HostAdapter)) {
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+ if (!blogic_probe(myadapter)) {
+ release_region(myadapter->io_addr,
+ myadapter->addr_count);
continue;
}
/*
Hard Reset the Host Adapter. If unsuccessful, abort further
initialization.
*/
- if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) {
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+ if (!blogic_hwreset(myadapter, true)) {
+ release_region(myadapter->io_addr,
+ myadapter->addr_count);
continue;
}
/*
- Check the Host Adapter. If unsuccessful, abort further initialization.
+ Check the Host Adapter. If unsuccessful, abort further
+ initialization.
*/
- if (!BusLogic_CheckHostAdapter(HostAdapter)) {
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+ if (!blogic_checkadapter(myadapter)) {
+ release_region(myadapter->io_addr,
+ myadapter->addr_count);
continue;
}
/*
Initialize the Driver Options field if provided.
*/
- if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
- HostAdapter->DriverOptions = &BusLogic_DriverOptions[DriverOptionsIndex++];
+ if (drvr_optindex < blogic_drvr_options_count)
+ myadapter->drvr_opts =
+ &blogic_drvr_options[drvr_optindex++];
/*
- Announce the Driver Version and Date, Author's Name, Copyright Notice,
- and Electronic Mail Address.
+ Announce the Driver Version and Date, Author's Name,
+ Copyright Notice, and Electronic Mail Address.
*/
- BusLogic_AnnounceDriver(HostAdapter);
+ blogic_announce_drvr(myadapter);
/*
Register the SCSI Host structure.
*/
- Host = scsi_host_alloc(&Bus_Logic_template, sizeof(struct BusLogic_HostAdapter));
- if (Host == NULL) {
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+ host = scsi_host_alloc(&blogic_template,
+ sizeof(struct blogic_adapter));
+ if (host == NULL) {
+ release_region(myadapter->io_addr,
+ myadapter->addr_count);
continue;
}
- HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
- memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter));
- HostAdapter->SCSI_Host = Host;
- HostAdapter->HostNumber = Host->host_no;
+ myadapter = (struct blogic_adapter *) host->hostdata;
+ memcpy(myadapter, adapter, sizeof(struct blogic_adapter));
+ myadapter->scsi_host = host;
+ myadapter->host_no = host->host_no;
/*
- Add Host Adapter to the end of the list of registered BusLogic
- Host Adapters.
+ Add Host Adapter to the end of the list of registered
+ BusLogic Host Adapters.
*/
- list_add_tail(&HostAdapter->host_list, &BusLogic_host_list);
+ list_add_tail(&myadapter->host_list, &blogic_host_list);
/*
- Read the Host Adapter Configuration, Configure the Host Adapter,
- Acquire the System Resources necessary to use the Host Adapter, then
- Create the Initial CCBs, Initialize the Host Adapter, and finally
- perform Target Device Inquiry.
-
- From this point onward, any failure will be assumed to be due to a
- problem with the Host Adapter, rather than due to having mistakenly
- identified this port as belonging to a BusLogic Host Adapter. The
- I/O Address range will not be released, thereby preventing it from
- being incorrectly identified as any other type of Host Adapter.
+ Read the Host Adapter Configuration, Configure the Host
+ Adapter, Acquire the System Resources necessary to use
+ the Host Adapter, then Create the Initial CCBs, Initialize
+ the Host Adapter, and finally perform Target Device
+ Inquiry. From this point onward, any failure will be
+ assumed to be due to a problem with the Host Adapter,
+ rather than due to having mistakenly identified this port
+ as belonging to a BusLogic Host Adapter. The I/O Address
+ range will not be released, thereby preventing it from
+ being incorrectly identified as any other type of Host
+ Adapter.
*/
- if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
- BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
- BusLogic_AcquireResources(HostAdapter) &&
- BusLogic_CreateInitialCCBs(HostAdapter) &&
- BusLogic_InitializeHostAdapter(HostAdapter) &&
- BusLogic_TargetDeviceInquiry(HostAdapter)) {
+ if (blogic_rdconfig(myadapter) &&
+ blogic_reportconfig(myadapter) &&
+ blogic_getres(myadapter) &&
+ blogic_create_initccbs(myadapter) &&
+ blogic_initadapter(myadapter) &&
+ blogic_inquiry(myadapter)) {
/*
- Initialization has been completed successfully. Release and
- re-register usage of the I/O Address range so that the Model
- Name of the Host Adapter will appear, and initialize the SCSI
- Host structure.
+ Initialization has been completed successfully.
+ Release and re-register usage of the I/O Address
+ range so that the Model Name of the Host Adapter
+ will appear, and initialize the SCSI Host structure.
*/
- release_region(HostAdapter->IO_Address,
- HostAdapter->AddressCount);
- if (!request_region(HostAdapter->IO_Address,
- HostAdapter->AddressCount,
- HostAdapter->FullModelName)) {
+ release_region(myadapter->io_addr,
+ myadapter->addr_count);
+ if (!request_region(myadapter->io_addr,
+ myadapter->addr_count,
+ myadapter->full_model)) {
printk(KERN_WARNING
"BusLogic: Release and re-register of "
"port 0x%04lx failed \n",
- (unsigned long)HostAdapter->IO_Address);
- BusLogic_DestroyCCBs(HostAdapter);
- BusLogic_ReleaseResources(HostAdapter);
- list_del(&HostAdapter->host_list);
- scsi_host_put(Host);
+ (unsigned long)myadapter->io_addr);
+ blogic_destroy_ccbs(myadapter);
+ blogic_relres(myadapter);
+ list_del(&myadapter->host_list);
+ scsi_host_put(host);
ret = -ENOMEM;
} else {
- BusLogic_InitializeHostStructure(HostAdapter,
- Host);
- if (scsi_add_host(Host, HostAdapter->PCI_Device
- ? &HostAdapter->PCI_Device->dev
+ blogic_inithoststruct(myadapter,
+ host);
+ if (scsi_add_host(host, myadapter->pci_device
+ ? &myadapter->pci_device->dev
: NULL)) {
printk(KERN_WARNING
"BusLogic: scsi_add_host()"
"failed!\n");
- BusLogic_DestroyCCBs(HostAdapter);
- BusLogic_ReleaseResources(HostAdapter);
- list_del(&HostAdapter->host_list);
- scsi_host_put(Host);
+ blogic_destroy_ccbs(myadapter);
+ blogic_relres(myadapter);
+ list_del(&myadapter->host_list);
+ scsi_host_put(host);
ret = -ENODEV;
} else {
- scsi_scan_host(Host);
- BusLogicHostAdapterCount++;
+ scsi_scan_host(host);
+ adapter_count++;
}
}
} else {
/*
- An error occurred during Host Adapter Configuration Querying, Host
- Adapter Configuration, Resource Acquisition, CCB Creation, Host
- Adapter Initialization, or Target Device Inquiry, so remove Host
- Adapter from the list of registered BusLogic Host Adapters, destroy
- the CCBs, Release the System Resources, and Unregister the SCSI
+ An error occurred during Host Adapter Configuration
+ Querying, Host Adapter Configuration, Resource
+ Acquisition, CCB Creation, Host Adapter
+ Initialization, or Target Device Inquiry, so
+ remove Host Adapter from the list of registered
+ BusLogic Host Adapters, destroy the CCBs, Release
+ the System Resources, and Unregister the SCSI
Host.
*/
- BusLogic_DestroyCCBs(HostAdapter);
- BusLogic_ReleaseResources(HostAdapter);
- list_del(&HostAdapter->host_list);
- scsi_host_put(Host);
+ blogic_destroy_ccbs(myadapter);
+ blogic_relres(myadapter);
+ list_del(&myadapter->host_list);
+ scsi_host_put(host);
ret = -ENODEV;
}
}
- kfree(PrototypeHostAdapter);
- kfree(BusLogic_ProbeInfoList);
- BusLogic_ProbeInfoList = NULL;
+ kfree(adapter);
+ kfree(blogic_probeinfo_list);
+ blogic_probeinfo_list = NULL;
return ret;
}
/*
- BusLogic_ReleaseHostAdapter releases all resources previously acquired to
+ blogic_deladapter releases all resources previously acquired to
support a specific Host Adapter, including the I/O Address range, and
unregisters the BusLogic Host Adapter.
*/
-static int __exit BusLogic_ReleaseHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static int __exit blogic_deladapter(struct blogic_adapter *adapter)
{
- struct Scsi_Host *Host = HostAdapter->SCSI_Host;
+ struct Scsi_Host *host = adapter->scsi_host;
- scsi_remove_host(Host);
+ scsi_remove_host(host);
/*
FlashPoint Host Adapters must first be released by the FlashPoint
SCCB Manager.
*/
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
- FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
+ if (blogic_flashpoint_type(adapter))
+ FlashPoint_ReleaseHostAdapter(adapter->cardhandle);
/*
Destroy the CCBs and release any system resources acquired to
support Host Adapter.
*/
- BusLogic_DestroyCCBs(HostAdapter);
- BusLogic_ReleaseResources(HostAdapter);
+ blogic_destroy_ccbs(adapter);
+ blogic_relres(adapter);
/*
Release usage of the I/O Address range.
*/
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+ release_region(adapter->io_addr, adapter->addr_count);
/*
- Remove Host Adapter from the list of registered BusLogic Host Adapters.
+ Remove Host Adapter from the list of registered BusLogic
+ Host Adapters.
*/
- list_del(&HostAdapter->host_list);
+ list_del(&adapter->host_list);
- scsi_host_put(Host);
+ scsi_host_put(host);
return 0;
}
/*
- BusLogic_QueueCompletedCCB queues CCB for completion processing.
+ blogic_qcompleted_ccb queues CCB for completion processing.
*/
-static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB)
+static void blogic_qcompleted_ccb(struct blogic_ccb *ccb)
{
- struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
- CCB->Status = BusLogic_CCB_Completed;
- CCB->Next = NULL;
- if (HostAdapter->FirstCompletedCCB == NULL) {
- HostAdapter->FirstCompletedCCB = CCB;
- HostAdapter->LastCompletedCCB = CCB;
+ struct blogic_adapter *adapter = ccb->adapter;
+
+ ccb->status = BLOGIC_CCB_COMPLETE;
+ ccb->next = NULL;
+ if (adapter->firstccb == NULL) {
+ adapter->firstccb = ccb;
+ adapter->lastccb = ccb;
} else {
- HostAdapter->LastCompletedCCB->Next = CCB;
- HostAdapter->LastCompletedCCB = CCB;
+ adapter->lastccb->next = ccb;
+ adapter->lastccb = ccb;
}
- HostAdapter->ActiveCommands[CCB->TargetID]--;
+ adapter->active_cmds[ccb->tgt_id]--;
}
/*
- BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
+ blogic_resultcode computes a SCSI Subsystem Result Code from
the Host Adapter Status and Target Device Status.
*/
-static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_HostAdapterStatus HostAdapterStatus, enum BusLogic_TargetDeviceStatus TargetDeviceStatus)
+static int blogic_resultcode(struct blogic_adapter *adapter,
+ enum blogic_adapter_status adapter_status,
+ enum blogic_tgt_status tgt_status)
{
- int HostStatus;
- switch (HostAdapterStatus) {
- case BusLogic_CommandCompletedNormally:
- case BusLogic_LinkedCommandCompleted:
- case BusLogic_LinkedCommandCompletedWithFlag:
- HostStatus = DID_OK;
+ int hoststatus;
+
+ switch (adapter_status) {
+ case BLOGIC_CMD_CMPLT_NORMAL:
+ case BLOGIC_LINK_CMD_CMPLT:
+ case BLOGIC_LINK_CMD_CMPLT_FLAG:
+ hoststatus = DID_OK;
break;
- case BusLogic_SCSISelectionTimeout:
- HostStatus = DID_TIME_OUT;
+ case BLOGIC_SELECT_TIMEOUT:
+ hoststatus = DID_TIME_OUT;
break;
- case BusLogic_InvalidOutgoingMailboxActionCode:
- case BusLogic_InvalidCommandOperationCode:
- case BusLogic_InvalidCommandParameter:
- BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", HostAdapter, HostAdapterStatus);
- case BusLogic_DataUnderRun:
- case BusLogic_DataOverRun:
- case BusLogic_UnexpectedBusFree:
- case BusLogic_LinkedCCBhasInvalidLUN:
- case BusLogic_AutoRequestSenseFailed:
- case BusLogic_TaggedQueuingMessageRejected:
- case BusLogic_UnsupportedMessageReceived:
- case BusLogic_HostAdapterHardwareFailed:
- case BusLogic_TargetDeviceReconnectedImproperly:
- case BusLogic_AbortQueueGenerated:
- case BusLogic_HostAdapterSoftwareError:
- case BusLogic_HostAdapterHardwareTimeoutError:
- case BusLogic_SCSIParityErrorDetected:
- HostStatus = DID_ERROR;
+ case BLOGIC_INVALID_OUTBOX_CODE:
+ case BLOGIC_INVALID_CMD_CODE:
+ case BLOGIC_BAD_CMD_PARAM:
+ blogic_warn("BusLogic Driver Protocol Error 0x%02X\n",
+ adapter, adapter_status);
+ case BLOGIC_DATA_UNDERRUN:
+ case BLOGIC_DATA_OVERRUN:
+ case BLOGIC_NOEXPECT_BUSFREE:
+ case BLOGIC_LINKCCB_BADLUN:
+ case BLOGIC_AUTOREQSENSE_FAIL:
+ case BLOGIC_TAGQUEUE_REJECT:
+ case BLOGIC_BAD_MSG_RCVD:
+ case BLOGIC_HW_FAIL:
+ case BLOGIC_BAD_RECONNECT:
+ case BLOGIC_ABRT_QUEUE:
+ case BLOGIC_ADAPTER_SW_ERROR:
+ case BLOGIC_HW_TIMEOUT:
+ case BLOGIC_PARITY_ERR:
+ hoststatus = DID_ERROR;
break;
- case BusLogic_InvalidBusPhaseRequested:
- case BusLogic_TargetFailedResponseToATN:
- case BusLogic_HostAdapterAssertedRST:
- case BusLogic_OtherDeviceAssertedRST:
- case BusLogic_HostAdapterAssertedBusDeviceReset:
- HostStatus = DID_RESET;
+ case BLOGIC_INVALID_BUSPHASE:
+ case BLOGIC_NORESPONSE_TO_ATN:
+ case BLOGIC_HW_RESET:
+ case BLOGIC_RST_FROM_OTHERDEV:
+ case BLOGIC_HW_BDR:
+ hoststatus = DID_RESET;
break;
default:
- BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", HostAdapter, HostAdapterStatus);
- HostStatus = DID_ERROR;
+ blogic_warn("Unknown Host Adapter Status 0x%02X\n", adapter,
+ adapter_status);
+ hoststatus = DID_ERROR;
break;
}
- return (HostStatus << 16) | TargetDeviceStatus;
+ return (hoststatus << 16) | tgt_status;
}
/*
- BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
+ blogic_scan_inbox scans the Incoming Mailboxes saving any
Incoming Mailbox entries for completion processing.
*/
-static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdapter)
+static void blogic_scan_inbox(struct blogic_adapter *adapter)
{
/*
- Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
- any completed CCBs for further processing. It is essential that for each
- CCB and SCSI Command issued, command completion processing is performed
- exactly once. Therefore, only Incoming Mailboxes with completion code
- Command Completed Without Error, Command Completed With Error, or Command
- Aborted At Host Request are saved for completion processing. When an
- Incoming Mailbox has a completion code of Aborted Command Not Found, the
- CCB had already completed or been aborted before the current Abort request
- was processed, and so completion processing has already occurred and no
- further action should be taken.
- */
- struct BusLogic_IncomingMailbox *NextIncomingMailbox = HostAdapter->NextIncomingMailbox;
- enum BusLogic_CompletionCode CompletionCode;
- while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) {
+ Scan through the Incoming Mailboxes in Strict Round Robin
+ fashion, saving any completed CCBs for further processing. It
+ is essential that for each CCB and SCSI Command issued, command
+ completion processing is performed exactly once. Therefore,
+ only Incoming Mailboxes with completion code Command Completed
+ Without Error, Command Completed With Error, or Command Aborted
+ At Host Request are saved for completion processing. When an
+ Incoming Mailbox has a completion code of Aborted Command Not
+ Found, the CCB had already completed or been aborted before the
+ current Abort request was processed, and so completion processing
+ has already occurred and no further action should be taken.
+ */
+ struct blogic_inbox *next_inbox = adapter->next_inbox;
+ enum blogic_cmplt_code comp_code;
+
+ while ((comp_code = next_inbox->comp_code) != BLOGIC_INBOX_FREE) {
/*
- We are only allowed to do this because we limit our architectures we
- run on to machines where bus_to_virt() actually works. There *needs*
- to be a dma_addr_to_virt() in the new PCI DMA mapping interface to
- replace bus_to_virt() or else this code is going to become very
+ We are only allowed to do this because we limit our
+ architectures we run on to machines where bus_to_virt(
+ actually works. There *needs* to be a dma_addr_to_virt()
+ in the new PCI DMA mapping interface to replace
+ bus_to_virt() or else this code is going to become very
innefficient.
*/
- struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) Bus_to_Virtual(NextIncomingMailbox->CCB);
- if (CompletionCode != BusLogic_AbortedCommandNotFound) {
- if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) {
+ struct blogic_ccb *ccb =
+ (struct blogic_ccb *) bus_to_virt(next_inbox->ccb);
+ if (comp_code != BLOGIC_CMD_NOTFOUND) {
+ if (ccb->status == BLOGIC_CCB_ACTIVE ||
+ ccb->status == BLOGIC_CCB_RESET) {
/*
- Save the Completion Code for this CCB and queue the CCB
- for completion processing.
+ Save the Completion Code for this CCB and
+ queue the CCB for completion processing.
*/
- CCB->CompletionCode = CompletionCode;
- BusLogic_QueueCompletedCCB(CCB);
+ ccb->comp_code = comp_code;
+ blogic_qcompleted_ccb(ccb);
} else {
/*
- If a CCB ever appears in an Incoming Mailbox and is not marked
- as status Active or Reset, then there is most likely a bug in
+ If a CCB ever appears in an Incoming Mailbox
+ and is not marked as status Active or Reset,
+ then there is most likely a bug in
the Host Adapter firmware.
*/
- BusLogic_Warning("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", HostAdapter, CCB->SerialNumber, CCB->Status);
+ blogic_warn("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
}
}
- NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
- if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
- NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
+ next_inbox->comp_code = BLOGIC_INBOX_FREE;
+ if (++next_inbox > adapter->last_inbox)
+ next_inbox = adapter->first_inbox;
}
- HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
+ adapter->next_inbox = next_inbox;
}
/*
- BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
+ blogic_process_ccbs iterates over the completed CCBs for Host
Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
should already have been acquired by the caller.
*/
-static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapter)
+static void blogic_process_ccbs(struct blogic_adapter *adapter)
{
- if (HostAdapter->ProcessCompletedCCBsActive)
+ if (adapter->processing_ccbs)
return;
- HostAdapter->ProcessCompletedCCBsActive = true;
- while (HostAdapter->FirstCompletedCCB != NULL) {
- struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB;
- struct scsi_cmnd *Command = CCB->Command;
- HostAdapter->FirstCompletedCCB = CCB->Next;
- if (HostAdapter->FirstCompletedCCB == NULL)
- HostAdapter->LastCompletedCCB = NULL;
+ adapter->processing_ccbs = true;
+ while (adapter->firstccb != NULL) {
+ struct blogic_ccb *ccb = adapter->firstccb;
+ struct scsi_cmnd *command = ccb->command;
+ adapter->firstccb = ccb->next;
+ if (adapter->firstccb == NULL)
+ adapter->lastccb = NULL;
/*
Process the Completed CCB.
*/
- if (CCB->Opcode == BusLogic_BusDeviceReset) {
- int TargetID = CCB->TargetID;
- BusLogic_Warning("Bus Device Reset CCB #%ld to Target " "%d Completed\n", HostAdapter, CCB->SerialNumber, TargetID);
- BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
- HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
- HostAdapter->CommandsSinceReset[TargetID] = 0;
- HostAdapter->LastResetCompleted[TargetID] = jiffies;
+ if (ccb->opcode == BLOGIC_BDR) {
+ int tgt_id = ccb->tgt_id;
+
+ blogic_warn("Bus Device Reset CCB #%ld to Target " "%d Completed\n", adapter, ccb->serial, tgt_id);
+ blogic_inc_count(&adapter->tgt_stats[tgt_id].bdr_done);
+ adapter->tgt_flags[tgt_id].tagq_active = false;
+ adapter->cmds_since_rst[tgt_id] = 0;
+ adapter->last_resetdone[tgt_id] = jiffies;
/*
Place CCB back on the Host Adapter's free list.
*/
- BusLogic_DeallocateCCB(CCB);
+ blogic_dealloc_ccb(ccb);
#if 0 /* this needs to be redone different for new EH */
/*
- Bus Device Reset CCBs have the Command field non-NULL only when a
- Bus Device Reset was requested for a Command that did not have a
- currently active CCB in the Host Adapter (i.e., a Synchronous
- Bus Device Reset), and hence would not have its Completion Routine
- called otherwise.
+ Bus Device Reset CCBs have the command field
+ non-NULL only when a Bus Device Reset was requested
+ for a command that did not have a currently active
+ CCB in the Host Adapter (i.e., a Synchronous Bus
+ Device Reset), and hence would not have its
+ Completion Routine called otherwise.
*/
- while (Command != NULL) {
- struct scsi_cmnd *NextCommand = Command->reset_chain;
- Command->reset_chain = NULL;
- Command->result = DID_RESET << 16;
- Command->scsi_done(Command);
- Command = NextCommand;
+ while (command != NULL) {
+ struct scsi_cmnd *nxt_cmd =
+ command->reset_chain;
+ command->reset_chain = NULL;
+ command->result = DID_RESET << 16;
+ command->scsi_done(command);
+ command = nxt_cmd;
}
#endif
/*
- Iterate over the CCBs for this Host Adapter performing completion
- processing for any CCBs marked as Reset for this Target.
+ Iterate over the CCBs for this Host Adapter
+ performing completion processing for any CCBs
+ marked as Reset for this Target.
*/
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) {
- Command = CCB->Command;
- BusLogic_DeallocateCCB(CCB);
- HostAdapter->ActiveCommands[TargetID]--;
- Command->result = DID_RESET << 16;
- Command->scsi_done(Command);
+ for (ccb = adapter->all_ccbs; ccb != NULL;
+ ccb = ccb->next_all)
+ if (ccb->status == BLOGIC_CCB_RESET &&
+ ccb->tgt_id == tgt_id) {
+ command = ccb->command;
+ blogic_dealloc_ccb(ccb);
+ adapter->active_cmds[tgt_id]--;
+ command->result = DID_RESET << 16;
+ command->scsi_done(command);
}
- HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+ adapter->bdr_pend[tgt_id] = NULL;
} else {
/*
- Translate the Completion Code, Host Adapter Status, and Target
- Device Status into a SCSI Subsystem Result Code.
+ Translate the Completion Code, Host Adapter Status,
+ and Target Device Status into a SCSI Subsystem
+ Result Code.
*/
- switch (CCB->CompletionCode) {
- case BusLogic_IncomingMailboxFree:
- case BusLogic_AbortedCommandNotFound:
- case BusLogic_InvalidCCB:
- BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
+ switch (ccb->comp_code) {
+ case BLOGIC_INBOX_FREE:
+ case BLOGIC_CMD_NOTFOUND:
+ case BLOGIC_INVALID_CCB:
+ blogic_warn("CCB #%ld to Target %d Impossible State\n", adapter, ccb->serial, ccb->tgt_id);
break;
- case BusLogic_CommandCompletedWithoutError:
- HostAdapter->TargetStatistics[CCB->TargetID]
- .CommandsCompleted++;
- HostAdapter->TargetFlags[CCB->TargetID]
- .CommandSuccessfulFlag = true;
- Command->result = DID_OK << 16;
+ case BLOGIC_CMD_COMPLETE_GOOD:
+ adapter->tgt_stats[ccb->tgt_id]
+ .cmds_complete++;
+ adapter->tgt_flags[ccb->tgt_id]
+ .cmd_good = true;
+ command->result = DID_OK << 16;
break;
- case BusLogic_CommandAbortedAtHostRequest:
- BusLogic_Warning("CCB #%ld to Target %d Aborted\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
- BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID]
- .CommandAbortsCompleted);
- Command->result = DID_ABORT << 16;
+ case BLOGIC_CMD_ABORT_BY_HOST:
+ blogic_warn("CCB #%ld to Target %d Aborted\n",
+ adapter, ccb->serial, ccb->tgt_id);
+ blogic_inc_count(&adapter->tgt_stats[ccb->tgt_id].aborts_done);
+ command->result = DID_ABORT << 16;
break;
- case BusLogic_CommandCompletedWithError:
- Command->result = BusLogic_ComputeResultCode(HostAdapter, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
- if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) {
- HostAdapter->TargetStatistics[CCB->TargetID]
- .CommandsCompleted++;
- if (BusLogic_GlobalOptions.TraceErrors) {
+ case BLOGIC_CMD_COMPLETE_ERROR:
+ command->result = blogic_resultcode(adapter,
+ ccb->adapter_status, ccb->tgt_status);
+ if (ccb->adapter_status != BLOGIC_SELECT_TIMEOUT) {
+ adapter->tgt_stats[ccb->tgt_id]
+ .cmds_complete++;
+ if (blogic_global_options.trace_err) {
int i;
- BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
- "Adapter Status %02X " "Target Status %02X\n", HostAdapter, CCB->SerialNumber, CCB->TargetID, Command->result, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
- BusLogic_Notice("CDB ", HostAdapter);
- for (i = 0; i < CCB->CDB_Length; i++)
- BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
- BusLogic_Notice("\n", HostAdapter);
- BusLogic_Notice("Sense ", HostAdapter);
- for (i = 0; i < CCB->SenseDataLength; i++)
- BusLogic_Notice(" %02X", HostAdapter, Command->sense_buffer[i]);
- BusLogic_Notice("\n", HostAdapter);
+ blogic_notice("CCB #%ld Target %d: Result %X Host "
+ "Adapter Status %02X " "Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
+ blogic_notice("CDB ", adapter);
+ for (i = 0; i < ccb->cdblen; i++)
+ blogic_notice(" %02X", adapter, ccb->cdb[i]);
+ blogic_notice("\n", adapter);
+ blogic_notice("Sense ", adapter);
+ for (i = 0; i < ccb->sense_datalen; i++)
+ blogic_notice(" %02X", adapter, command->sense_buffer[i]);
+ blogic_notice("\n", adapter);
}
}
break;
@@ -2641,141 +2849,145 @@ static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapt
CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
Wide Data Transfers Supported) bits.
*/
- if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
- struct SCSI_Inquiry *InquiryResult =
- (struct SCSI_Inquiry *) scsi_sglist(Command);
- TargetFlags->TargetExists = true;
- TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
- TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
+ if (ccb->cdb[0] == INQUIRY && ccb->cdb[1] == 0 &&
+ ccb->adapter_status == BLOGIC_CMD_CMPLT_NORMAL) {
+ struct blogic_tgt_flags *tgt_flags =
+ &adapter->tgt_flags[ccb->tgt_id];
+ struct scsi_inquiry *inquiry =
+ (struct scsi_inquiry *) scsi_sglist(command);
+ tgt_flags->tgt_exists = true;
+ tgt_flags->tagq_ok = inquiry->CmdQue;
+ tgt_flags->wide_ok = inquiry->WBus16;
}
/*
Place CCB back on the Host Adapter's free list.
*/
- BusLogic_DeallocateCCB(CCB);
+ blogic_dealloc_ccb(ccb);
/*
Call the SCSI Command Completion Routine.
*/
- Command->scsi_done(Command);
+ command->scsi_done(command);
}
}
- HostAdapter->ProcessCompletedCCBsActive = false;
+ adapter->processing_ccbs = false;
}
/*
- BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
+ blogic_inthandler handles hardware interrupts from BusLogic Host
Adapters.
*/
-static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier)
+static irqreturn_t blogic_inthandler(int irq_ch, void *devid)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier;
- unsigned long ProcessorFlags;
+ struct blogic_adapter *adapter = (struct blogic_adapter *) devid;
+ unsigned long processor_flag;
/*
Acquire exclusive access to Host Adapter.
*/
- spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
+ spin_lock_irqsave(adapter->scsi_host->host_lock, processor_flag);
/*
Handle Interrupts appropriately for each Host Adapter type.
*/
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
- union BusLogic_InterruptRegister InterruptRegister;
+ if (blogic_multimaster_type(adapter)) {
+ union blogic_int_reg intreg;
/*
Read the Host Adapter Interrupt Register.
*/
- InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
- if (InterruptRegister.ir.InterruptValid) {
+ intreg.all = blogic_rdint(adapter);
+ if (intreg.ir.int_valid) {
/*
Acknowledge the interrupt and reset the Host Adapter
Interrupt Register.
*/
- BusLogic_InterruptReset(HostAdapter);
+ blogic_intreset(adapter);
/*
- Process valid External SCSI Bus Reset and Incoming Mailbox
- Loaded Interrupts. Command Complete Interrupts are noted,
- and Outgoing Mailbox Available Interrupts are ignored, as
- they are never enabled.
+ Process valid External SCSI Bus Reset and Incoming
+ Mailbox Loaded Interrupts. Command Complete
+ Interrupts are noted, and Outgoing Mailbox Available
+ Interrupts are ignored, as they are never enabled.
*/
- if (InterruptRegister.ir.ExternalBusReset)
- HostAdapter->HostAdapterExternalReset = true;
- else if (InterruptRegister.ir.IncomingMailboxLoaded)
- BusLogic_ScanIncomingMailboxes(HostAdapter);
- else if (InterruptRegister.ir.CommandComplete)
- HostAdapter->HostAdapterCommandCompleted = true;
+ if (intreg.ir.ext_busreset)
+ adapter->adapter_extreset = true;
+ else if (intreg.ir.mailin_loaded)
+ blogic_scan_inbox(adapter);
+ else if (intreg.ir.cmd_complete)
+ adapter->adapter_cmd_complete = true;
}
} else {
/*
Check if there is a pending interrupt for this Host Adapter.
*/
- if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
- switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) {
- case FlashPoint_NormalInterrupt:
+ if (FlashPoint_InterruptPending(adapter->cardhandle))
+ switch (FlashPoint_HandleInterrupt(adapter->cardhandle)) {
+ case FPOINT_NORMAL_INT:
break;
- case FlashPoint_ExternalBusReset:
- HostAdapter->HostAdapterExternalReset = true;
+ case FPOINT_EXT_RESET:
+ adapter->adapter_extreset = true;
break;
- case FlashPoint_InternalError:
- BusLogic_Warning("Internal FlashPoint Error detected" " - Resetting Host Adapter\n", HostAdapter);
- HostAdapter->HostAdapterInternalError = true;
+ case FPOINT_INTERN_ERR:
+ blogic_warn("Internal FlashPoint Error detected - Resetting Host Adapter\n", adapter);
+ adapter->adapter_intern_err = true;
break;
}
}
/*
Process any completed CCBs.
*/
- if (HostAdapter->FirstCompletedCCB != NULL)
- BusLogic_ProcessCompletedCCBs(HostAdapter);
+ if (adapter->firstccb != NULL)
+ blogic_process_ccbs(adapter);
/*
Reset the Host Adapter if requested.
*/
- if (HostAdapter->HostAdapterExternalReset) {
- BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", HostAdapter, HostAdapter->FullModelName);
- BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
- BusLogic_ResetHostAdapter(HostAdapter, false);
- HostAdapter->HostAdapterExternalReset = false;
- } else if (HostAdapter->HostAdapterInternalError) {
- BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", HostAdapter, HostAdapter->FullModelName);
- BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
- BusLogic_ResetHostAdapter(HostAdapter, true);
- HostAdapter->HostAdapterInternalError = false;
+ if (adapter->adapter_extreset) {
+ blogic_warn("Resetting %s due to External SCSI Bus Reset\n", adapter, adapter->full_model);
+ blogic_inc_count(&adapter->ext_resets);
+ blogic_resetadapter(adapter, false);
+ adapter->adapter_extreset = false;
+ } else if (adapter->adapter_intern_err) {
+ blogic_warn("Resetting %s due to Host Adapter Internal Error\n", adapter, adapter->full_model);
+ blogic_inc_count(&adapter->adapter_intern_errors);
+ blogic_resetadapter(adapter, true);
+ adapter->adapter_intern_err = false;
}
/*
Release exclusive access to Host Adapter.
*/
- spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
+ spin_unlock_irqrestore(adapter->scsi_host->host_lock, processor_flag);
return IRQ_HANDLED;
}
/*
- BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
+ blogic_write_outbox places CCB and Action Code into an Outgoing
Mailbox for execution by Host Adapter. The Host Adapter's Lock should
already have been acquired by the caller.
*/
-static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
- *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB)
+static bool blogic_write_outbox(struct blogic_adapter *adapter,
+ enum blogic_action action, struct blogic_ccb *ccb)
{
- struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
- NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
- if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) {
- CCB->Status = BusLogic_CCB_Active;
+ struct blogic_outbox *next_outbox;
+
+ next_outbox = adapter->next_outbox;
+ if (next_outbox->action == BLOGIC_OUTBOX_FREE) {
+ ccb->status = BLOGIC_CCB_ACTIVE;
/*
- The CCB field must be written before the Action Code field since
- the Host Adapter is operating asynchronously and the locking code
- does not protect against simultaneous access by the Host Adapter.
+ The CCB field must be written before the Action Code field
+ since the Host Adapter is operating asynchronously and the
+ locking code does not protect against simultaneous access
+ by the Host Adapter.
*/
- NextOutgoingMailbox->CCB = CCB->DMA_Handle;
- NextOutgoingMailbox->ActionCode = ActionCode;
- BusLogic_StartMailboxCommand(HostAdapter);
- if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
- NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
- HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
- if (ActionCode == BusLogic_MailboxStartCommand) {
- HostAdapter->ActiveCommands[CCB->TargetID]++;
- if (CCB->Opcode != BusLogic_BusDeviceReset)
- HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
+ next_outbox->ccb = ccb->dma_handle;
+ next_outbox->action = action;
+ blogic_execmbox(adapter);
+ if (++next_outbox > adapter->last_outbox)
+ next_outbox = adapter->first_outbox;
+ adapter->next_outbox = next_outbox;
+ if (action == BLOGIC_MBOX_START) {
+ adapter->active_cmds[ccb->tgt_id]++;
+ if (ccb->opcode != BLOGIC_BDR)
+ adapter->tgt_stats[ccb->tgt_id].cmds_tried++;
}
return true;
}
@@ -2784,65 +2996,72 @@ static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
/* Error Handling (EH) support */
-static int BusLogic_host_reset(struct scsi_cmnd * SCpnt)
+static int blogic_hostreset(struct scsi_cmnd *SCpnt)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) SCpnt->device->host->hostdata;
unsigned int id = SCpnt->device->id;
- struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
+ struct blogic_tgt_stats *stats = &adapter->tgt_stats[id];
int rc;
spin_lock_irq(SCpnt->device->host->host_lock);
- BusLogic_IncrementErrorCounter(&stats->HostAdapterResetsRequested);
+ blogic_inc_count(&stats->adatper_reset_req);
- rc = BusLogic_ResetHostAdapter(HostAdapter, false);
+ rc = blogic_resetadapter(adapter, false);
spin_unlock_irq(SCpnt->device->host->host_lock);
return rc;
}
/*
- BusLogic_QueueCommand creates a CCB for Command and places it into an
+ blogic_qcmd creates a CCB for Command and places it into an
Outgoing Mailbox for execution by the associated Host Adapter.
*/
-static int BusLogic_QueueCommand_lck(struct scsi_cmnd *Command, void (*CompletionRoutine) (struct scsi_cmnd *))
+static int blogic_qcmd_lck(struct scsi_cmnd *command,
+ void (*comp_cb) (struct scsi_cmnd *))
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[Command->device->id];
- struct BusLogic_TargetStatistics *TargetStatistics = HostAdapter->TargetStatistics;
- unsigned char *CDB = Command->cmnd;
- int CDB_Length = Command->cmd_len;
- int TargetID = Command->device->id;
- int LogicalUnit = Command->device->lun;
- int BufferLength = scsi_bufflen(Command);
- int Count;
- struct BusLogic_CCB *CCB;
- /*
- SCSI REQUEST_SENSE commands will be executed automatically by the Host
- Adapter for any errors, so they should not be executed explicitly unless
- the Sense Data is zero indicating that no error occurred.
- */
- if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
- Command->result = DID_OK << 16;
- CompletionRoutine(Command);
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) command->device->host->hostdata;
+ struct blogic_tgt_flags *tgt_flags =
+ &adapter->tgt_flags[command->device->id];
+ struct blogic_tgt_stats *tgt_stats = adapter->tgt_stats;
+ unsigned char *cdb = command->cmnd;
+ int cdblen = command->cmd_len;
+ int tgt_id = command->device->id;
+ int lun = command->device->lun;
+ int buflen = scsi_bufflen(command);
+ int count;
+ struct blogic_ccb *ccb;
+
+ /*
+ SCSI REQUEST_SENSE commands will be executed automatically by the
+ Host Adapter for any errors, so they should not be executed
+ explicitly unless the Sense Data is zero indicating that no error
+ occurred.
+ */
+ if (cdb[0] == REQUEST_SENSE && command->sense_buffer[0] != 0) {
+ command->result = DID_OK << 16;
+ comp_cb(command);
return 0;
}
/*
- Allocate a CCB from the Host Adapter's free list. In the unlikely event
- that there are none available and memory allocation fails, wait 1 second
- and try again. If that fails, the Host Adapter is probably hung so signal
- an error as a Host Adapter Hard Reset should be initiated soon.
- */
- CCB = BusLogic_AllocateCCB(HostAdapter);
- if (CCB == NULL) {
- spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
- BusLogic_Delay(1);
- spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
- CCB = BusLogic_AllocateCCB(HostAdapter);
- if (CCB == NULL) {
- Command->result = DID_ERROR << 16;
- CompletionRoutine(Command);
+ Allocate a CCB from the Host Adapter's free list. In the unlikely
+ event that there are none available and memory allocation fails,
+ wait 1 second and try again. If that fails, the Host Adapter is
+ probably hung so signal an error as a Host Adapter Hard Reset
+ should be initiated soon.
+ */
+ ccb = blogic_alloc_ccb(adapter);
+ if (ccb == NULL) {
+ spin_unlock_irq(adapter->scsi_host->host_lock);
+ blogic_delay(1);
+ spin_lock_irq(adapter->scsi_host->host_lock);
+ ccb = blogic_alloc_ccb(adapter);
+ if (ccb == NULL) {
+ command->result = DID_ERROR << 16;
+ comp_cb(command);
return 0;
}
}
@@ -2850,217 +3069,241 @@ static int BusLogic_QueueCommand_lck(struct scsi_cmnd *Command, void (*Completio
/*
Initialize the fields in the BusLogic Command Control Block (CCB).
*/
- Count = scsi_dma_map(Command);
- BUG_ON(Count < 0);
- if (Count) {
+ count = scsi_dma_map(command);
+ BUG_ON(count < 0);
+ if (count) {
struct scatterlist *sg;
int i;
- CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
- CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
+ ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
+ ccb->datalen = count * sizeof(struct blogic_sg_seg);
+ if (blogic_multimaster_type(adapter))
+ ccb->data = (void *)((unsigned int) ccb->dma_handle +
+ ((unsigned long) &ccb->sglist -
+ (unsigned long) ccb));
else
- CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
+ ccb->data = ccb->sglist;
- scsi_for_each_sg(Command, sg, Count, i) {
- CCB->ScatterGatherList[i].SegmentByteCount =
- sg_dma_len(sg);
- CCB->ScatterGatherList[i].SegmentDataPointer =
- sg_dma_address(sg);
+ scsi_for_each_sg(command, sg, count, i) {
+ ccb->sglist[i].segbytes = sg_dma_len(sg);
+ ccb->sglist[i].segdata = sg_dma_address(sg);
}
- } else if (!Count) {
- CCB->Opcode = BusLogic_InitiatorCCB;
- CCB->DataLength = BufferLength;
- CCB->DataPointer = 0;
+ } else if (!count) {
+ ccb->opcode = BLOGIC_INITIATOR_CCB;
+ ccb->datalen = buflen;
+ ccb->data = 0;
}
- switch (CDB[0]) {
+ switch (cdb[0]) {
case READ_6:
case READ_10:
- CCB->DataDirection = BusLogic_DataInLengthChecked;
- TargetStatistics[TargetID].ReadCommands++;
- BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, BufferLength);
- BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
+ ccb->datadir = BLOGIC_DATAIN_CHECKED;
+ tgt_stats[tgt_id].read_cmds++;
+ blogic_addcount(&tgt_stats[tgt_id].bytesread, buflen);
+ blogic_incszbucket(tgt_stats[tgt_id].read_sz_buckets, buflen);
break;
case WRITE_6:
case WRITE_10:
- CCB->DataDirection = BusLogic_DataOutLengthChecked;
- TargetStatistics[TargetID].WriteCommands++;
- BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
- BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
+ ccb->datadir = BLOGIC_DATAOUT_CHECKED;
+ tgt_stats[tgt_id].write_cmds++;
+ blogic_addcount(&tgt_stats[tgt_id].byteswritten, buflen);
+ blogic_incszbucket(tgt_stats[tgt_id].write_sz_buckets, buflen);
break;
default:
- CCB->DataDirection = BusLogic_UncheckedDataTransfer;
+ ccb->datadir = BLOGIC_UNCHECKED_TX;
break;
}
- CCB->CDB_Length = CDB_Length;
- CCB->HostAdapterStatus = 0;
- CCB->TargetDeviceStatus = 0;
- CCB->TargetID = TargetID;
- CCB->LogicalUnit = LogicalUnit;
- CCB->TagEnable = false;
- CCB->LegacyTagEnable = false;
- /*
- BusLogic recommends that after a Reset the first couple of commands that
- are sent to a Target Device be sent in a non Tagged Queue fashion so that
- the Host Adapter and Target Device can establish Synchronous and Wide
- Transfer before Queue Tag messages can interfere with the Synchronous and
- Wide Negotiation messages. By waiting to enable Tagged Queuing until after
- the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
- assured that after a Reset any pending commands are requeued before Tagged
- Queuing is enabled and that the Tagged Queuing message will not occur while
- the partition table is being printed. In addition, some devices do not
- properly handle the transition from non-tagged to tagged commands, so it is
- necessary to wait until there are no pending commands for a target device
+ ccb->cdblen = cdblen;
+ ccb->adapter_status = 0;
+ ccb->tgt_status = 0;
+ ccb->tgt_id = tgt_id;
+ ccb->lun = lun;
+ ccb->tag_enable = false;
+ ccb->legacytag_enable = false;
+ /*
+ BusLogic recommends that after a Reset the first couple of
+ commands that are sent to a Target Device be sent in a non
+ Tagged Queue fashion so that the Host Adapter and Target Device
+ can establish Synchronous and Wide Transfer before Queue Tag
+ messages can interfere with the Synchronous and Wide Negotiation
+ messages. By waiting to enable Tagged Queuing until after the
+ first BLOGIC_MAX_TAG_DEPTH commands have been queued, it is
+ assured that after a Reset any pending commands are requeued
+ before Tagged Queuing is enabled and that the Tagged Queuing
+ message will not occur while the partition table is being printed.
+ In addition, some devices do not properly handle the transition
+ from non-tagged to tagged commands, so it is necessary to wait
+ until there are no pending commands for a target device
before queuing tagged commands.
*/
- if (HostAdapter->CommandsSinceReset[TargetID]++ >=
- BusLogic_MaxTaggedQueueDepth && !TargetFlags->TaggedQueuingActive && HostAdapter->ActiveCommands[TargetID] == 0 && TargetFlags->TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
- TargetFlags->TaggedQueuingActive = true;
- BusLogic_Notice("Tagged Queuing now active for Target %d\n", HostAdapter, TargetID);
- }
- if (TargetFlags->TaggedQueuingActive) {
- enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag;
+ if (adapter->cmds_since_rst[tgt_id]++ >= BLOGIC_MAX_TAG_DEPTH &&
+ !tgt_flags->tagq_active &&
+ adapter->active_cmds[tgt_id] == 0
+ && tgt_flags->tagq_ok &&
+ (adapter->tagq_ok & (1 << tgt_id))) {
+ tgt_flags->tagq_active = true;
+ blogic_notice("Tagged Queuing now active for Target %d\n",
+ adapter, tgt_id);
+ }
+ if (tgt_flags->tagq_active) {
+ enum blogic_queuetag queuetag = BLOGIC_SIMPLETAG;
/*
- When using Tagged Queuing with Simple Queue Tags, it appears that disk
- drive controllers do not guarantee that a queued command will not
- remain in a disconnected state indefinitely if commands that read or
- write nearer the head position continue to arrive without interruption.
- Therefore, for each Target Device this driver keeps track of the last
- time either the queue was empty or an Ordered Queue Tag was issued. If
- more than 4 seconds (one fifth of the 20 second disk timeout) have
- elapsed since this last sequence point, this command will be issued
- with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
- the Target Device to complete all previously queued commands before
- this command may be executed.
+ When using Tagged Queuing with Simple Queue Tags, it
+ appears that disk drive controllers do not guarantee that
+ a queued command will not remain in a disconnected state
+ indefinitely if commands that read or write nearer the
+ head position continue to arrive without interruption.
+ Therefore, for each Target Device this driver keeps track
+ of the last time either the queue was empty or an Ordered
+ Queue Tag was issued. If more than 4 seconds (one fifth
+ of the 20 second disk timeout) have elapsed since this
+ last sequence point, this command will be issued with an
+ Ordered Queue Tag rather than a Simple Queue Tag, which
+ forces the Target Device to complete all previously
+ queued commands before this command may be executed.
*/
- if (HostAdapter->ActiveCommands[TargetID] == 0)
- HostAdapter->LastSequencePoint[TargetID] = jiffies;
- else if (time_after(jiffies, HostAdapter->LastSequencePoint[TargetID] + 4 * HZ)) {
- HostAdapter->LastSequencePoint[TargetID] = jiffies;
- QueueTag = BusLogic_OrderedQueueTag;
+ if (adapter->active_cmds[tgt_id] == 0)
+ adapter->last_seqpoint[tgt_id] = jiffies;
+ else if (time_after(jiffies,
+ adapter->last_seqpoint[tgt_id] + 4 * HZ)) {
+ adapter->last_seqpoint[tgt_id] = jiffies;
+ queuetag = BLOGIC_ORDEREDTAG;
}
- if (HostAdapter->ExtendedLUNSupport) {
- CCB->TagEnable = true;
- CCB->QueueTag = QueueTag;
+ if (adapter->ext_lun) {
+ ccb->tag_enable = true;
+ ccb->queuetag = queuetag;
} else {
- CCB->LegacyTagEnable = true;
- CCB->LegacyQueueTag = QueueTag;
+ ccb->legacytag_enable = true;
+ ccb->legacy_tag = queuetag;
}
}
- memcpy(CCB->CDB, CDB, CDB_Length);
- CCB->SenseDataLength = SCSI_SENSE_BUFFERSIZE;
- CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device, Command->sense_buffer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
- CCB->Command = Command;
- Command->scsi_done = CompletionRoutine;
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+ memcpy(ccb->cdb, cdb, cdblen);
+ ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE;
+ ccb->sensedata = pci_map_single(adapter->pci_device,
+ command->sense_buffer, ccb->sense_datalen,
+ PCI_DMA_FROMDEVICE);
+ ccb->command = command;
+ command->scsi_done = comp_cb;
+ if (blogic_multimaster_type(adapter)) {
/*
- Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI
- Subsystem should not attempt to queue more commands than can be placed
- in Outgoing Mailboxes, so there should always be one free. In the
- unlikely event that there are none available, wait 1 second and try
- again. If that fails, the Host Adapter is probably hung so signal an
- error as a Host Adapter Hard Reset should be initiated soon.
+ Place the CCB in an Outgoing Mailbox. The higher levels
+ of the SCSI Subsystem should not attempt to queue more
+ commands than can be placed in Outgoing Mailboxes, so
+ there should always be one free. In the unlikely event
+ that there are none available, wait 1 second and try
+ again. If that fails, the Host Adapter is probably hung
+ so signal an error as a Host Adapter Hard Reset should
+ be initiated soon.
*/
- if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
- spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
- BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter);
- BusLogic_Delay(1);
- spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
- if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
- BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter);
- BusLogic_DeallocateCCB(CCB);
- Command->result = DID_ERROR << 16;
- Command->scsi_done(Command);
+ if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, ccb)) {
+ spin_unlock_irq(adapter->scsi_host->host_lock);
+ blogic_warn("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", adapter);
+ blogic_delay(1);
+ spin_lock_irq(adapter->scsi_host->host_lock);
+ if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
+ ccb)) {
+ blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter);
+ blogic_dealloc_ccb(ccb);
+ command->result = DID_ERROR << 16;
+ command->scsi_done(command);
}
}
} else {
/*
- Call the FlashPoint SCCB Manager to start execution of the CCB.
+ Call the FlashPoint SCCB Manager to start execution of
+ the CCB.
*/
- CCB->Status = BusLogic_CCB_Active;
- HostAdapter->ActiveCommands[TargetID]++;
- TargetStatistics[TargetID].CommandsAttempted++;
- FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
+ ccb->status = BLOGIC_CCB_ACTIVE;
+ adapter->active_cmds[tgt_id]++;
+ tgt_stats[tgt_id].cmds_tried++;
+ FlashPoint_StartCCB(adapter->cardhandle, ccb);
/*
- The Command may have already completed and BusLogic_QueueCompletedCCB
- been called, or it may still be pending.
+ The Command may have already completed and
+ blogic_qcompleted_ccb been called, or it may still be
+ pending.
*/
- if (CCB->Status == BusLogic_CCB_Completed)
- BusLogic_ProcessCompletedCCBs(HostAdapter);
+ if (ccb->status == BLOGIC_CCB_COMPLETE)
+ blogic_process_ccbs(adapter);
}
return 0;
}
-static DEF_SCSI_QCMD(BusLogic_QueueCommand)
+static DEF_SCSI_QCMD(blogic_qcmd)
#if 0
/*
- BusLogic_AbortCommand aborts Command if possible.
+ blogic_abort aborts Command if possible.
*/
-static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
+static int blogic_abort(struct scsi_cmnd *command)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) command->device->host->hostdata;
+
+ int tgt_id = command->device->id;
+ struct blogic_ccb *ccb;
+ blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_request);
- int TargetID = Command->device->id;
- struct BusLogic_CCB *CCB;
- BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
/*
- Attempt to find an Active CCB for this Command. If no Active CCB for this
- Command is found, then no Abort is necessary.
+ Attempt to find an Active CCB for this Command. If no Active
+ CCB for this Command is found, then no Abort is necessary.
*/
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Command == Command)
+ for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
+ if (ccb->command == command)
break;
- if (CCB == NULL) {
- BusLogic_Warning("Unable to Abort Command to Target %d - " "No CCB Found\n", HostAdapter, TargetID);
+ if (ccb == NULL) {
+ blogic_warn("Unable to Abort Command to Target %d - No CCB Found\n", adapter, tgt_id);
return SUCCESS;
- } else if (CCB->Status == BusLogic_CCB_Completed) {
- BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Completed\n", HostAdapter, TargetID);
+ } else if (ccb->status == BLOGIC_CCB_COMPLETE) {
+ blogic_warn("Unable to Abort Command to Target %d - CCB Completed\n", adapter, tgt_id);
return SUCCESS;
- } else if (CCB->Status == BusLogic_CCB_Reset) {
- BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Reset\n", HostAdapter, TargetID);
+ } else if (ccb->status == BLOGIC_CCB_RESET) {
+ blogic_warn("Unable to Abort Command to Target %d - CCB Reset\n", adapter, tgt_id);
return SUCCESS;
}
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+ if (blogic_multimaster_type(adapter)) {
/*
- Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx
- do not generate Abort Tag messages, but only generate the non-tagged
- Abort message. Since non-tagged commands are not sent by the Host
- Adapter until the queue of outstanding tagged commands has completed,
- and the Abort message is treated as a non-tagged command, it is
- effectively impossible to abort commands when Tagged Queuing is active.
- Firmware version 5.xx does generate Abort Tag messages, so it is
- possible to abort commands when Tagged Queuing is active.
+ Attempt to Abort this CCB. MultiMaster Firmware versions
+ prior to 5.xx do not generate Abort Tag messages, but only
+ generate the non-tagged Abort message. Since non-tagged
+ commands are not sent by the Host Adapter until the queue
+ of outstanding tagged commands has completed, and the
+ Abort message is treated as a non-tagged command, it is
+ effectively impossible to abort commands when Tagged
+ Queuing is active. Firmware version 5.xx does generate
+ Abort Tag messages, so it is possible to abort commands
+ when Tagged Queuing is active.
*/
- if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && HostAdapter->FirmwareVersion[0] < '5') {
- BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "Abort Tag Not Supported\n", HostAdapter, CCB->SerialNumber, TargetID);
+ if (adapter->tgt_flags[tgt_id].tagq_active &&
+ adapter->fw_ver[0] < '5') {
+ blogic_warn("Unable to Abort CCB #%ld to Target %d - Abort Tag Not Supported\n", adapter, ccb->serial, tgt_id);
return FAILURE;
- } else if (BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxAbortCommand, CCB)) {
- BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
- BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
+ } else if (blogic_write_outbox(adapter, BLOGIC_MBOX_ABORT,
+ ccb)) {
+ blogic_warn("Aborting CCB #%ld to Target %d\n",
+ adapter, ccb->serial, tgt_id);
+ blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
return SUCCESS;
} else {
- BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "No Outgoing Mailboxes\n", HostAdapter, CCB->SerialNumber, TargetID);
+ blogic_warn("Unable to Abort CCB #%ld to Target %d - No Outgoing Mailboxes\n", adapter, ccb->serial, tgt_id);
return FAILURE;
}
} else {
/*
- Call the FlashPoint SCCB Manager to abort execution of the CCB.
+ Call the FlashPoint SCCB Manager to abort execution of
+ the CCB.
*/
- BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
- BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
- FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
+ blogic_warn("Aborting CCB #%ld to Target %d\n", adapter,
+ ccb->serial, tgt_id);
+ blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
+ FlashPoint_AbortCCB(adapter->cardhandle, ccb);
/*
The Abort may have already been completed and
- BusLogic_QueueCompletedCCB been called, or it
+ blogic_qcompleted_ccb been called, or it
may still be pending.
*/
- if (CCB->Status == BusLogic_CCB_Completed) {
- BusLogic_ProcessCompletedCCBs(HostAdapter);
- }
+ if (ccb->status == BLOGIC_CCB_COMPLETE)
+ blogic_process_ccbs(adapter);
return SUCCESS;
}
return SUCCESS;
@@ -3068,21 +3311,23 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
#endif
/*
- BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
+ blogic_resetadapter resets Host Adapter if possible, marking all
currently executing SCSI Commands as having been Reset.
*/
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, bool HardReset)
+static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset)
{
- struct BusLogic_CCB *CCB;
- int TargetID;
+ struct blogic_ccb *ccb;
+ int tgt_id;
/*
* Attempt to Reset and Reinitialize the Host Adapter.
*/
- if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(HostAdapter))) {
- BusLogic_Error("Resetting %s Failed\n", HostAdapter, HostAdapter->FullModelName);
+ if (!(blogic_hwreset(adapter, hard_reset) &&
+ blogic_initadapter(adapter))) {
+ blogic_err("Resetting %s Failed\n", adapter,
+ adapter->full_model);
return FAILURE;
}
@@ -3090,9 +3335,9 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, b
* Deallocate all currently executing CCBs.
*/
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Status == BusLogic_CCB_Active)
- BusLogic_DeallocateCCB(CCB);
+ for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
+ if (ccb->status == BLOGIC_CCB_ACTIVE)
+ blogic_dealloc_ccb(ccb);
/*
* Wait a few seconds between the Host Adapter Hard Reset which
* initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
@@ -3100,21 +3345,21 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, b
* after a SCSI Bus Reset.
*/
- if (HardReset) {
- spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
- BusLogic_Delay(HostAdapter->BusSettleTime);
- spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+ if (hard_reset) {
+ spin_unlock_irq(adapter->scsi_host->host_lock);
+ blogic_delay(adapter->bus_settle_time);
+ spin_lock_irq(adapter->scsi_host->host_lock);
}
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- HostAdapter->LastResetAttempted[TargetID] = jiffies;
- HostAdapter->LastResetCompleted[TargetID] = jiffies;
+ for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
+ adapter->last_resettried[tgt_id] = jiffies;
+ adapter->last_resetdone[tgt_id] = jiffies;
}
return SUCCESS;
}
/*
- BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
+ blogic_diskparam returns the Heads/Sectors/Cylinders BIOS Disk
Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
the appropriate number of cylinders so as not to exceed drive capacity. In
order for disks equal to or larger than 1 GB to be addressable by the BIOS
@@ -3130,66 +3375,70 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, b
the BIOS, and a warning may be displayed.
*/
-static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device, sector_t capacity, int *Parameters)
+static int blogic_diskparam(struct scsi_device *sdev, struct block_device *dev,
+ sector_t capacity, int *params)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata;
- struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters;
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) sdev->host->hostdata;
+ struct bios_diskparam *diskparam = (struct bios_diskparam *) params;
unsigned char *buf;
- if (HostAdapter->ExtendedTranslationEnabled && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */ ) {
- if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */ ) {
- DiskParameters->Heads = 255;
- DiskParameters->Sectors = 63;
+
+ if (adapter->ext_trans_enable && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */) {
+ if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */) {
+ diskparam->heads = 255;
+ diskparam->sectors = 63;
} else {
- DiskParameters->Heads = 128;
- DiskParameters->Sectors = 32;
+ diskparam->heads = 128;
+ diskparam->sectors = 32;
}
} else {
- DiskParameters->Heads = 64;
- DiskParameters->Sectors = 32;
+ diskparam->heads = 64;
+ diskparam->sectors = 32;
}
- DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
- buf = scsi_bios_ptable(Device);
+ diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
+ buf = scsi_bios_ptable(dev);
if (buf == NULL)
return 0;
/*
- If the boot sector partition table flag is valid, search for a partition
- table entry whose end_head matches one of the standard BusLogic geometry
- translations (64/32, 128/32, or 255/63).
+ If the boot sector partition table flag is valid, search for
+ a partition table entry whose end_head matches one of the
+ standard BusLogic geometry translations (64/32, 128/32, or 255/63).
*/
if (*(unsigned short *) (buf + 64) == 0xAA55) {
- struct partition *FirstPartitionEntry = (struct partition *) buf;
- struct partition *PartitionEntry = FirstPartitionEntry;
- int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
- unsigned char PartitionEntryEndHead = 0, PartitionEntryEndSector = 0;
- for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) {
- PartitionEntryEndHead = PartitionEntry->end_head;
- PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
- if (PartitionEntryEndHead == 64 - 1) {
- DiskParameters->Heads = 64;
- DiskParameters->Sectors = 32;
+ struct partition *part1_entry = (struct partition *) buf;
+ struct partition *part_entry = part1_entry;
+ int saved_cyl = diskparam->cylinders, part_no;
+ unsigned char part_end_head = 0, part_end_sector = 0;
+
+ for (part_no = 0; part_no < 4; part_no++) {
+ part_end_head = part_entry->end_head;
+ part_end_sector = part_entry->end_sector & 0x3F;
+ if (part_end_head == 64 - 1) {
+ diskparam->heads = 64;
+ diskparam->sectors = 32;
break;
- } else if (PartitionEntryEndHead == 128 - 1) {
- DiskParameters->Heads = 128;
- DiskParameters->Sectors = 32;
+ } else if (part_end_head == 128 - 1) {
+ diskparam->heads = 128;
+ diskparam->sectors = 32;
break;
- } else if (PartitionEntryEndHead == 255 - 1) {
- DiskParameters->Heads = 255;
- DiskParameters->Sectors = 63;
+ } else if (part_end_head == 255 - 1) {
+ diskparam->heads = 255;
+ diskparam->sectors = 63;
break;
}
- PartitionEntry++;
+ part_entry++;
}
- if (PartitionNumber == 4) {
- PartitionEntryEndHead = FirstPartitionEntry->end_head;
- PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
+ if (part_no == 4) {
+ part_end_head = part1_entry->end_head;
+ part_end_sector = part1_entry->end_sector & 0x3F;
}
- DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
- if (PartitionNumber < 4 && PartitionEntryEndSector == DiskParameters->Sectors) {
- if (DiskParameters->Cylinders != SavedCylinders)
- BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
- } else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) {
- BusLogic_Warning("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", HostAdapter, PartitionEntryEndHead + 1, PartitionEntryEndSector);
- BusLogic_Warning("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
+ diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
+ if (part_no < 4 && part_end_sector == diskparam->sectors) {
+ if (diskparam->cylinders != saved_cyl)
+ blogic_warn("Adopting Geometry %d/%d from Partition Table\n", adapter, diskparam->heads, diskparam->sectors);
+ } else if (part_end_head > 0 || part_end_sector > 0) {
+ blogic_warn("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
+ blogic_warn("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", adapter, diskparam->heads, diskparam->sectors);
}
}
kfree(buf);
@@ -3201,186 +3450,182 @@ static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_de
BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
*/
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
+static int blogic_write_info(struct Scsi_Host *shost, char *procbuf,
+ int bytes_avail)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
- struct BusLogic_TargetStatistics *TargetStatistics;
- int TargetID, Length;
- char *Buffer;
-
- TargetStatistics = HostAdapter->TargetStatistics;
- if (WriteFlag) {
- HostAdapter->ExternalHostAdapterResets = 0;
- HostAdapter->HostAdapterInternalErrors = 0;
- memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
- return 0;
- }
- Buffer = HostAdapter->MessageBuffer;
- Length = HostAdapter->MessageBufferLength;
- Length += sprintf(&Buffer[Length], "\n\
+ struct blogic_adapter *adapter =
+ (struct blogic_adapter *) shost->hostdata;
+ struct blogic_tgt_stats *tgt_stats;
+
+ tgt_stats = adapter->tgt_stats;
+ adapter->ext_resets = 0;
+ adapter->adapter_intern_errors = 0;
+ memset(tgt_stats, 0, BLOGIC_MAXDEV * sizeof(struct blogic_tgt_stats));
+ return 0;
+}
+
+static int blogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
+{
+ struct blogic_adapter *adapter = (struct blogic_adapter *) shost->hostdata;
+ struct blogic_tgt_stats *tgt_stats;
+ int tgt;
+
+ tgt_stats = adapter->tgt_stats;
+ seq_write(m, adapter->msgbuf, adapter->msgbuflen);
+ seq_printf(m, "\n\
Current Driver Queue Depth: %d\n\
-Currently Allocated CCBs: %d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs);
- Length += sprintf(&Buffer[Length], "\n\n\
+Currently Allocated CCBs: %d\n", adapter->drvr_qdepth, adapter->alloc_ccbs);
+ seq_printf(m, "\n\n\
DATA TRANSFER STATISTICS\n\
\n\
Target Tagged Queuing Queue Depth Active Attempted Completed\n\
====== ============== =========== ====== ========= =========\n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists)
+ for (tgt = 0; tgt < adapter->maxdev; tgt++) {
+ struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
+ if (!tgt_flags->tgt_exists)
continue;
- Length += sprintf(&Buffer[Length], " %2d %s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? " Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
+ seq_printf(m, " %2d %s", tgt, (tgt_flags->tagq_ok ? (tgt_flags->tagq_active ? " Active" : (adapter->tagq_ok & (1 << tgt)
? " Permitted" : " Disabled"))
: "Not Supported"));
- Length += sprintf(&Buffer[Length],
- " %3d %3u %9u %9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted);
+ seq_printf(m,
+ " %3d %3u %9u %9u\n", adapter->qdepth[tgt], adapter->active_cmds[tgt], tgt_stats[tgt].cmds_tried, tgt_stats[tgt].cmds_complete);
}
- Length += sprintf(&Buffer[Length], "\n\
+ seq_printf(m, "\n\
Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
====== ============= ============== =================== ===================\n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists)
+ for (tgt = 0; tgt < adapter->maxdev; tgt++) {
+ struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
+ if (!tgt_flags->tgt_exists)
continue;
- Length += sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
- if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
- Length += sprintf(&Buffer[Length], " %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
+ seq_printf(m, " %2d %9u %9u", tgt, tgt_stats[tgt].read_cmds, tgt_stats[tgt].write_cmds);
+ if (tgt_stats[tgt].bytesread.billions > 0)
+ seq_printf(m, " %9u%09u", tgt_stats[tgt].bytesread.billions, tgt_stats[tgt].bytesread.units);
else
- Length += sprintf(&Buffer[Length], " %9u", TargetStatistics[TargetID].TotalBytesRead.Units);
- if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
- Length += sprintf(&Buffer[Length], " %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
+ seq_printf(m, " %9u", tgt_stats[tgt].bytesread.units);
+ if (tgt_stats[tgt].byteswritten.billions > 0)
+ seq_printf(m, " %9u%09u\n", tgt_stats[tgt].byteswritten.billions, tgt_stats[tgt].byteswritten.units);
else
- Length += sprintf(&Buffer[Length], " %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
+ seq_printf(m, " %9u\n", tgt_stats[tgt].byteswritten.units);
}
- Length += sprintf(&Buffer[Length], "\n\
+ seq_printf(m, "\n\
Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
====== ======= ========= ========= ========= ========= =========\n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists)
+ for (tgt = 0; tgt < adapter->maxdev; tgt++) {
+ struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
+ if (!tgt_flags->tgt_exists)
continue;
- Length +=
- sprintf(&Buffer[Length],
- " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
- TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
- Length +=
- sprintf(&Buffer[Length],
- " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
- TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
- }
- Length += sprintf(&Buffer[Length], "\n\
+ seq_printf(m,
+ " %2d Read %9u %9u %9u %9u %9u\n", tgt,
+ tgt_stats[tgt].read_sz_buckets[0],
+ tgt_stats[tgt].read_sz_buckets[1], tgt_stats[tgt].read_sz_buckets[2], tgt_stats[tgt].read_sz_buckets[3], tgt_stats[tgt].read_sz_buckets[4]);
+ seq_printf(m,
+ " %2d Write %9u %9u %9u %9u %9u\n", tgt,
+ tgt_stats[tgt].write_sz_buckets[0],
+ tgt_stats[tgt].write_sz_buckets[1], tgt_stats[tgt].write_sz_buckets[2], tgt_stats[tgt].write_sz_buckets[3], tgt_stats[tgt].write_sz_buckets[4]);
+ }
+ seq_printf(m, "\n\
Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
====== ======= ========= ========= ========= ========= =========\n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists)
+ for (tgt = 0; tgt < adapter->maxdev; tgt++) {
+ struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
+ if (!tgt_flags->tgt_exists)
continue;
- Length +=
- sprintf(&Buffer[Length],
- " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
- TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
- Length +=
- sprintf(&Buffer[Length],
- " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
- TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
- }
- Length += sprintf(&Buffer[Length], "\n\n\
+ seq_printf(m,
+ " %2d Read %9u %9u %9u %9u %9u\n", tgt,
+ tgt_stats[tgt].read_sz_buckets[5],
+ tgt_stats[tgt].read_sz_buckets[6], tgt_stats[tgt].read_sz_buckets[7], tgt_stats[tgt].read_sz_buckets[8], tgt_stats[tgt].read_sz_buckets[9]);
+ seq_printf(m,
+ " %2d Write %9u %9u %9u %9u %9u\n", tgt,
+ tgt_stats[tgt].write_sz_buckets[5],
+ tgt_stats[tgt].write_sz_buckets[6], tgt_stats[tgt].write_sz_buckets[7], tgt_stats[tgt].write_sz_buckets[8], tgt_stats[tgt].write_sz_buckets[9]);
+ }
+ seq_printf(m, "\n\n\
ERROR RECOVERY STATISTICS\n\
\n\
Command Aborts Bus Device Resets Host Adapter Resets\n\
Target Requested Completed Requested Completed Requested Completed\n\
ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
- struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists)
+ for (tgt = 0; tgt < adapter->maxdev; tgt++) {
+ struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
+ if (!tgt_flags->tgt_exists)
continue;
- Length += sprintf(&Buffer[Length], "\
- %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted);
- }
- Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
- Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
- if (Length >= BusLogic_MessageBufferSize)
- BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize);
- if ((Length -= Offset) <= 0)
- return 0;
- if (Length >= BytesAvailable)
- Length = BytesAvailable;
- memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
- *StartPointer = ProcBuffer;
- return Length;
+ seq_printf(m, "\
+ %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", tgt, tgt_stats[tgt].aborts_request, tgt_stats[tgt].aborts_tried, tgt_stats[tgt].aborts_done, tgt_stats[tgt].bdr_request, tgt_stats[tgt].bdr_tried, tgt_stats[tgt].bdr_done, tgt_stats[tgt].adatper_reset_req, tgt_stats[tgt].adapter_reset_attempt, tgt_stats[tgt].adapter_reset_done);
+ }
+ seq_printf(m, "\nExternal Host Adapter Resets: %d\n", adapter->ext_resets);
+ seq_printf(m, "Host Adapter Internal Errors: %d\n", adapter->adapter_intern_errors);
+ return 0;
}
/*
- BusLogic_Message prints Driver Messages.
+ blogic_msg prints Driver Messages.
*/
-static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...)
+static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
+ struct blogic_adapter *adapter, ...)
{
- static char Buffer[BusLogic_LineBufferSize];
- static bool BeginningOfLine = true;
- va_list Arguments;
- int Length = 0;
- va_start(Arguments, HostAdapter);
- Length = vsprintf(Buffer, Format, Arguments);
- va_end(Arguments);
- if (MessageLevel == BusLogic_AnnounceLevel) {
- static int AnnouncementLines = 0;
- strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
- HostAdapter->MessageBufferLength += Length;
- if (++AnnouncementLines <= 2)
- printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
- } else if (MessageLevel == BusLogic_InfoLevel) {
- strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
- HostAdapter->MessageBufferLength += Length;
- if (BeginningOfLine) {
- if (Buffer[0] != '\n' || Length > 1)
- printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
+ static char buf[BLOGIC_LINEBUF_SIZE];
+ static bool begin = true;
+ va_list args;
+ int len = 0;
+
+ va_start(args, adapter);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
+ if (msglevel == BLOGIC_ANNOUNCE_LEVEL) {
+ static int msglines = 0;
+ strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
+ adapter->msgbuflen += len;
+ if (++msglines <= 2)
+ printk("%sscsi: %s", blogic_msglevelmap[msglevel], buf);
+ } else if (msglevel == BLOGIC_INFO_LEVEL) {
+ strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
+ adapter->msgbuflen += len;
+ if (begin) {
+ if (buf[0] != '\n' || len > 1)
+ printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
} else
- printk("%s", Buffer);
+ printk("%s", buf);
} else {
- if (BeginningOfLine) {
- if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
- printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
+ if (begin) {
+ if (adapter != NULL && adapter->adapter_initd)
+ printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
else
- printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
+ printk("%s%s", blogic_msglevelmap[msglevel], buf);
} else
- printk("%s", Buffer);
+ printk("%s", buf);
}
- BeginningOfLine = (Buffer[Length - 1] == '\n');
+ begin = (buf[len - 1] == '\n');
}
/*
- BusLogic_ParseKeyword parses an individual option keyword. It returns true
+ blogic_parse parses an individual option keyword. It returns true
and updates the pointer if the keyword is recognized and false otherwise.
*/
-static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
+static bool __init blogic_parse(char **str, char *keyword)
{
- char *Pointer = *StringPointer;
- while (*Keyword != '\0') {
- char StringChar = *Pointer++;
- char KeywordChar = *Keyword++;
- if (StringChar >= 'A' && StringChar <= 'Z')
- StringChar += 'a' - 'Z';
- if (KeywordChar >= 'A' && KeywordChar <= 'Z')
- KeywordChar += 'a' - 'Z';
- if (StringChar != KeywordChar)
+ char *pointer = *str;
+ while (*keyword != '\0') {
+ char strch = *pointer++;
+ char keywordch = *keyword++;
+ if (strch >= 'A' && strch <= 'Z')
+ strch += 'a' - 'Z';
+ if (keywordch >= 'A' && keywordch <= 'Z')
+ keywordch += 'a' - 'Z';
+ if (strch != keywordch)
return false;
}
- *StringPointer = Pointer;
+ *str = pointer;
return true;
}
/*
- BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options
+ blogic_parseopts handles processing of BusLogic Driver Options
specifications.
BusLogic Driver Options may be specified either via the Linux Kernel Command
@@ -3396,164 +3641,177 @@ static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
<file:Documentation/scsi/BusLogic.txt>.
*/
-static int __init BusLogic_ParseDriverOptions(char *OptionsString)
+static int __init blogic_parseopts(char *options)
{
while (true) {
- struct BusLogic_DriverOptions *DriverOptions = &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
- int TargetID;
- memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions));
- while (*OptionsString != '\0' && *OptionsString != ';') {
+ struct blogic_drvr_options *drvr_opts =
+ &blogic_drvr_options[blogic_drvr_options_count++];
+ int tgt_id;
+
+ memset(drvr_opts, 0, sizeof(struct blogic_drvr_options));
+ while (*options != '\0' && *options != ';') {
/* Probing Options. */
- if (BusLogic_ParseKeyword(&OptionsString, "IO:")) {
- unsigned long IO_Address = simple_strtoul(OptionsString, &OptionsString, 0);
- BusLogic_ProbeOptions.LimitedProbeISA = true;
- switch (IO_Address) {
+ if (blogic_parse(&options, "IO:")) {
+ unsigned long io_addr = simple_strtoul(options,
+ &options, 0);
+ blogic_probe_options.limited_isa = true;
+ switch (io_addr) {
case 0x330:
- BusLogic_ProbeOptions.Probe330 = true;
+ blogic_probe_options.probe330 = true;
break;
case 0x334:
- BusLogic_ProbeOptions.Probe334 = true;
+ blogic_probe_options.probe334 = true;
break;
case 0x230:
- BusLogic_ProbeOptions.Probe230 = true;
+ blogic_probe_options.probe230 = true;
break;
case 0x234:
- BusLogic_ProbeOptions.Probe234 = true;
+ blogic_probe_options.probe234 = true;
break;
case 0x130:
- BusLogic_ProbeOptions.Probe130 = true;
+ blogic_probe_options.probe130 = true;
break;
case 0x134:
- BusLogic_ProbeOptions.Probe134 = true;
+ blogic_probe_options.probe134 = true;
break;
default:
- BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, IO_Address);
+ blogic_err("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, io_addr);
return 0;
}
- } else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
- BusLogic_ProbeOptions.NoProbeISA = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
- BusLogic_ProbeOptions.NoProbePCI = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
- BusLogic_ProbeOptions.NoProbe = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
- BusLogic_ProbeOptions.NoSortPCI = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
- BusLogic_ProbeOptions.MultiMasterFirst = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
- BusLogic_ProbeOptions.FlashPointFirst = true;
+ } else if (blogic_parse(&options, "NoProbeISA"))
+ blogic_probe_options.noprobe_isa = true;
+ else if (blogic_parse(&options, "NoProbePCI"))
+ blogic_probe_options.noprobe_pci = true;
+ else if (blogic_parse(&options, "NoProbe"))
+ blogic_probe_options.noprobe = true;
+ else if (blogic_parse(&options, "NoSortPCI"))
+ blogic_probe_options.nosort_pci = true;
+ else if (blogic_parse(&options, "MultiMasterFirst"))
+ blogic_probe_options.multimaster_first = true;
+ else if (blogic_parse(&options, "FlashPointFirst"))
+ blogic_probe_options.flashpoint_first = true;
/* Tagged Queuing Options. */
- else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || BusLogic_ParseKeyword(&OptionsString, "QD:[")) {
- for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
- unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
- if (QueueDepth > BusLogic_MaxTaggedQueueDepth) {
- BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
+ else if (blogic_parse(&options, "QueueDepth:[") ||
+ blogic_parse(&options, "QD:[")) {
+ for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
+ unsigned short qdepth = simple_strtoul(options, &options, 0);
+ if (qdepth > BLOGIC_MAX_TAG_DEPTH) {
+ blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
return 0;
}
- DriverOptions->QueueDepth[TargetID] = QueueDepth;
- if (*OptionsString == ',')
- OptionsString++;
- else if (*OptionsString == ']')
+ drvr_opts->qdepth[tgt_id] = qdepth;
+ if (*options == ',')
+ options++;
+ else if (*options == ']')
break;
else {
- BusLogic_Error("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, OptionsString);
+ blogic_err("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, options);
return 0;
}
}
- if (*OptionsString != ']') {
- BusLogic_Error("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, OptionsString);
+ if (*options != ']') {
+ blogic_err("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, options);
return 0;
} else
- OptionsString++;
- } else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || BusLogic_ParseKeyword(&OptionsString, "QD:")) {
- unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
- if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) {
- BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
+ options++;
+ } else if (blogic_parse(&options, "QueueDepth:") || blogic_parse(&options, "QD:")) {
+ unsigned short qdepth = simple_strtoul(options, &options, 0);
+ if (qdepth == 0 ||
+ qdepth > BLOGIC_MAX_TAG_DEPTH) {
+ blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
return 0;
}
- DriverOptions->CommonQueueDepth = QueueDepth;
- for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
- DriverOptions->QueueDepth[TargetID] = QueueDepth;
- } else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || BusLogic_ParseKeyword(&OptionsString, "TQ:")) {
- if (BusLogic_ParseKeyword(&OptionsString, "Default")) {
- DriverOptions->TaggedQueuingPermitted = 0x0000;
- DriverOptions->TaggedQueuingPermittedMask = 0x0000;
- } else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) {
- DriverOptions->TaggedQueuingPermitted = 0xFFFF;
- DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
- } else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) {
- DriverOptions->TaggedQueuingPermitted = 0x0000;
- DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
+ drvr_opts->common_qdepth = qdepth;
+ for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
+ drvr_opts->qdepth[tgt_id] = qdepth;
+ } else if (blogic_parse(&options, "TaggedQueuing:") ||
+ blogic_parse(&options, "TQ:")) {
+ if (blogic_parse(&options, "Default")) {
+ drvr_opts->tagq_ok = 0x0000;
+ drvr_opts->tagq_ok_mask = 0x0000;
+ } else if (blogic_parse(&options, "Enable")) {
+ drvr_opts->tagq_ok = 0xFFFF;
+ drvr_opts->tagq_ok_mask = 0xFFFF;
+ } else if (blogic_parse(&options, "Disable")) {
+ drvr_opts->tagq_ok = 0x0000;
+ drvr_opts->tagq_ok_mask = 0xFFFF;
} else {
- unsigned short TargetBit;
- for (TargetID = 0, TargetBit = 1; TargetID < BusLogic_MaxTargetDevices; TargetID++, TargetBit <<= 1)
- switch (*OptionsString++) {
+ unsigned short tgt_bit;
+ for (tgt_id = 0, tgt_bit = 1;
+ tgt_id < BLOGIC_MAXDEV;
+ tgt_id++, tgt_bit <<= 1)
+ switch (*options++) {
case 'Y':
- DriverOptions->TaggedQueuingPermitted |= TargetBit;
- DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+ drvr_opts->tagq_ok |= tgt_bit;
+ drvr_opts->tagq_ok_mask |= tgt_bit;
break;
case 'N':
- DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
- DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+ drvr_opts->tagq_ok &= ~tgt_bit;
+ drvr_opts->tagq_ok_mask |= tgt_bit;
break;
case 'X':
break;
default:
- OptionsString--;
- TargetID = BusLogic_MaxTargetDevices;
+ options--;
+ tgt_id = BLOGIC_MAXDEV;
break;
}
}
}
/* Miscellaneous Options. */
- else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || BusLogic_ParseKeyword(&OptionsString, "BST:")) {
- unsigned short BusSettleTime = simple_strtoul(OptionsString, &OptionsString, 0);
- if (BusSettleTime > 5 * 60) {
- BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, BusSettleTime);
+ else if (blogic_parse(&options, "BusSettleTime:") ||
+ blogic_parse(&options, "BST:")) {
+ unsigned short bus_settle_time =
+ simple_strtoul(options, &options, 0);
+ if (bus_settle_time > 5 * 60) {
+ blogic_err("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
return 0;
}
- DriverOptions->BusSettleTime = BusSettleTime;
- } else if (BusLogic_ParseKeyword(&OptionsString, "InhibitTargetInquiry"))
- DriverOptions->LocalOptions.InhibitTargetInquiry = true;
+ drvr_opts->bus_settle_time = bus_settle_time;
+ } else if (blogic_parse(&options,
+ "InhibitTargetInquiry"))
+ drvr_opts->stop_tgt_inquiry = true;
/* Debugging Options. */
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
- BusLogic_GlobalOptions.TraceProbe = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
- BusLogic_GlobalOptions.TraceHardwareReset = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
- BusLogic_GlobalOptions.TraceConfiguration = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
- BusLogic_GlobalOptions.TraceErrors = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) {
- BusLogic_GlobalOptions.TraceProbe = true;
- BusLogic_GlobalOptions.TraceHardwareReset = true;
- BusLogic_GlobalOptions.TraceConfiguration = true;
- BusLogic_GlobalOptions.TraceErrors = true;
+ else if (blogic_parse(&options, "TraceProbe"))
+ blogic_global_options.trace_probe = true;
+ else if (blogic_parse(&options, "TraceHardwareReset"))
+ blogic_global_options.trace_hw_reset = true;
+ else if (blogic_parse(&options, "TraceConfiguration"))
+ blogic_global_options.trace_config = true;
+ else if (blogic_parse(&options, "TraceErrors"))
+ blogic_global_options.trace_err = true;
+ else if (blogic_parse(&options, "Debug")) {
+ blogic_global_options.trace_probe = true;
+ blogic_global_options.trace_hw_reset = true;
+ blogic_global_options.trace_config = true;
+ blogic_global_options.trace_err = true;
}
- if (*OptionsString == ',')
- OptionsString++;
- else if (*OptionsString != ';' && *OptionsString != '\0') {
- BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, OptionsString);
- *OptionsString = '\0';
+ if (*options == ',')
+ options++;
+ else if (*options != ';' && *options != '\0') {
+ blogic_err("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, options);
+ *options = '\0';
}
}
- if (!(BusLogic_DriverOptionsCount == 0 || BusLogic_ProbeInfoCount == 0 || BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) {
- BusLogic_Error("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
+ if (!(blogic_drvr_options_count == 0 ||
+ blogic_probeinfo_count == 0 ||
+ blogic_drvr_options_count == blogic_probeinfo_count)) {
+ blogic_err("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
return 0;
}
/*
Tagged Queuing is disabled when the Queue Depth is 1 since queuing
multiple commands is not possible.
*/
- for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
- if (DriverOptions->QueueDepth[TargetID] == 1) {
- unsigned short TargetBit = 1 << TargetID;
- DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
- DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+ for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
+ if (drvr_opts->qdepth[tgt_id] == 1) {
+ unsigned short tgt_bit = 1 << tgt_id;
+ drvr_opts->tagq_ok &= ~tgt_bit;
+ drvr_opts->tagq_ok_mask |= tgt_bit;
}
- if (*OptionsString == ';')
- OptionsString++;
- if (*OptionsString == '\0')
+ if (*options == ';')
+ options++;
+ if (*options == '\0')
return 0;
}
return 1;
@@ -3563,18 +3821,19 @@ static int __init BusLogic_ParseDriverOptions(char *OptionsString)
Get it all started
*/
-static struct scsi_host_template Bus_Logic_template = {
+static struct scsi_host_template blogic_template = {
.module = THIS_MODULE,
.proc_name = "BusLogic",
- .proc_info = BusLogic_ProcDirectoryInfo,
+ .write_info = blogic_write_info,
+ .show_info = blogic_show_info,
.name = "BusLogic",
- .info = BusLogic_DriverInfo,
- .queuecommand = BusLogic_QueueCommand,
- .slave_configure = BusLogic_SlaveConfigure,
- .bios_param = BusLogic_BIOSDiskParameters,
- .eh_host_reset_handler = BusLogic_host_reset,
+ .info = blogic_drvr_info,
+ .queuecommand = blogic_qcmd,
+ .slave_configure = blogic_slaveconfig,
+ .bios_param = blogic_diskparam,
+ .eh_host_reset_handler = blogic_hostreset,
#if 0
- .eh_abort_handler = BusLogic_AbortCommand,
+ .eh_abort_handler = blogic_abort,
#endif
.unchecked_isa_dma = 1,
.max_sectors = 128,
@@ -3582,40 +3841,40 @@ static struct scsi_host_template Bus_Logic_template = {
};
/*
- BusLogic_Setup handles processing of Kernel Command Line Arguments.
+ blogic_setup handles processing of Kernel Command Line Arguments.
*/
-static int __init BusLogic_Setup(char *str)
+static int __init blogic_setup(char *str)
{
int ints[3];
(void) get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] != 0) {
- BusLogic_Error("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
+ blogic_err("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
return 0;
}
if (str == NULL || *str == '\0')
return 0;
- return BusLogic_ParseDriverOptions(str);
+ return blogic_parseopts(str);
}
/*
* Exit function. Deletes all hosts associated with this driver.
*/
-static void __exit BusLogic_exit(void)
+static void __exit blogic_exit(void)
{
- struct BusLogic_HostAdapter *ha, *next;
+ struct blogic_adapter *ha, *next;
- list_for_each_entry_safe(ha, next, &BusLogic_host_list, host_list)
- BusLogic_ReleaseHostAdapter(ha);
+ list_for_each_entry_safe(ha, next, &blogic_host_list, host_list)
+ blogic_deladapter(ha);
}
-__setup("BusLogic=", BusLogic_Setup);
+__setup("BusLogic=", blogic_setup);
#ifdef MODULE
-static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
+/*static struct pci_device_id blogic_pci_tbl[] = {
{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
@@ -3623,9 +3882,15 @@ static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ }
+};*/
+static DEFINE_PCI_DEVICE_TABLE(blogic_pci_tbl) = {
+ {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
+ {0, },
};
#endif
-MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl);
+MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
-module_init(BusLogic_init);
-module_exit(BusLogic_exit);
+module_init(blogic_init);
+module_exit(blogic_exit);
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 649fcb3..b53ec2f 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -37,14 +37,14 @@
Define the maximum number of BusLogic Host Adapters supported by this driver.
*/
-#define BusLogic_MaxHostAdapters 16
+#define BLOGIC_MAX_ADAPTERS 16
/*
Define the maximum number of Target Devices supported by this driver.
*/
-#define BusLogic_MaxTargetDevices 16
+#define BLOGIC_MAXDEV 16
/*
@@ -53,7 +53,7 @@
large as the largest single request generated by the I/O Subsystem.
*/
-#define BusLogic_ScatterGatherLimit 128
+#define BLOGIC_SG_LIMIT 128
/*
@@ -62,12 +62,12 @@
Tagged Queuing and whether or not ISA Bounce Buffers are required.
*/
-#define BusLogic_MaxTaggedQueueDepth 64
-#define BusLogic_MaxAutomaticTaggedQueueDepth 28
-#define BusLogic_MinAutomaticTaggedQueueDepth 7
-#define BusLogic_TaggedQueueDepthBB 3
-#define BusLogic_UntaggedQueueDepth 3
-#define BusLogic_UntaggedQueueDepthBB 2
+#define BLOGIC_MAX_TAG_DEPTH 64
+#define BLOGIC_MAX_AUTO_TAG_DEPTH 28
+#define BLOGIC_MIN_AUTO_TAG_DEPTH 7
+#define BLOGIC_TAG_DEPTH_BB 3
+#define BLOGIC_UNTAG_DEPTH 3
+#define BLOGIC_UNTAG_DEPTH_BB 2
/*
@@ -77,7 +77,7 @@
a SCSI Bus Reset.
*/
-#define BusLogic_DefaultBusSettleTime 2
+#define BLOGIC_BUS_SETTLE_TIME 2
/*
@@ -87,7 +87,7 @@
does not cross an allocation block size boundary.
*/
-#define BusLogic_MaxMailboxes 211
+#define BLOGIC_MAX_MAILBOX 211
/*
@@ -95,50 +95,50 @@
Kernel memory allocation.
*/
-#define BusLogic_CCB_AllocationGroupSize 7
+#define BLOGIC_CCB_GRP_ALLOCSIZE 7
/*
Define the Host Adapter Line and Message Buffer Sizes.
*/
-#define BusLogic_LineBufferSize 100
-#define BusLogic_MessageBufferSize 9700
+#define BLOGIC_LINEBUF_SIZE 100
+#define BLOGIC_MSGBUF_SIZE 9700
/*
Define the Driver Message Levels.
*/
-enum BusLogic_MessageLevel {
- BusLogic_AnnounceLevel = 0,
- BusLogic_InfoLevel = 1,
- BusLogic_NoticeLevel = 2,
- BusLogic_WarningLevel = 3,
- BusLogic_ErrorLevel = 4
+enum blogic_msglevel {
+ BLOGIC_ANNOUNCE_LEVEL = 0,
+ BLOGIC_INFO_LEVEL = 1,
+ BLOGIC_NOTICE_LEVEL = 2,
+ BLOGIC_WARN_LEVEL = 3,
+ BLOGIC_ERR_LEVEL = 4
};
-static char *BusLogic_MessageLevelMap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
+static char *blogic_msglevelmap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
/*
Define Driver Message macros.
*/
-#define BusLogic_Announce(Format, Arguments...) \
- BusLogic_Message(BusLogic_AnnounceLevel, Format, ##Arguments)
+#define blogic_announce(format, args...) \
+ blogic_msg(BLOGIC_ANNOUNCE_LEVEL, format, ##args)
-#define BusLogic_Info(Format, Arguments...) \
- BusLogic_Message(BusLogic_InfoLevel, Format, ##Arguments)
+#define blogic_info(format, args...) \
+ blogic_msg(BLOGIC_INFO_LEVEL, format, ##args)
-#define BusLogic_Notice(Format, Arguments...) \
- BusLogic_Message(BusLogic_NoticeLevel, Format, ##Arguments)
+#define blogic_notice(format, args...) \
+ blogic_msg(BLOGIC_NOTICE_LEVEL, format, ##args)
-#define BusLogic_Warning(Format, Arguments...) \
- BusLogic_Message(BusLogic_WarningLevel, Format, ##Arguments)
+#define blogic_warn(format, args...) \
+ blogic_msg(BLOGIC_WARN_LEVEL, format, ##args)
-#define BusLogic_Error(Format, Arguments...) \
- BusLogic_Message(BusLogic_ErrorLevel, Format, ##Arguments)
+#define blogic_err(format, args...) \
+ blogic_msg(BLOGIC_ERR_LEVEL, format, ##args)
/*
@@ -146,15 +146,15 @@ static char *BusLogic_MessageLevelMap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTIC
of I/O Addresses required by each type.
*/
-enum BusLogic_HostAdapterType {
- BusLogic_MultiMaster = 1,
- BusLogic_FlashPoint = 2
+enum blogic_adapter_type {
+ BLOGIC_MULTIMASTER = 1,
+ BLOGIC_FLASHPOINT = 2
} PACKED;
-#define BusLogic_MultiMasterAddressCount 4
-#define BusLogic_FlashPointAddressCount 256
+#define BLOGIC_MULTIMASTER_ADDR_COUNT 4
+#define BLOGIC_FLASHPOINT_ADDR_COUNT 256
-static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
+static int blogic_adapter_addr_count[3] = { 0, BLOGIC_MULTIMASTER_ADDR_COUNT, BLOGIC_FLASHPOINT_ADDR_COUNT };
/*
@@ -163,19 +163,16 @@ static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddres
#ifdef CONFIG_SCSI_FLASHPOINT
-#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
- (HostAdapter->HostAdapterType == BusLogic_MultiMaster)
+#define blogic_multimaster_type(adapter) \
+ (adapter->adapter_type == BLOGIC_MULTIMASTER)
-#define BusLogic_FlashPointHostAdapterP(HostAdapter) \
- (HostAdapter->HostAdapterType == BusLogic_FlashPoint)
+#define blogic_flashpoint_type(adapter) \
+ (adapter->adapter_type == BLOGIC_FLASHPOINT)
#else
-#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
- (true)
-
-#define BusLogic_FlashPointHostAdapterP(HostAdapter) \
- (false)
+#define blogic_multimaster_type(adapter) (true)
+#define blogic_flashpoint_type(adapter) (false)
#endif
@@ -184,35 +181,35 @@ static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddres
Define the possible Host Adapter Bus Types.
*/
-enum BusLogic_HostAdapterBusType {
- BusLogic_Unknown_Bus = 0,
- BusLogic_ISA_Bus = 1,
- BusLogic_EISA_Bus = 2,
- BusLogic_PCI_Bus = 3,
- BusLogic_VESA_Bus = 4,
- BusLogic_MCA_Bus = 5
+enum blogic_adapter_bus_type {
+ BLOGIC_UNKNOWN_BUS = 0,
+ BLOGIC_ISA_BUS = 1,
+ BLOGIC_EISA_BUS = 2,
+ BLOGIC_PCI_BUS = 3,
+ BLOGIC_VESA_BUS = 4,
+ BLOGIC_MCA_BUS = 5
} PACKED;
-static char *BusLogic_HostAdapterBusNames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
+static char *blogic_adapter_busnames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
-static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] = {
- BusLogic_VESA_Bus, /* BT-4xx */
- BusLogic_ISA_Bus, /* BT-5xx */
- BusLogic_MCA_Bus, /* BT-6xx */
- BusLogic_EISA_Bus, /* BT-7xx */
- BusLogic_Unknown_Bus, /* BT-8xx */
- BusLogic_PCI_Bus /* BT-9xx */
+static enum blogic_adapter_bus_type blogic_adater_bus_types[] = {
+ BLOGIC_VESA_BUS, /* BT-4xx */
+ BLOGIC_ISA_BUS, /* BT-5xx */
+ BLOGIC_MCA_BUS, /* BT-6xx */
+ BLOGIC_EISA_BUS, /* BT-7xx */
+ BLOGIC_UNKNOWN_BUS, /* BT-8xx */
+ BLOGIC_PCI_BUS /* BT-9xx */
};
/*
Define the possible Host Adapter BIOS Disk Geometry Translations.
*/
-enum BusLogic_BIOS_DiskGeometryTranslation {
- BusLogic_BIOS_Disk_Not_Installed = 0,
- BusLogic_BIOS_Disk_Installed_64x32 = 1,
- BusLogic_BIOS_Disk_Installed_128x32 = 2,
- BusLogic_BIOS_Disk_Installed_255x63 = 3
+enum blogic_bios_diskgeometry {
+ BLOGIC_BIOS_NODISK = 0,
+ BLOGIC_BIOS_DISK64x32 = 1,
+ BLOGIC_BIOS_DISK128x32 = 2,
+ BLOGIC_BIOS_DISK255x63 = 3
} PACKED;
@@ -220,9 +217,9 @@ enum BusLogic_BIOS_DiskGeometryTranslation {
Define a 10^18 Statistics Byte Counter data type.
*/
-struct BusLogic_ByteCounter {
- unsigned int Units;
- unsigned int Billions;
+struct blogic_byte_count {
+ unsigned int units;
+ unsigned int billions;
};
@@ -230,79 +227,71 @@ struct BusLogic_ByteCounter {
Define the structure for I/O Address and Bus Probing Information.
*/
-struct BusLogic_ProbeInfo {
- enum BusLogic_HostAdapterType HostAdapterType;
- enum BusLogic_HostAdapterBusType HostAdapterBusType;
- unsigned long IO_Address;
- unsigned long PCI_Address;
- struct pci_dev *PCI_Device;
- unsigned char Bus;
- unsigned char Device;
- unsigned char IRQ_Channel;
+struct blogic_probeinfo {
+ enum blogic_adapter_type adapter_type;
+ enum blogic_adapter_bus_type adapter_bus_type;
+ unsigned long io_addr;
+ unsigned long pci_addr;
+ struct pci_dev *pci_device;
+ unsigned char bus;
+ unsigned char dev;
+ unsigned char irq_ch;
};
/*
Define the Probe Options.
*/
-struct BusLogic_ProbeOptions {
- bool NoProbe:1; /* Bit 0 */
- bool NoProbeISA:1; /* Bit 1 */
- bool NoProbePCI:1; /* Bit 2 */
- bool NoSortPCI:1; /* Bit 3 */
- bool MultiMasterFirst:1;/* Bit 4 */
- bool FlashPointFirst:1; /* Bit 5 */
- bool LimitedProbeISA:1; /* Bit 6 */
- bool Probe330:1; /* Bit 7 */
- bool Probe334:1; /* Bit 8 */
- bool Probe230:1; /* Bit 9 */
- bool Probe234:1; /* Bit 10 */
- bool Probe130:1; /* Bit 11 */
- bool Probe134:1; /* Bit 12 */
+struct blogic_probe_options {
+ bool noprobe:1; /* Bit 0 */
+ bool noprobe_isa:1; /* Bit 1 */
+ bool noprobe_pci:1; /* Bit 2 */
+ bool nosort_pci:1; /* Bit 3 */
+ bool multimaster_first:1; /* Bit 4 */
+ bool flashpoint_first:1; /* Bit 5 */
+ bool limited_isa:1; /* Bit 6 */
+ bool probe330:1; /* Bit 7 */
+ bool probe334:1; /* Bit 8 */
+ bool probe230:1; /* Bit 9 */
+ bool probe234:1; /* Bit 10 */
+ bool probe130:1; /* Bit 11 */
+ bool probe134:1; /* Bit 12 */
};
/*
Define the Global Options.
*/
-struct BusLogic_GlobalOptions {
- bool TraceProbe:1; /* Bit 0 */
- bool TraceHardwareReset:1; /* Bit 1 */
- bool TraceConfiguration:1; /* Bit 2 */
- bool TraceErrors:1; /* Bit 3 */
-};
-
-/*
- Define the Local Options.
-*/
-
-struct BusLogic_LocalOptions {
- bool InhibitTargetInquiry:1; /* Bit 0 */
+struct blogic_global_options {
+ bool trace_probe:1; /* Bit 0 */
+ bool trace_hw_reset:1; /* Bit 1 */
+ bool trace_config:1; /* Bit 2 */
+ bool trace_err:1; /* Bit 3 */
};
/*
Define the BusLogic SCSI Host Adapter I/O Register Offsets.
*/
-#define BusLogic_ControlRegisterOffset 0 /* WO register */
-#define BusLogic_StatusRegisterOffset 0 /* RO register */
-#define BusLogic_CommandParameterRegisterOffset 1 /* WO register */
-#define BusLogic_DataInRegisterOffset 1 /* RO register */
-#define BusLogic_InterruptRegisterOffset 2 /* RO register */
-#define BusLogic_GeometryRegisterOffset 3 /* RO register */
+#define BLOGIC_CNTRL_REG 0 /* WO register */
+#define BLOGIC_STATUS_REG 0 /* RO register */
+#define BLOGIC_CMD_PARM_REG 1 /* WO register */
+#define BLOGIC_DATAIN_REG 1 /* RO register */
+#define BLOGIC_INT_REG 2 /* RO register */
+#define BLOGIC_GEOMETRY_REG 3 /* RO register */
/*
Define the structure of the write-only Control Register.
*/
-union BusLogic_ControlRegister {
- unsigned char All;
+union blogic_cntrl_reg {
+ unsigned char all;
struct {
unsigned char:4; /* Bits 0-3 */
- bool SCSIBusReset:1; /* Bit 4 */
- bool InterruptReset:1; /* Bit 5 */
- bool SoftReset:1; /* Bit 6 */
- bool HardReset:1; /* Bit 7 */
+ bool bus_reset:1; /* Bit 4 */
+ bool int_reset:1; /* Bit 5 */
+ bool soft_reset:1; /* Bit 6 */
+ bool hard_reset:1; /* Bit 7 */
} cr;
};
@@ -310,17 +299,17 @@ union BusLogic_ControlRegister {
Define the structure of the read-only Status Register.
*/
-union BusLogic_StatusRegister {
- unsigned char All;
+union blogic_stat_reg {
+ unsigned char all;
struct {
- bool CommandInvalid:1; /* Bit 0 */
- bool Reserved:1; /* Bit 1 */
- bool DataInRegisterReady:1; /* Bit 2 */
- bool CommandParameterRegisterBusy:1; /* Bit 3 */
- bool HostAdapterReady:1; /* Bit 4 */
- bool InitializationRequired:1; /* Bit 5 */
- bool DiagnosticFailure:1; /* Bit 6 */
- bool DiagnosticActive:1; /* Bit 7 */
+ bool cmd_invalid:1; /* Bit 0 */
+ bool rsvd:1; /* Bit 1 */
+ bool datain_ready:1; /* Bit 2 */
+ bool cmd_param_busy:1; /* Bit 3 */
+ bool adapter_ready:1; /* Bit 4 */
+ bool init_reqd:1; /* Bit 5 */
+ bool diag_failed:1; /* Bit 6 */
+ bool diag_active:1; /* Bit 7 */
} sr;
};
@@ -328,15 +317,15 @@ union BusLogic_StatusRegister {
Define the structure of the read-only Interrupt Register.
*/
-union BusLogic_InterruptRegister {
- unsigned char All;
+union blogic_int_reg {
+ unsigned char all;
struct {
- bool IncomingMailboxLoaded:1; /* Bit 0 */
- bool OutgoingMailboxAvailable:1;/* Bit 1 */
- bool CommandComplete:1; /* Bit 2 */
- bool ExternalBusReset:1; /* Bit 3 */
- unsigned char Reserved:3; /* Bits 4-6 */
- bool InterruptValid:1; /* Bit 7 */
+ bool mailin_loaded:1; /* Bit 0 */
+ bool mailout_avail:1; /* Bit 1 */
+ bool cmd_complete:1; /* Bit 2 */
+ bool ext_busreset:1; /* Bit 3 */
+ unsigned char rsvd:3; /* Bits 4-6 */
+ bool int_valid:1; /* Bit 7 */
} ir;
};
@@ -344,13 +333,13 @@ union BusLogic_InterruptRegister {
Define the structure of the read-only Geometry Register.
*/
-union BusLogic_GeometryRegister {
- unsigned char All;
+union blogic_geo_reg {
+ unsigned char all;
struct {
- enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2; /* Bits 0-1 */
- enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2; /* Bits 2-3 */
+ enum blogic_bios_diskgeometry d0_geo:2; /* Bits 0-1 */
+ enum blogic_bios_diskgeometry d1_geo:2; /* Bits 2-3 */
unsigned char:3; /* Bits 4-6 */
- bool ExtendedTranslationEnabled:1; /* Bit 7 */
+ bool ext_trans_enable:1; /* Bit 7 */
} gr;
};
@@ -358,82 +347,82 @@ union BusLogic_GeometryRegister {
Define the BusLogic SCSI Host Adapter Command Register Operation Codes.
*/
-enum BusLogic_OperationCode {
- BusLogic_TestCommandCompleteInterrupt = 0x00,
- BusLogic_InitializeMailbox = 0x01,
- BusLogic_ExecuteMailboxCommand = 0x02,
- BusLogic_ExecuteBIOSCommand = 0x03,
- BusLogic_InquireBoardID = 0x04,
- BusLogic_EnableOutgoingMailboxAvailableInt = 0x05,
- BusLogic_SetSCSISelectionTimeout = 0x06,
- BusLogic_SetPreemptTimeOnBus = 0x07,
- BusLogic_SetTimeOffBus = 0x08,
- BusLogic_SetBusTransferRate = 0x09,
- BusLogic_InquireInstalledDevicesID0to7 = 0x0A,
- BusLogic_InquireConfiguration = 0x0B,
- BusLogic_EnableTargetMode = 0x0C,
- BusLogic_InquireSetupInformation = 0x0D,
- BusLogic_WriteAdapterLocalRAM = 0x1A,
- BusLogic_ReadAdapterLocalRAM = 0x1B,
- BusLogic_WriteBusMasterChipFIFO = 0x1C,
- BusLogic_ReadBusMasterChipFIFO = 0x1D,
- BusLogic_EchoCommandData = 0x1F,
- BusLogic_HostAdapterDiagnostic = 0x20,
- BusLogic_SetAdapterOptions = 0x21,
- BusLogic_InquireInstalledDevicesID8to15 = 0x23,
- BusLogic_InquireTargetDevices = 0x24,
- BusLogic_DisableHostAdapterInterrupt = 0x25,
- BusLogic_InitializeExtendedMailbox = 0x81,
- BusLogic_ExecuteSCSICommand = 0x83,
- BusLogic_InquireFirmwareVersion3rdDigit = 0x84,
- BusLogic_InquireFirmwareVersionLetter = 0x85,
- BusLogic_InquirePCIHostAdapterInformation = 0x86,
- BusLogic_InquireHostAdapterModelNumber = 0x8B,
- BusLogic_InquireSynchronousPeriod = 0x8C,
- BusLogic_InquireExtendedSetupInformation = 0x8D,
- BusLogic_EnableStrictRoundRobinMode = 0x8F,
- BusLogic_StoreHostAdapterLocalRAM = 0x90,
- BusLogic_FetchHostAdapterLocalRAM = 0x91,
- BusLogic_StoreLocalDataInEEPROM = 0x92,
- BusLogic_UploadAutoSCSICode = 0x94,
- BusLogic_ModifyIOAddress = 0x95,
- BusLogic_SetCCBFormat = 0x96,
- BusLogic_WriteInquiryBuffer = 0x9A,
- BusLogic_ReadInquiryBuffer = 0x9B,
- BusLogic_FlashROMUploadDownload = 0xA7,
- BusLogic_ReadSCAMData = 0xA8,
- BusLogic_WriteSCAMData = 0xA9
+enum blogic_opcode {
+ BLOGIC_TEST_CMP_COMPLETE = 0x00,
+ BLOGIC_INIT_MBOX = 0x01,
+ BLOGIC_EXEC_MBOX_CMD = 0x02,
+ BLOGIC_EXEC_BIOS_CMD = 0x03,
+ BLOGIC_GET_BOARD_ID = 0x04,
+ BLOGIC_ENABLE_OUTBOX_AVAIL_INT = 0x05,
+ BLOGIC_SET_SELECT_TIMEOUT = 0x06,
+ BLOGIC_SET_PREEMPT_TIME = 0x07,
+ BLOGIC_SET_TIMEOFF_BUS = 0x08,
+ BLOGIC_SET_TXRATE = 0x09,
+ BLOGIC_INQ_DEV0TO7 = 0x0A,
+ BLOGIC_INQ_CONFIG = 0x0B,
+ BLOGIC_TGT_MODE = 0x0C,
+ BLOGIC_INQ_SETUPINFO = 0x0D,
+ BLOGIC_WRITE_LOCALRAM = 0x1A,
+ BLOGIC_READ_LOCALRAM = 0x1B,
+ BLOGIC_WRITE_BUSMASTER_FIFO = 0x1C,
+ BLOGIC_READ_BUSMASTER_FIFO = 0x1D,
+ BLOGIC_ECHO_CMDDATA = 0x1F,
+ BLOGIC_ADAPTER_DIAG = 0x20,
+ BLOGIC_SET_OPTIONS = 0x21,
+ BLOGIC_INQ_DEV8TO15 = 0x23,
+ BLOGIC_INQ_DEV = 0x24,
+ BLOGIC_DISABLE_INT = 0x25,
+ BLOGIC_INIT_EXT_MBOX = 0x81,
+ BLOGIC_EXEC_SCS_CMD = 0x83,
+ BLOGIC_INQ_FWVER_D3 = 0x84,
+ BLOGIC_INQ_FWVER_LETTER = 0x85,
+ BLOGIC_INQ_PCI_INFO = 0x86,
+ BLOGIC_INQ_MODELNO = 0x8B,
+ BLOGIC_INQ_SYNC_PERIOD = 0x8C,
+ BLOGIC_INQ_EXTSETUP = 0x8D,
+ BLOGIC_STRICT_RR = 0x8F,
+ BLOGIC_STORE_LOCALRAM = 0x90,
+ BLOGIC_FETCH_LOCALRAM = 0x91,
+ BLOGIC_STORE_TO_EEPROM = 0x92,
+ BLOGIC_LOAD_AUTOSCSICODE = 0x94,
+ BLOGIC_MOD_IOADDR = 0x95,
+ BLOGIC_SETCCB_FMT = 0x96,
+ BLOGIC_WRITE_INQBUF = 0x9A,
+ BLOGIC_READ_INQBUF = 0x9B,
+ BLOGIC_FLASH_LOAD = 0xA7,
+ BLOGIC_READ_SCAMDATA = 0xA8,
+ BLOGIC_WRITE_SCAMDATA = 0xA9
};
/*
Define the Inquire Board ID reply structure.
*/
-struct BusLogic_BoardID {
- unsigned char BoardType; /* Byte 0 */
- unsigned char CustomFeatures; /* Byte 1 */
- unsigned char FirmwareVersion1stDigit; /* Byte 2 */
- unsigned char FirmwareVersion2ndDigit; /* Byte 3 */
+struct blogic_board_id {
+ unsigned char type; /* Byte 0 */
+ unsigned char custom_features; /* Byte 1 */
+ unsigned char fw_ver_digit1; /* Byte 2 */
+ unsigned char fw_ver_digit2; /* Byte 3 */
};
/*
Define the Inquire Configuration reply structure.
*/
-struct BusLogic_Configuration {
+struct blogic_config {
unsigned char:5; /* Byte 0 Bits 0-4 */
- bool DMA_Channel5:1; /* Byte 0 Bit 5 */
- bool DMA_Channel6:1; /* Byte 0 Bit 6 */
- bool DMA_Channel7:1; /* Byte 0 Bit 7 */
- bool IRQ_Channel9:1; /* Byte 1 Bit 0 */
- bool IRQ_Channel10:1; /* Byte 1 Bit 1 */
- bool IRQ_Channel11:1; /* Byte 1 Bit 2 */
- bool IRQ_Channel12:1; /* Byte 1 Bit 3 */
+ bool dma_ch5:1; /* Byte 0 Bit 5 */
+ bool dma_ch6:1; /* Byte 0 Bit 6 */
+ bool dma_ch7:1; /* Byte 0 Bit 7 */
+ bool irq_ch9:1; /* Byte 1 Bit 0 */
+ bool irq_ch10:1; /* Byte 1 Bit 1 */
+ bool irq_ch11:1; /* Byte 1 Bit 2 */
+ bool irq_ch12:1; /* Byte 1 Bit 3 */
unsigned char:1; /* Byte 1 Bit 4 */
- bool IRQ_Channel14:1; /* Byte 1 Bit 5 */
- bool IRQ_Channel15:1; /* Byte 1 Bit 6 */
+ bool irq_ch14:1; /* Byte 1 Bit 5 */
+ bool irq_ch15:1; /* Byte 1 Bit 6 */
unsigned char:1; /* Byte 1 Bit 7 */
- unsigned char HostAdapterID:4; /* Byte 2 Bits 0-3 */
+ unsigned char id:4; /* Byte 2 Bits 0-3 */
unsigned char:4; /* Byte 2 Bits 4-7 */
};
@@ -441,42 +430,42 @@ struct BusLogic_Configuration {
Define the Inquire Setup Information reply structure.
*/
-struct BusLogic_SynchronousValue {
- unsigned char Offset:4; /* Bits 0-3 */
- unsigned char TransferPeriod:3; /* Bits 4-6 */
- bool Synchronous:1; /* Bit 7 */
+struct blogic_syncval {
+ unsigned char offset:4; /* Bits 0-3 */
+ unsigned char tx_period:3; /* Bits 4-6 */
+ bool sync:1; /* Bit 7 */
};
-struct BusLogic_SetupInformation {
- bool SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */
- bool ParityCheckingEnabled:1; /* Byte 0 Bit 1 */
- unsigned char:6; /* Byte 0 Bits 2-7 */
- unsigned char BusTransferRate; /* Byte 1 */
- unsigned char PreemptTimeOnBus; /* Byte 2 */
- unsigned char TimeOffBus; /* Byte 3 */
- unsigned char MailboxCount; /* Byte 4 */
- unsigned char MailboxAddress[3]; /* Bytes 5-7 */
- struct BusLogic_SynchronousValue SynchronousValuesID0to7[8]; /* Bytes 8-15 */
- unsigned char DisconnectPermittedID0to7; /* Byte 16 */
- unsigned char Signature; /* Byte 17 */
- unsigned char CharacterD; /* Byte 18 */
- unsigned char HostBusType; /* Byte 19 */
- unsigned char WideTransfersPermittedID0to7; /* Byte 20 */
- unsigned char WideTransfersActiveID0to7; /* Byte 21 */
- struct BusLogic_SynchronousValue SynchronousValuesID8to15[8]; /* Bytes 22-29 */
- unsigned char DisconnectPermittedID8to15; /* Byte 30 */
- unsigned char:8; /* Byte 31 */
- unsigned char WideTransfersPermittedID8to15; /* Byte 32 */
- unsigned char WideTransfersActiveID8to15; /* Byte 33 */
+struct blogic_setup_info {
+ bool sync:1; /* Byte 0 Bit 0 */
+ bool parity:1; /* Byte 0 Bit 1 */
+ unsigned char:6; /* Byte 0 Bits 2-7 */
+ unsigned char tx_rate; /* Byte 1 */
+ unsigned char preempt_time; /* Byte 2 */
+ unsigned char timeoff_bus; /* Byte 3 */
+ unsigned char mbox_count; /* Byte 4 */
+ unsigned char mbox_addr[3]; /* Bytes 5-7 */
+ struct blogic_syncval sync0to7[8]; /* Bytes 8-15 */
+ unsigned char disconnect_ok0to7; /* Byte 16 */
+ unsigned char sig; /* Byte 17 */
+ unsigned char char_d; /* Byte 18 */
+ unsigned char bus_type; /* Byte 19 */
+ unsigned char wide_tx_ok0to7; /* Byte 20 */
+ unsigned char wide_tx_active0to7; /* Byte 21 */
+ struct blogic_syncval sync8to15[8]; /* Bytes 22-29 */
+ unsigned char disconnect_ok8to15; /* Byte 30 */
+ unsigned char:8; /* Byte 31 */
+ unsigned char wide_tx_ok8to15; /* Byte 32 */
+ unsigned char wide_tx_active8to15; /* Byte 33 */
};
/*
Define the Initialize Extended Mailbox request structure.
*/
-struct BusLogic_ExtendedMailboxRequest {
- unsigned char MailboxCount; /* Byte 0 */
- u32 BaseMailboxAddress; /* Bytes 1-4 */
+struct blogic_extmbox_req {
+ unsigned char mbox_count; /* Byte 0 */
+ u32 base_mbox_addr; /* Bytes 1-4 */
} PACKED;
@@ -486,63 +475,63 @@ struct BusLogic_ExtendedMailboxRequest {
the Modify I/O Address command.
*/
-enum BusLogic_ISACompatibleIOPort {
- BusLogic_IO_330 = 0,
- BusLogic_IO_334 = 1,
- BusLogic_IO_230 = 2,
- BusLogic_IO_234 = 3,
- BusLogic_IO_130 = 4,
- BusLogic_IO_134 = 5,
- BusLogic_IO_Disable = 6,
- BusLogic_IO_Disable2 = 7
+enum blogic_isa_ioport {
+ BLOGIC_IO_330 = 0,
+ BLOGIC_IO_334 = 1,
+ BLOGIC_IO_230 = 2,
+ BLOGIC_IO_234 = 3,
+ BLOGIC_IO_130 = 4,
+ BLOGIC_IO_134 = 5,
+ BLOGIC_IO_DISABLE = 6,
+ BLOGIC_IO_DISABLE2 = 7
} PACKED;
-struct BusLogic_PCIHostAdapterInformation {
- enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort; /* Byte 0 */
- unsigned char PCIAssignedIRQChannel; /* Byte 1 */
- bool LowByteTerminated:1; /* Byte 2 Bit 0 */
- bool HighByteTerminated:1; /* Byte 2 Bit 1 */
- unsigned char:2; /* Byte 2 Bits 2-3 */
- bool JP1:1; /* Byte 2 Bit 4 */
- bool JP2:1; /* Byte 2 Bit 5 */
- bool JP3:1; /* Byte 2 Bit 6 */
- bool GenericInfoValid:1;/* Byte 2 Bit 7 */
- unsigned char:8; /* Byte 3 */
+struct blogic_adapter_info {
+ enum blogic_isa_ioport isa_port; /* Byte 0 */
+ unsigned char irq_ch; /* Byte 1 */
+ bool low_term:1; /* Byte 2 Bit 0 */
+ bool high_term:1; /* Byte 2 Bit 1 */
+ unsigned char:2; /* Byte 2 Bits 2-3 */
+ bool JP1:1; /* Byte 2 Bit 4 */
+ bool JP2:1; /* Byte 2 Bit 5 */
+ bool JP3:1; /* Byte 2 Bit 6 */
+ bool genericinfo_valid:1; /* Byte 2 Bit 7 */
+ unsigned char:8; /* Byte 3 */
};
/*
Define the Inquire Extended Setup Information reply structure.
*/
-struct BusLogic_ExtendedSetupInformation {
- unsigned char BusType; /* Byte 0 */
- unsigned char BIOS_Address; /* Byte 1 */
- unsigned short ScatterGatherLimit; /* Bytes 2-3 */
- unsigned char MailboxCount; /* Byte 4 */
- u32 BaseMailboxAddress; /* Bytes 5-8 */
+struct blogic_ext_setup {
+ unsigned char bus_type; /* Byte 0 */
+ unsigned char bios_addr; /* Byte 1 */
+ unsigned short sg_limit; /* Bytes 2-3 */
+ unsigned char mbox_count; /* Byte 4 */
+ u32 base_mbox_addr; /* Bytes 5-8 */
struct {
unsigned char:2; /* Byte 9 Bits 0-1 */
- bool FastOnEISA:1; /* Byte 9 Bit 2 */
+ bool fast_on_eisa:1; /* Byte 9 Bit 2 */
unsigned char:3; /* Byte 9 Bits 3-5 */
- bool LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */
+ bool level_int:1; /* Byte 9 Bit 6 */
unsigned char:1; /* Byte 9 Bit 7 */
- } Misc;
- unsigned char FirmwareRevision[3]; /* Bytes 10-12 */
- bool HostWideSCSI:1; /* Byte 13 Bit 0 */
- bool HostDifferentialSCSI:1; /* Byte 13 Bit 1 */
- bool HostSupportsSCAM:1; /* Byte 13 Bit 2 */
- bool HostUltraSCSI:1; /* Byte 13 Bit 3 */
- bool HostSmartTermination:1; /* Byte 13 Bit 4 */
- unsigned char:3; /* Byte 13 Bits 5-7 */
+ } misc;
+ unsigned char fw_rev[3]; /* Bytes 10-12 */
+ bool wide:1; /* Byte 13 Bit 0 */
+ bool differential:1; /* Byte 13 Bit 1 */
+ bool scam:1; /* Byte 13 Bit 2 */
+ bool ultra:1; /* Byte 13 Bit 3 */
+ bool smart_term:1; /* Byte 13 Bit 4 */
+ unsigned char:3; /* Byte 13 Bits 5-7 */
} PACKED;
/*
Define the Enable Strict Round Robin Mode request type.
*/
-enum BusLogic_RoundRobinModeRequest {
- BusLogic_AggressiveRoundRobinMode = 0,
- BusLogic_StrictRoundRobinMode = 1
+enum blogic_rr_req {
+ BLOGIC_AGGRESSIVE_RR = 0,
+ BLOGIC_STRICT_RR_MODE = 1
} PACKED;
@@ -550,95 +539,95 @@ enum BusLogic_RoundRobinModeRequest {
Define the Fetch Host Adapter Local RAM request type.
*/
-#define BusLogic_BIOS_BaseOffset 0
-#define BusLogic_AutoSCSI_BaseOffset 64
+#define BLOGIC_BIOS_BASE 0
+#define BLOGIC_AUTOSCSI_BASE 64
-struct BusLogic_FetchHostAdapterLocalRAMRequest {
- unsigned char ByteOffset; /* Byte 0 */
- unsigned char ByteCount; /* Byte 1 */
+struct blogic_fetch_localram {
+ unsigned char offset; /* Byte 0 */
+ unsigned char count; /* Byte 1 */
};
/*
Define the Host Adapter Local RAM AutoSCSI structure.
*/
-struct BusLogic_AutoSCSIData {
- unsigned char InternalFactorySignature[2]; /* Bytes 0-1 */
- unsigned char InformationByteCount; /* Byte 2 */
- unsigned char HostAdapterType[6]; /* Bytes 3-8 */
- unsigned char:8; /* Byte 9 */
- bool FloppyEnabled:1; /* Byte 10 Bit 0 */
- bool FloppySecondary:1; /* Byte 10 Bit 1 */
- bool LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */
- unsigned char:2; /* Byte 10 Bits 3-4 */
- unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */
- unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */
- bool DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */
- unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */
- bool IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */
- unsigned char DMA_TransferRate; /* Byte 13 */
- unsigned char SCSI_ID; /* Byte 14 */
- bool LowByteTerminated:1; /* Byte 15 Bit 0 */
- bool ParityCheckingEnabled:1; /* Byte 15 Bit 1 */
- bool HighByteTerminated:1; /* Byte 15 Bit 2 */
- bool NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */
- bool FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */
- bool BusResetEnabled:1; /* Byte 15 Bit 5 */
- bool:1; /* Byte 15 Bit 6 */
- bool ActiveNegationEnabled:1; /* Byte 15 Bit 7 */
- unsigned char BusOnDelay; /* Byte 16 */
- unsigned char BusOffDelay; /* Byte 17 */
- bool HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */
- bool BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */
- bool ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */
- bool MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */
- bool:1; /* Byte 18 Bit 4 */
- bool BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */
- bool BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */
- bool FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */
- unsigned short DeviceEnabled; /* Bytes 19-20 */
- unsigned short WidePermitted; /* Bytes 21-22 */
- unsigned short FastPermitted; /* Bytes 23-24 */
- unsigned short SynchronousPermitted; /* Bytes 25-26 */
- unsigned short DisconnectPermitted; /* Bytes 27-28 */
- unsigned short SendStartUnitCommand; /* Bytes 29-30 */
- unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */
- unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */
- unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */
- bool StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */
- bool VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */
- bool VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */
- bool VESABurstReadEnabled:1; /* Byte 33 Bit 7 */
- unsigned short UltraPermitted; /* Bytes 34-35 */
- unsigned int:32; /* Bytes 36-39 */
- unsigned char:8; /* Byte 40 */
- unsigned char AutoSCSIMaximumLUN; /* Byte 41 */
- bool:1; /* Byte 42 Bit 0 */
- bool SCAM_Dominant:1; /* Byte 42 Bit 1 */
- bool SCAM_Enabled:1; /* Byte 42 Bit 2 */
- bool SCAM_Level2:1; /* Byte 42 Bit 3 */
- unsigned char:4; /* Byte 42 Bits 4-7 */
- bool INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */
- bool:1; /* Byte 43 Bit 1 */
- bool CDROMBootEnabled:1; /* Byte 43 Bit 2 */
- unsigned char:5; /* Byte 43 Bits 3-7 */
- unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */
- unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */
- unsigned char ForceBusDeviceScanningOrder:1; /* Byte 45 Bit 0 */
- unsigned char:7; /* Byte 45 Bits 1-7 */
- unsigned short NonTaggedToAlternateLUNPermitted; /* Bytes 46-47 */
- unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */
- unsigned char Reserved[10]; /* Bytes 50-59 */
- unsigned char ManufacturingDiagnostic[2]; /* Bytes 60-61 */
- unsigned short Checksum; /* Bytes 62-63 */
+struct blogic_autoscsi {
+ unsigned char factory_sig[2]; /* Bytes 0-1 */
+ unsigned char info_bytes; /* Byte 2 */
+ unsigned char adapter_type[6]; /* Bytes 3-8 */
+ unsigned char:8; /* Byte 9 */
+ bool floppy:1; /* Byte 10 Bit 0 */
+ bool floppy_sec:1; /* Byte 10 Bit 1 */
+ bool level_int:1; /* Byte 10 Bit 2 */
+ unsigned char:2; /* Byte 10 Bits 3-4 */
+ unsigned char systemram_bios:3; /* Byte 10 Bits 5-7 */
+ unsigned char dma_ch:7; /* Byte 11 Bits 0-6 */
+ bool dma_autoconf:1; /* Byte 11 Bit 7 */
+ unsigned char irq_ch:7; /* Byte 12 Bits 0-6 */
+ bool irq_autoconf:1; /* Byte 12 Bit 7 */
+ unsigned char dma_tx_rate; /* Byte 13 */
+ unsigned char scsi_id; /* Byte 14 */
+ bool low_term:1; /* Byte 15 Bit 0 */
+ bool parity:1; /* Byte 15 Bit 1 */
+ bool high_term:1; /* Byte 15 Bit 2 */
+ bool noisy_cable:1; /* Byte 15 Bit 3 */
+ bool fast_sync_neg:1; /* Byte 15 Bit 4 */
+ bool reset_enabled:1; /* Byte 15 Bit 5 */
+ bool:1; /* Byte 15 Bit 6 */
+ bool active_negation:1; /* Byte 15 Bit 7 */
+ unsigned char bus_on_delay; /* Byte 16 */
+ unsigned char bus_off_delay; /* Byte 17 */
+ bool bios_enabled:1; /* Byte 18 Bit 0 */
+ bool int19_redir_enabled:1; /* Byte 18 Bit 1 */
+ bool ext_trans_enable:1; /* Byte 18 Bit 2 */
+ bool removable_as_fixed:1; /* Byte 18 Bit 3 */
+ bool:1; /* Byte 18 Bit 4 */
+ bool morethan2_drives:1; /* Byte 18 Bit 5 */
+ bool bios_int:1; /* Byte 18 Bit 6 */
+ bool floptical:1; /* Byte 19 Bit 7 */
+ unsigned short dev_enabled; /* Bytes 19-20 */
+ unsigned short wide_ok; /* Bytes 21-22 */
+ unsigned short fast_ok; /* Bytes 23-24 */
+ unsigned short sync_ok; /* Bytes 25-26 */
+ unsigned short discon_ok; /* Bytes 27-28 */
+ unsigned short send_start_unit; /* Bytes 29-30 */
+ unsigned short ignore_bios_scan; /* Bytes 31-32 */
+ unsigned char pci_int_pin:2; /* Byte 33 Bits 0-1 */
+ unsigned char adapter_ioport:2; /* Byte 33 Bits 2-3 */
+ bool strict_rr_enabled:1; /* Byte 33 Bit 4 */
+ bool vesabus_33mhzplus:1; /* Byte 33 Bit 5 */
+ bool vesa_burst_write:1; /* Byte 33 Bit 6 */
+ bool vesa_burst_read:1; /* Byte 33 Bit 7 */
+ unsigned short ultra_ok; /* Bytes 34-35 */
+ unsigned int:32; /* Bytes 36-39 */
+ unsigned char:8; /* Byte 40 */
+ unsigned char autoscsi_maxlun; /* Byte 41 */
+ bool:1; /* Byte 42 Bit 0 */
+ bool scam_dominant:1; /* Byte 42 Bit 1 */
+ bool scam_enabled:1; /* Byte 42 Bit 2 */
+ bool scam_lev2:1; /* Byte 42 Bit 3 */
+ unsigned char:4; /* Byte 42 Bits 4-7 */
+ bool int13_exten:1; /* Byte 43 Bit 0 */
+ bool:1; /* Byte 43 Bit 1 */
+ bool cd_boot:1; /* Byte 43 Bit 2 */
+ unsigned char:5; /* Byte 43 Bits 3-7 */
+ unsigned char boot_id:4; /* Byte 44 Bits 0-3 */
+ unsigned char boot_ch:4; /* Byte 44 Bits 4-7 */
+ unsigned char force_scan_order:1; /* Byte 45 Bit 0 */
+ unsigned char:7; /* Byte 45 Bits 1-7 */
+ unsigned short nontagged_to_alt_ok; /* Bytes 46-47 */
+ unsigned short reneg_sync_on_check; /* Bytes 48-49 */
+ unsigned char rsvd[10]; /* Bytes 50-59 */
+ unsigned char manuf_diag[2]; /* Bytes 60-61 */
+ unsigned short cksum; /* Bytes 62-63 */
} PACKED;
/*
Define the Host Adapter Local RAM Auto SCSI Byte 45 structure.
*/
-struct BusLogic_AutoSCSIByte45 {
- unsigned char ForceBusDeviceScanningOrder:1; /* Bit 0 */
+struct blogic_autoscsi_byte45 {
+ unsigned char force_scan_order:1; /* Bit 0 */
unsigned char:7; /* Bits 1-7 */
};
@@ -646,13 +635,13 @@ struct BusLogic_AutoSCSIByte45 {
Define the Host Adapter Local RAM BIOS Drive Map Byte structure.
*/
-#define BusLogic_BIOS_DriveMapOffset 17
+#define BLOGIC_BIOS_DRVMAP 17
-struct BusLogic_BIOSDriveMapByte {
- unsigned char TargetIDBit3:1; /* Bit 0 */
- unsigned char:2; /* Bits 1-2 */
- enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2; /* Bits 3-4 */
- unsigned char TargetID:3; /* Bits 5-7 */
+struct blogic_bios_drvmap {
+ unsigned char tgt_idbit3:1; /* Bit 0 */
+ unsigned char:2; /* Bits 1-2 */
+ enum blogic_bios_diskgeometry diskgeom:2; /* Bits 3-4 */
+ unsigned char tgt_id:3; /* Bits 5-7 */
};
/*
@@ -660,19 +649,19 @@ struct BusLogic_BIOSDriveMapByte {
necessary to support more than 8 Logical Units per Target Device.
*/
-enum BusLogic_SetCCBFormatRequest {
- BusLogic_LegacyLUNFormatCCB = 0,
- BusLogic_ExtendedLUNFormatCCB = 1
+enum blogic_setccb_fmt {
+ BLOGIC_LEGACY_LUN_CCB = 0,
+ BLOGIC_EXT_LUN_CCB = 1
} PACKED;
/*
Define the Outgoing Mailbox Action Codes.
*/
-enum BusLogic_ActionCode {
- BusLogic_OutgoingMailboxFree = 0x00,
- BusLogic_MailboxStartCommand = 0x01,
- BusLogic_MailboxAbortCommand = 0x02
+enum blogic_action {
+ BLOGIC_OUTBOX_FREE = 0x00,
+ BLOGIC_MBOX_START = 0x01,
+ BLOGIC_MBOX_ABORT = 0x02
} PACKED;
@@ -682,26 +671,26 @@ enum BusLogic_ActionCode {
completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5.
*/
-enum BusLogic_CompletionCode {
- BusLogic_IncomingMailboxFree = 0x00,
- BusLogic_CommandCompletedWithoutError = 0x01,
- BusLogic_CommandAbortedAtHostRequest = 0x02,
- BusLogic_AbortedCommandNotFound = 0x03,
- BusLogic_CommandCompletedWithError = 0x04,
- BusLogic_InvalidCCB = 0x05
+enum blogic_cmplt_code {
+ BLOGIC_INBOX_FREE = 0x00,
+ BLOGIC_CMD_COMPLETE_GOOD = 0x01,
+ BLOGIC_CMD_ABORT_BY_HOST = 0x02,
+ BLOGIC_CMD_NOTFOUND = 0x03,
+ BLOGIC_CMD_COMPLETE_ERROR = 0x04,
+ BLOGIC_INVALID_CCB = 0x05
} PACKED;
/*
Define the Command Control Block (CCB) Opcodes.
*/
-enum BusLogic_CCB_Opcode {
- BusLogic_InitiatorCCB = 0x00,
- BusLogic_TargetCCB = 0x01,
- BusLogic_InitiatorCCB_ScatterGather = 0x02,
- BusLogic_InitiatorCCB_ResidualDataLength = 0x03,
- BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04,
- BusLogic_BusDeviceReset = 0x81
+enum blogic_ccb_opcode {
+ BLOGIC_INITIATOR_CCB = 0x00,
+ BLOGIC_TGT_CCB = 0x01,
+ BLOGIC_INITIATOR_CCB_SG = 0x02,
+ BLOGIC_INITIATOR_CCBB_RESIDUAL = 0x03,
+ BLOGIC_INITIATOR_CCB_SG_RESIDUAL = 0x04,
+ BLOGIC_BDR = 0x81
} PACKED;
@@ -709,11 +698,11 @@ enum BusLogic_CCB_Opcode {
Define the CCB Data Direction Codes.
*/
-enum BusLogic_DataDirection {
- BusLogic_UncheckedDataTransfer = 0,
- BusLogic_DataInLengthChecked = 1,
- BusLogic_DataOutLengthChecked = 2,
- BusLogic_NoDataTransfer = 3
+enum blogic_datadir {
+ BLOGIC_UNCHECKED_TX = 0,
+ BLOGIC_DATAIN_CHECKED = 1,
+ BLOGIC_DATAOUT_CHECKED = 2,
+ BLOGIC_NOTX = 3
};
@@ -722,32 +711,32 @@ enum BusLogic_DataDirection {
return status code 0x0C; it uses 0x12 for both overruns and underruns.
*/
-enum BusLogic_HostAdapterStatus {
- BusLogic_CommandCompletedNormally = 0x00,
- BusLogic_LinkedCommandCompleted = 0x0A,
- BusLogic_LinkedCommandCompletedWithFlag = 0x0B,
- BusLogic_DataUnderRun = 0x0C,
- BusLogic_SCSISelectionTimeout = 0x11,
- BusLogic_DataOverRun = 0x12,
- BusLogic_UnexpectedBusFree = 0x13,
- BusLogic_InvalidBusPhaseRequested = 0x14,
- BusLogic_InvalidOutgoingMailboxActionCode = 0x15,
- BusLogic_InvalidCommandOperationCode = 0x16,
- BusLogic_LinkedCCBhasInvalidLUN = 0x17,
- BusLogic_InvalidCommandParameter = 0x1A,
- BusLogic_AutoRequestSenseFailed = 0x1B,
- BusLogic_TaggedQueuingMessageRejected = 0x1C,
- BusLogic_UnsupportedMessageReceived = 0x1D,
- BusLogic_HostAdapterHardwareFailed = 0x20,
- BusLogic_TargetFailedResponseToATN = 0x21,
- BusLogic_HostAdapterAssertedRST = 0x22,
- BusLogic_OtherDeviceAssertedRST = 0x23,
- BusLogic_TargetDeviceReconnectedImproperly = 0x24,
- BusLogic_HostAdapterAssertedBusDeviceReset = 0x25,
- BusLogic_AbortQueueGenerated = 0x26,
- BusLogic_HostAdapterSoftwareError = 0x27,
- BusLogic_HostAdapterHardwareTimeoutError = 0x30,
- BusLogic_SCSIParityErrorDetected = 0x34
+enum blogic_adapter_status {
+ BLOGIC_CMD_CMPLT_NORMAL = 0x00,
+ BLOGIC_LINK_CMD_CMPLT = 0x0A,
+ BLOGIC_LINK_CMD_CMPLT_FLAG = 0x0B,
+ BLOGIC_DATA_UNDERRUN = 0x0C,
+ BLOGIC_SELECT_TIMEOUT = 0x11,
+ BLOGIC_DATA_OVERRUN = 0x12,
+ BLOGIC_NOEXPECT_BUSFREE = 0x13,
+ BLOGIC_INVALID_BUSPHASE = 0x14,
+ BLOGIC_INVALID_OUTBOX_CODE = 0x15,
+ BLOGIC_INVALID_CMD_CODE = 0x16,
+ BLOGIC_LINKCCB_BADLUN = 0x17,
+ BLOGIC_BAD_CMD_PARAM = 0x1A,
+ BLOGIC_AUTOREQSENSE_FAIL = 0x1B,
+ BLOGIC_TAGQUEUE_REJECT = 0x1C,
+ BLOGIC_BAD_MSG_RCVD = 0x1D,
+ BLOGIC_HW_FAIL = 0x20,
+ BLOGIC_NORESPONSE_TO_ATN = 0x21,
+ BLOGIC_HW_RESET = 0x22,
+ BLOGIC_RST_FROM_OTHERDEV = 0x23,
+ BLOGIC_BAD_RECONNECT = 0x24,
+ BLOGIC_HW_BDR = 0x25,
+ BLOGIC_ABRT_QUEUE = 0x26,
+ BLOGIC_ADAPTER_SW_ERROR = 0x27,
+ BLOGIC_HW_TIMEOUT = 0x30,
+ BLOGIC_PARITY_ERR = 0x34
} PACKED;
@@ -755,30 +744,28 @@ enum BusLogic_HostAdapterStatus {
Define the SCSI Target Device Status Codes.
*/
-enum BusLogic_TargetDeviceStatus {
- BusLogic_OperationGood = 0x00,
- BusLogic_CheckCondition = 0x02,
- BusLogic_DeviceBusy = 0x08
+enum blogic_tgt_status {
+ BLOGIC_OP_GOOD = 0x00,
+ BLOGIC_CHECKCONDITION = 0x02,
+ BLOGIC_DEVBUSY = 0x08
} PACKED;
/*
Define the Queue Tag Codes.
*/
-enum BusLogic_QueueTag {
- BusLogic_SimpleQueueTag = 0,
- BusLogic_HeadOfQueueTag = 1,
- BusLogic_OrderedQueueTag = 2,
- BusLogic_ReservedQT = 3
+enum blogic_queuetag {
+ BLOGIC_SIMPLETAG = 0,
+ BLOGIC_HEADTAG = 1,
+ BLOGIC_ORDEREDTAG = 2,
+ BLOGIC_RSVDTAG = 3
};
/*
Define the SCSI Command Descriptor Block (CDB).
*/
-#define BusLogic_CDB_MaxLength 12
-
-typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength];
+#define BLOGIC_CDB_MAXLEN 12
/*
@@ -786,20 +773,20 @@ typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength];
Firmware Interface and the FlashPoint SCCB Manager.
*/
-struct BusLogic_ScatterGatherSegment {
- u32 SegmentByteCount; /* Bytes 0-3 */
- u32 SegmentDataPointer; /* Bytes 4-7 */
+struct blogic_sg_seg {
+ u32 segbytes; /* Bytes 0-3 */
+ u32 segdata; /* Bytes 4-7 */
};
/*
Define the Driver CCB Status Codes.
*/
-enum BusLogic_CCB_Status {
- BusLogic_CCB_Free = 0,
- BusLogic_CCB_Active = 1,
- BusLogic_CCB_Completed = 2,
- BusLogic_CCB_Reset = 3
+enum blogic_ccb_status {
+ BLOGIC_CCB_FREE = 0,
+ BLOGIC_CCB_ACTIVE = 1,
+ BLOGIC_CCB_COMPLETE = 2,
+ BLOGIC_CCB_RESET = 3
} PACKED;
@@ -822,79 +809,81 @@ enum BusLogic_CCB_Status {
32 Logical Units per Target Device.
*/
-struct BusLogic_CCB {
+struct blogic_ccb {
/*
MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
*/
- enum BusLogic_CCB_Opcode Opcode; /* Byte 0 */
- unsigned char:3; /* Byte 1 Bits 0-2 */
- enum BusLogic_DataDirection DataDirection:2; /* Byte 1 Bits 3-4 */
- bool TagEnable:1; /* Byte 1 Bit 5 */
- enum BusLogic_QueueTag QueueTag:2; /* Byte 1 Bits 6-7 */
- unsigned char CDB_Length; /* Byte 2 */
- unsigned char SenseDataLength; /* Byte 3 */
- u32 DataLength; /* Bytes 4-7 */
- u32 DataPointer; /* Bytes 8-11 */
- unsigned char:8; /* Byte 12 */
- unsigned char:8; /* Byte 13 */
- enum BusLogic_HostAdapterStatus HostAdapterStatus; /* Byte 14 */
- enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 15 */
- unsigned char TargetID; /* Byte 16 */
- unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */
- bool LegacyTagEnable:1; /* Byte 17 Bit 5 */
- enum BusLogic_QueueTag LegacyQueueTag:2; /* Byte 17 Bits 6-7 */
- SCSI_CDB_T CDB; /* Bytes 18-29 */
- unsigned char:8; /* Byte 30 */
- unsigned char:8; /* Byte 31 */
- unsigned int:32; /* Bytes 32-35 */
- u32 SenseDataPointer; /* Bytes 36-39 */
+ enum blogic_ccb_opcode opcode; /* Byte 0 */
+ unsigned char:3; /* Byte 1 Bits 0-2 */
+ enum blogic_datadir datadir:2; /* Byte 1 Bits 3-4 */
+ bool tag_enable:1; /* Byte 1 Bit 5 */
+ enum blogic_queuetag queuetag:2; /* Byte 1 Bits 6-7 */
+ unsigned char cdblen; /* Byte 2 */
+ unsigned char sense_datalen; /* Byte 3 */
+ u32 datalen; /* Bytes 4-7 */
+ void *data; /* Bytes 8-11 */
+ unsigned char:8; /* Byte 12 */
+ unsigned char:8; /* Byte 13 */
+ enum blogic_adapter_status adapter_status; /* Byte 14 */
+ enum blogic_tgt_status tgt_status; /* Byte 15 */
+ unsigned char tgt_id; /* Byte 16 */
+ unsigned char lun:5; /* Byte 17 Bits 0-4 */
+ bool legacytag_enable:1; /* Byte 17 Bit 5 */
+ enum blogic_queuetag legacy_tag:2; /* Byte 17 Bits 6-7 */
+ unsigned char cdb[BLOGIC_CDB_MAXLEN]; /* Bytes 18-29 */
+ unsigned char:8; /* Byte 30 */
+ unsigned char:8; /* Byte 31 */
+ u32 rsvd_int; /* Bytes 32-35 */
+ u32 sensedata; /* Bytes 36-39 */
/*
FlashPoint SCCB Manager Defined Portion.
*/
- void (*CallbackFunction) (struct BusLogic_CCB *); /* Bytes 40-43 */
- u32 BaseAddress; /* Bytes 44-47 */
- enum BusLogic_CompletionCode CompletionCode; /* Byte 48 */
+ void (*callback) (struct blogic_ccb *); /* Bytes 40-43 */
+ u32 base_addr; /* Bytes 44-47 */
+ enum blogic_cmplt_code comp_code; /* Byte 48 */
#ifdef CONFIG_SCSI_FLASHPOINT
- unsigned char:8; /* Byte 49 */
- unsigned short OS_Flags; /* Bytes 50-51 */
- unsigned char Private[48]; /* Bytes 52-99 */
+ unsigned char:8; /* Byte 49 */
+ u16 os_flags; /* Bytes 50-51 */
+ unsigned char private[24]; /* Bytes 52-99 */
+ void *rsvd1;
+ void *rsvd2;
+ unsigned char private2[16];
#endif
/*
BusLogic Linux Driver Defined Portion.
*/
- dma_addr_t AllocationGroupHead;
- unsigned int AllocationGroupSize;
- u32 DMA_Handle;
- enum BusLogic_CCB_Status Status;
- unsigned long SerialNumber;
- struct scsi_cmnd *Command;
- struct BusLogic_HostAdapter *HostAdapter;
- struct BusLogic_CCB *Next;
- struct BusLogic_CCB *NextAll;
- struct BusLogic_ScatterGatherSegment
- ScatterGatherList[BusLogic_ScatterGatherLimit];
+ dma_addr_t allocgrp_head;
+ unsigned int allocgrp_size;
+ u32 dma_handle;
+ enum blogic_ccb_status status;
+ unsigned long serial;
+ struct scsi_cmnd *command;
+ struct blogic_adapter *adapter;
+ struct blogic_ccb *next;
+ struct blogic_ccb *next_all;
+ struct blogic_sg_seg sglist[BLOGIC_SG_LIMIT];
};
/*
Define the 32 Bit Mode Outgoing Mailbox structure.
*/
-struct BusLogic_OutgoingMailbox {
- u32 CCB; /* Bytes 0-3 */
- unsigned int:24; /* Bytes 4-6 */
- enum BusLogic_ActionCode ActionCode; /* Byte 7 */
+struct blogic_outbox {
+ u32 ccb; /* Bytes 0-3 */
+ u32:24; /* Bytes 4-6 */
+ enum blogic_action action; /* Byte 7 */
};
/*
Define the 32 Bit Mode Incoming Mailbox structure.
*/
-struct BusLogic_IncomingMailbox {
- u32 CCB; /* Bytes 0-3 */
- enum BusLogic_HostAdapterStatus HostAdapterStatus; /* Byte 4 */
- enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 5 */
- unsigned char:8; /* Byte 6 */
- enum BusLogic_CompletionCode CompletionCode; /* Byte 7 */
+struct blogic_inbox {
+ u32 ccb; /* Bytes 0-3 */
+ enum blogic_adapter_status adapter_status; /* Byte 4 */
+ enum blogic_tgt_status tgt_status; /* Byte 5 */
+ unsigned char:8; /* Byte 6 */
+ enum blogic_cmplt_code comp_code; /* Byte 7 */
};
@@ -902,64 +891,60 @@ struct BusLogic_IncomingMailbox {
Define the BusLogic Driver Options structure.
*/
-struct BusLogic_DriverOptions {
- unsigned short TaggedQueuingPermitted;
- unsigned short TaggedQueuingPermittedMask;
- unsigned short BusSettleTime;
- struct BusLogic_LocalOptions LocalOptions;
- unsigned char CommonQueueDepth;
- unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+struct blogic_drvr_options {
+ unsigned short tagq_ok;
+ unsigned short tagq_ok_mask;
+ unsigned short bus_settle_time;
+ unsigned short stop_tgt_inquiry;
+ unsigned char common_qdepth;
+ unsigned char qdepth[BLOGIC_MAXDEV];
};
/*
Define the Host Adapter Target Flags structure.
*/
-struct BusLogic_TargetFlags {
- bool TargetExists:1;
- bool TaggedQueuingSupported:1;
- bool WideTransfersSupported:1;
- bool TaggedQueuingActive:1;
- bool WideTransfersActive:1;
- bool CommandSuccessfulFlag:1;
- bool TargetInfoReported:1;
+struct blogic_tgt_flags {
+ bool tgt_exists:1;
+ bool tagq_ok:1;
+ bool wide_ok:1;
+ bool tagq_active:1;
+ bool wide_active:1;
+ bool cmd_good:1;
+ bool tgt_info_in:1;
};
/*
Define the Host Adapter Target Statistics structure.
*/
-#define BusLogic_SizeBuckets 10
-
-typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets];
-
-struct BusLogic_TargetStatistics {
- unsigned int CommandsAttempted;
- unsigned int CommandsCompleted;
- unsigned int ReadCommands;
- unsigned int WriteCommands;
- struct BusLogic_ByteCounter TotalBytesRead;
- struct BusLogic_ByteCounter TotalBytesWritten;
- BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
- BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
- unsigned short CommandAbortsRequested;
- unsigned short CommandAbortsAttempted;
- unsigned short CommandAbortsCompleted;
- unsigned short BusDeviceResetsRequested;
- unsigned short BusDeviceResetsAttempted;
- unsigned short BusDeviceResetsCompleted;
- unsigned short HostAdapterResetsRequested;
- unsigned short HostAdapterResetsAttempted;
- unsigned short HostAdapterResetsCompleted;
+#define BLOGIC_SZ_BUCKETS 10
+
+struct blogic_tgt_stats {
+ unsigned int cmds_tried;
+ unsigned int cmds_complete;
+ unsigned int read_cmds;
+ unsigned int write_cmds;
+ struct blogic_byte_count bytesread;
+ struct blogic_byte_count byteswritten;
+ unsigned int read_sz_buckets[BLOGIC_SZ_BUCKETS];
+ unsigned int write_sz_buckets[BLOGIC_SZ_BUCKETS];
+ unsigned short aborts_request;
+ unsigned short aborts_tried;
+ unsigned short aborts_done;
+ unsigned short bdr_request;
+ unsigned short bdr_tried;
+ unsigned short bdr_done;
+ unsigned short adatper_reset_req;
+ unsigned short adapter_reset_attempt;
+ unsigned short adapter_reset_done;
};
/*
Define the FlashPoint Card Handle data type.
*/
-#define FlashPoint_BadCardHandle 0xFFFFFFFF
-
-typedef unsigned int FlashPoint_CardHandle_T;
+#define FPOINT_BADCARD_HANDLE 0xFFFFFFFFL
/*
@@ -967,179 +952,179 @@ typedef unsigned int FlashPoint_CardHandle_T;
by the FlashPoint SCCB Manager.
*/
-struct FlashPoint_Info {
- u32 BaseAddress; /* Bytes 0-3 */
- bool Present; /* Byte 4 */
- unsigned char IRQ_Channel; /* Byte 5 */
- unsigned char SCSI_ID; /* Byte 6 */
- unsigned char SCSI_LUN; /* Byte 7 */
- unsigned short FirmwareRevision; /* Bytes 8-9 */
- unsigned short SynchronousPermitted; /* Bytes 10-11 */
- unsigned short FastPermitted; /* Bytes 12-13 */
- unsigned short UltraPermitted; /* Bytes 14-15 */
- unsigned short DisconnectPermitted; /* Bytes 16-17 */
- unsigned short WidePermitted; /* Bytes 18-19 */
- bool ParityCheckingEnabled:1; /* Byte 20 Bit 0 */
- bool HostWideSCSI:1; /* Byte 20 Bit 1 */
- bool HostSoftReset:1; /* Byte 20 Bit 2 */
- bool ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */
- bool LowByteTerminated:1; /* Byte 20 Bit 4 */
- bool HighByteTerminated:1; /* Byte 20 Bit 5 */
- bool ReportDataUnderrun:1; /* Byte 20 Bit 6 */
- bool SCAM_Enabled:1; /* Byte 20 Bit 7 */
- bool SCAM_Level2:1; /* Byte 21 Bit 0 */
- unsigned char:7; /* Byte 21 Bits 1-7 */
- unsigned char Family; /* Byte 22 */
- unsigned char BusType; /* Byte 23 */
- unsigned char ModelNumber[3]; /* Bytes 24-26 */
- unsigned char RelativeCardNumber; /* Byte 27 */
- unsigned char Reserved[4]; /* Bytes 28-31 */
- unsigned int OS_Reserved; /* Bytes 32-35 */
- unsigned char TranslationInfo[4]; /* Bytes 36-39 */
- unsigned int Reserved2[5]; /* Bytes 40-59 */
- unsigned int SecondaryRange; /* Bytes 60-63 */
+struct fpoint_info {
+ u32 base_addr; /* Bytes 0-3 */
+ bool present; /* Byte 4 */
+ unsigned char irq_ch; /* Byte 5 */
+ unsigned char scsi_id; /* Byte 6 */
+ unsigned char scsi_lun; /* Byte 7 */
+ u16 fw_rev; /* Bytes 8-9 */
+ u16 sync_ok; /* Bytes 10-11 */
+ u16 fast_ok; /* Bytes 12-13 */
+ u16 ultra_ok; /* Bytes 14-15 */
+ u16 discon_ok; /* Bytes 16-17 */
+ u16 wide_ok; /* Bytes 18-19 */
+ bool parity:1; /* Byte 20 Bit 0 */
+ bool wide:1; /* Byte 20 Bit 1 */
+ bool softreset:1; /* Byte 20 Bit 2 */
+ bool ext_trans_enable:1; /* Byte 20 Bit 3 */
+ bool low_term:1; /* Byte 20 Bit 4 */
+ bool high_term:1; /* Byte 20 Bit 5 */
+ bool report_underrun:1; /* Byte 20 Bit 6 */
+ bool scam_enabled:1; /* Byte 20 Bit 7 */
+ bool scam_lev2:1; /* Byte 21 Bit 0 */
+ unsigned char:7; /* Byte 21 Bits 1-7 */
+ unsigned char family; /* Byte 22 */
+ unsigned char bus_type; /* Byte 23 */
+ unsigned char model[3]; /* Bytes 24-26 */
+ unsigned char relative_cardnum; /* Byte 27 */
+ unsigned char rsvd[4]; /* Bytes 28-31 */
+ u32 os_rsvd; /* Bytes 32-35 */
+ unsigned char translation_info[4]; /* Bytes 36-39 */
+ u32 rsvd2[5]; /* Bytes 40-59 */
+ u32 sec_range; /* Bytes 60-63 */
};
/*
Define the BusLogic Driver Host Adapter structure.
*/
-struct BusLogic_HostAdapter {
- struct Scsi_Host *SCSI_Host;
- struct pci_dev *PCI_Device;
- enum BusLogic_HostAdapterType HostAdapterType;
- enum BusLogic_HostAdapterBusType HostAdapterBusType;
- unsigned long IO_Address;
- unsigned long PCI_Address;
- unsigned short AddressCount;
- unsigned char HostNumber;
- unsigned char ModelName[9];
- unsigned char FirmwareVersion[6];
- unsigned char FullModelName[18];
- unsigned char Bus;
- unsigned char Device;
- unsigned char IRQ_Channel;
- unsigned char DMA_Channel;
- unsigned char SCSI_ID;
- bool IRQ_ChannelAcquired:1;
- bool DMA_ChannelAcquired:1;
- bool ExtendedTranslationEnabled:1;
- bool ParityCheckingEnabled:1;
- bool BusResetEnabled:1;
- bool LevelSensitiveInterrupt:1;
- bool HostWideSCSI:1;
- bool HostDifferentialSCSI:1;
- bool HostSupportsSCAM:1;
- bool HostUltraSCSI:1;
- bool ExtendedLUNSupport:1;
- bool TerminationInfoValid:1;
- bool LowByteTerminated:1;
- bool HighByteTerminated:1;
- bool BounceBuffersRequired:1;
- bool StrictRoundRobinModeSupport:1;
- bool SCAM_Enabled:1;
- bool SCAM_Level2:1;
- bool HostAdapterInitialized:1;
- bool HostAdapterExternalReset:1;
- bool HostAdapterInternalError:1;
- bool ProcessCompletedCCBsActive;
- volatile bool HostAdapterCommandCompleted;
- unsigned short HostAdapterScatterGatherLimit;
- unsigned short DriverScatterGatherLimit;
- unsigned short MaxTargetDevices;
- unsigned short MaxLogicalUnits;
- unsigned short MailboxCount;
- unsigned short InitialCCBs;
- unsigned short IncrementalCCBs;
- unsigned short AllocatedCCBs;
- unsigned short DriverQueueDepth;
- unsigned short HostAdapterQueueDepth;
- unsigned short UntaggedQueueDepth;
- unsigned short CommonQueueDepth;
- unsigned short BusSettleTime;
- unsigned short SynchronousPermitted;
- unsigned short FastPermitted;
- unsigned short UltraPermitted;
- unsigned short WidePermitted;
- unsigned short DisconnectPermitted;
- unsigned short TaggedQueuingPermitted;
- unsigned short ExternalHostAdapterResets;
- unsigned short HostAdapterInternalErrors;
- unsigned short TargetDeviceCount;
- unsigned short MessageBufferLength;
- u32 BIOS_Address;
- struct BusLogic_DriverOptions *DriverOptions;
- struct FlashPoint_Info FlashPointInfo;
- FlashPoint_CardHandle_T CardHandle;
+struct blogic_adapter {
+ struct Scsi_Host *scsi_host;
+ struct pci_dev *pci_device;
+ enum blogic_adapter_type adapter_type;
+ enum blogic_adapter_bus_type adapter_bus_type;
+ unsigned long io_addr;
+ unsigned long pci_addr;
+ unsigned short addr_count;
+ unsigned char host_no;
+ unsigned char model[9];
+ unsigned char fw_ver[6];
+ unsigned char full_model[18];
+ unsigned char bus;
+ unsigned char dev;
+ unsigned char irq_ch;
+ unsigned char dma_ch;
+ unsigned char scsi_id;
+ bool irq_acquired:1;
+ bool dma_chan_acquired:1;
+ bool ext_trans_enable:1;
+ bool parity:1;
+ bool reset_enabled:1;
+ bool level_int:1;
+ bool wide:1;
+ bool differential:1;
+ bool scam:1;
+ bool ultra:1;
+ bool ext_lun:1;
+ bool terminfo_valid:1;
+ bool low_term:1;
+ bool high_term:1;
+ bool need_bouncebuf:1;
+ bool strict_rr:1;
+ bool scam_enabled:1;
+ bool scam_lev2:1;
+ bool adapter_initd:1;
+ bool adapter_extreset:1;
+ bool adapter_intern_err:1;
+ bool processing_ccbs;
+ volatile bool adapter_cmd_complete;
+ unsigned short adapter_sglimit;
+ unsigned short drvr_sglimit;
+ unsigned short maxdev;
+ unsigned short maxlun;
+ unsigned short mbox_count;
+ unsigned short initccbs;
+ unsigned short inc_ccbs;
+ unsigned short alloc_ccbs;
+ unsigned short drvr_qdepth;
+ unsigned short adapter_qdepth;
+ unsigned short untag_qdepth;
+ unsigned short common_qdepth;
+ unsigned short bus_settle_time;
+ unsigned short sync_ok;
+ unsigned short fast_ok;
+ unsigned short ultra_ok;
+ unsigned short wide_ok;
+ unsigned short discon_ok;
+ unsigned short tagq_ok;
+ unsigned short ext_resets;
+ unsigned short adapter_intern_errors;
+ unsigned short tgt_count;
+ unsigned short msgbuflen;
+ u32 bios_addr;
+ struct blogic_drvr_options *drvr_opts;
+ struct fpoint_info fpinfo;
+ void *cardhandle;
struct list_head host_list;
- struct BusLogic_CCB *All_CCBs;
- struct BusLogic_CCB *Free_CCBs;
- struct BusLogic_CCB *FirstCompletedCCB;
- struct BusLogic_CCB *LastCompletedCCB;
- struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
- struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
- unsigned char QueueDepth[BusLogic_MaxTargetDevices];
- unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
- unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
- unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
- unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
- unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
- unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
- unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
- struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
- struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
- struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
- struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
- struct BusLogic_IncomingMailbox *LastIncomingMailbox;
- struct BusLogic_IncomingMailbox *NextIncomingMailbox;
- struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
- unsigned char *MailboxSpace;
- dma_addr_t MailboxSpaceHandle;
- unsigned int MailboxSize;
- unsigned long CCB_Offset;
- char MessageBuffer[BusLogic_MessageBufferSize];
+ struct blogic_ccb *all_ccbs;
+ struct blogic_ccb *free_ccbs;
+ struct blogic_ccb *firstccb;
+ struct blogic_ccb *lastccb;
+ struct blogic_ccb *bdr_pend[BLOGIC_MAXDEV];
+ struct blogic_tgt_flags tgt_flags[BLOGIC_MAXDEV];
+ unsigned char qdepth[BLOGIC_MAXDEV];
+ unsigned char sync_period[BLOGIC_MAXDEV];
+ unsigned char sync_offset[BLOGIC_MAXDEV];
+ unsigned char active_cmds[BLOGIC_MAXDEV];
+ unsigned int cmds_since_rst[BLOGIC_MAXDEV];
+ unsigned long last_seqpoint[BLOGIC_MAXDEV];
+ unsigned long last_resettried[BLOGIC_MAXDEV];
+ unsigned long last_resetdone[BLOGIC_MAXDEV];
+ struct blogic_outbox *first_outbox;
+ struct blogic_outbox *last_outbox;
+ struct blogic_outbox *next_outbox;
+ struct blogic_inbox *first_inbox;
+ struct blogic_inbox *last_inbox;
+ struct blogic_inbox *next_inbox;
+ struct blogic_tgt_stats tgt_stats[BLOGIC_MAXDEV];
+ unsigned char *mbox_space;
+ dma_addr_t mbox_space_handle;
+ unsigned int mbox_sz;
+ unsigned long ccb_offset;
+ char msgbuf[BLOGIC_MSGBUF_SIZE];
};
/*
Define a structure for the BIOS Disk Parameters.
*/
-struct BIOS_DiskParameters {
- int Heads;
- int Sectors;
- int Cylinders;
+struct bios_diskparam {
+ int heads;
+ int sectors;
+ int cylinders;
};
/*
Define a structure for the SCSI Inquiry command results.
*/
-struct SCSI_Inquiry {
- unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */
- unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
- unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */
- bool RMB:1; /* Byte 1 Bit 7 */
- unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */
- unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */
- unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */
- unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */
- unsigned char:2; /* Byte 3 Bits 4-5 */
- bool TrmIOP:1; /* Byte 3 Bit 6 */
- bool AENC:1; /* Byte 3 Bit 7 */
- unsigned char AdditionalLength; /* Byte 4 */
- unsigned char:8; /* Byte 5 */
- unsigned char:8; /* Byte 6 */
- bool SftRe:1; /* Byte 7 Bit 0 */
- bool CmdQue:1; /* Byte 7 Bit 1 */
- bool:1; /* Byte 7 Bit 2 */
- bool Linked:1; /* Byte 7 Bit 3 */
- bool Sync:1; /* Byte 7 Bit 4 */
- bool WBus16:1; /* Byte 7 Bit 5 */
- bool WBus32:1; /* Byte 7 Bit 6 */
- bool RelAdr:1; /* Byte 7 Bit 7 */
- unsigned char VendorIdentification[8]; /* Bytes 8-15 */
- unsigned char ProductIdentification[16]; /* Bytes 16-31 */
- unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */
+struct scsi_inquiry {
+ unsigned char devtype:5; /* Byte 0 Bits 0-4 */
+ unsigned char dev_qual:3; /* Byte 0 Bits 5-7 */
+ unsigned char dev_modifier:7; /* Byte 1 Bits 0-6 */
+ bool rmb:1; /* Byte 1 Bit 7 */
+ unsigned char ansi_ver:3; /* Byte 2 Bits 0-2 */
+ unsigned char ecma_ver:3; /* Byte 2 Bits 3-5 */
+ unsigned char iso_ver:2; /* Byte 2 Bits 6-7 */
+ unsigned char resp_fmt:4; /* Byte 3 Bits 0-3 */
+ unsigned char:2; /* Byte 3 Bits 4-5 */
+ bool TrmIOP:1; /* Byte 3 Bit 6 */
+ bool AENC:1; /* Byte 3 Bit 7 */
+ unsigned char addl_len; /* Byte 4 */
+ unsigned char:8; /* Byte 5 */
+ unsigned char:8; /* Byte 6 */
+ bool SftRe:1; /* Byte 7 Bit 0 */
+ bool CmdQue:1; /* Byte 7 Bit 1 */
+ bool:1; /* Byte 7 Bit 2 */
+ bool linked:1; /* Byte 7 Bit 3 */
+ bool sync:1; /* Byte 7 Bit 4 */
+ bool WBus16:1; /* Byte 7 Bit 5 */
+ bool WBus32:1; /* Byte 7 Bit 6 */
+ bool RelAdr:1; /* Byte 7 Bit 7 */
+ unsigned char vendor[8]; /* Bytes 8-15 */
+ unsigned char product[16]; /* Bytes 16-31 */
+ unsigned char product_rev[4]; /* Bytes 32-35 */
};
@@ -1148,185 +1133,170 @@ struct SCSI_Inquiry {
Host Adapter I/O Registers.
*/
-static inline void BusLogic_SCSIBusReset(struct BusLogic_HostAdapter *HostAdapter)
+static inline void blogic_busreset(struct blogic_adapter *adapter)
{
- union BusLogic_ControlRegister ControlRegister;
- ControlRegister.All = 0;
- ControlRegister.cr.SCSIBusReset = true;
- outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+ union blogic_cntrl_reg cr;
+ cr.all = 0;
+ cr.cr.bus_reset = true;
+ outb(cr.all, adapter->io_addr + BLOGIC_CNTRL_REG);
}
-static inline void BusLogic_InterruptReset(struct BusLogic_HostAdapter *HostAdapter)
+static inline void blogic_intreset(struct blogic_adapter *adapter)
{
- union BusLogic_ControlRegister ControlRegister;
- ControlRegister.All = 0;
- ControlRegister.cr.InterruptReset = true;
- outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+ union blogic_cntrl_reg cr;
+ cr.all = 0;
+ cr.cr.int_reset = true;
+ outb(cr.all, adapter->io_addr + BLOGIC_CNTRL_REG);
}
-static inline void BusLogic_SoftReset(struct BusLogic_HostAdapter *HostAdapter)
+static inline void blogic_softreset(struct blogic_adapter *adapter)
{
- union BusLogic_ControlRegister ControlRegister;
- ControlRegister.All = 0;
- ControlRegister.cr.SoftReset = true;
- outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+ union blogic_cntrl_reg cr;
+ cr.all = 0;
+ cr.cr.soft_reset = true;
+ outb(cr.all, adapter->io_addr + BLOGIC_CNTRL_REG);
}
-static inline void BusLogic_HardReset(struct BusLogic_HostAdapter *HostAdapter)
+static inline void blogic_hardreset(struct blogic_adapter *adapter)
{
- union BusLogic_ControlRegister ControlRegister;
- ControlRegister.All = 0;
- ControlRegister.cr.HardReset = true;
- outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+ union blogic_cntrl_reg cr;
+ cr.all = 0;
+ cr.cr.hard_reset = true;
+ outb(cr.all, adapter->io_addr + BLOGIC_CNTRL_REG);
}
-static inline unsigned char BusLogic_ReadStatusRegister(struct BusLogic_HostAdapter *HostAdapter)
+static inline unsigned char blogic_rdstatus(struct blogic_adapter *adapter)
{
- return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
+ return inb(adapter->io_addr + BLOGIC_STATUS_REG);
}
-static inline void BusLogic_WriteCommandParameterRegister(struct BusLogic_HostAdapter
- *HostAdapter, unsigned char Value)
+static inline void blogic_setcmdparam(struct blogic_adapter *adapter,
+ unsigned char value)
{
- outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
+ outb(value, adapter->io_addr + BLOGIC_CMD_PARM_REG);
}
-static inline unsigned char BusLogic_ReadDataInRegister(struct BusLogic_HostAdapter *HostAdapter)
+static inline unsigned char blogic_rddatain(struct blogic_adapter *adapter)
{
- return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
+ return inb(adapter->io_addr + BLOGIC_DATAIN_REG);
}
-static inline unsigned char BusLogic_ReadInterruptRegister(struct BusLogic_HostAdapter *HostAdapter)
+static inline unsigned char blogic_rdint(struct blogic_adapter *adapter)
{
- return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
+ return inb(adapter->io_addr + BLOGIC_INT_REG);
}
-static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAdapter *HostAdapter)
+static inline unsigned char blogic_rdgeom(struct blogic_adapter *adapter)
{
- return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
+ return inb(adapter->io_addr + BLOGIC_GEOMETRY_REG);
}
/*
- BusLogic_StartMailboxCommand issues an Execute Mailbox Command, which
+ blogic_execmbox issues an Execute Mailbox Command, which
notifies the Host Adapter that an entry has been made in an Outgoing
Mailbox.
*/
-static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *HostAdapter)
+static inline void blogic_execmbox(struct blogic_adapter *adapter)
{
- BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
+ blogic_setcmdparam(adapter, BLOGIC_EXEC_MBOX_CMD);
}
/*
- BusLogic_Delay waits for Seconds to elapse.
+ blogic_delay waits for Seconds to elapse.
*/
-static inline void BusLogic_Delay(int Seconds)
-{
- mdelay(1000 * Seconds);
-}
-
-/*
- Virtual_to_Bus and Bus_to_Virtual map between Kernel Virtual Addresses
- and PCI/VLB/EISA/ISA Bus Addresses.
-*/
-
-static inline u32 Virtual_to_Bus(void *VirtualAddress)
-{
- return (u32) virt_to_bus(VirtualAddress);
-}
-
-static inline void *Bus_to_Virtual(u32 BusAddress)
+static inline void blogic_delay(int seconds)
{
- return (void *) bus_to_virt(BusAddress);
+ mdelay(1000 * seconds);
}
/*
- Virtual_to_32Bit_Virtual maps between Kernel Virtual Addresses and
+ virt_to_32bit_virt maps between Kernel Virtual Addresses and
32 bit Kernel Virtual Addresses. This avoids compilation warnings
on 64 bit architectures.
*/
-static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress)
+static inline u32 virt_to_32bit_virt(void *virt_addr)
{
- return (u32) (unsigned long) VirtualAddress;
+ return (u32) (unsigned long) virt_addr;
}
/*
- BusLogic_IncrementErrorCounter increments Error Counter by 1, stopping at
+ blogic_inc_count increments counter by 1, stopping at
65535 rather than wrapping around to 0.
*/
-static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
+static inline void blogic_inc_count(unsigned short *count)
{
- if (*ErrorCounter < 65535)
- (*ErrorCounter)++;
+ if (*count < 65535)
+ (*count)++;
}
/*
- BusLogic_IncrementByteCounter increments Byte Counter by Amount.
+ blogic_addcount increments Byte Counter by Amount.
*/
-static inline void BusLogic_IncrementByteCounter(struct BusLogic_ByteCounter
- *ByteCounter, unsigned int Amount)
+static inline void blogic_addcount(struct blogic_byte_count *bytecount,
+ unsigned int amount)
{
- ByteCounter->Units += Amount;
- if (ByteCounter->Units > 999999999) {
- ByteCounter->Units -= 1000000000;
- ByteCounter->Billions++;
+ bytecount->units += amount;
+ if (bytecount->units > 999999999) {
+ bytecount->units -= 1000000000;
+ bytecount->billions++;
}
}
/*
- BusLogic_IncrementSizeBucket increments the Bucket for Amount.
+ blogic_incszbucket increments the Bucket for Amount.
*/
-static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T CommandSizeBuckets, unsigned int Amount)
+static inline void blogic_incszbucket(unsigned int *cmdsz_buckets,
+ unsigned int amount)
{
- int Index = 0;
- if (Amount < 8 * 1024) {
- if (Amount < 2 * 1024)
- Index = (Amount < 1 * 1024 ? 0 : 1);
+ int index = 0;
+ if (amount < 8 * 1024) {
+ if (amount < 2 * 1024)
+ index = (amount < 1 * 1024 ? 0 : 1);
else
- Index = (Amount < 4 * 1024 ? 2 : 3);
- } else if (Amount < 128 * 1024) {
- if (Amount < 32 * 1024)
- Index = (Amount < 16 * 1024 ? 4 : 5);
+ index = (amount < 4 * 1024 ? 2 : 3);
+ } else if (amount < 128 * 1024) {
+ if (amount < 32 * 1024)
+ index = (amount < 16 * 1024 ? 4 : 5);
else
- Index = (Amount < 64 * 1024 ? 6 : 7);
+ index = (amount < 64 * 1024 ? 6 : 7);
} else
- Index = (Amount < 256 * 1024 ? 8 : 9);
- CommandSizeBuckets[Index]++;
+ index = (amount < 256 * 1024 ? 8 : 9);
+ cmdsz_buckets[index]++;
}
/*
Define the version number of the FlashPoint Firmware (SCCB Manager).
*/
-#define FlashPoint_FirmwareVersion "5.02"
+#define FLASHPOINT_FW_VER "5.02"
/*
Define the possible return values from FlashPoint_HandleInterrupt.
*/
-#define FlashPoint_NormalInterrupt 0x00
-#define FlashPoint_InternalError 0xFE
-#define FlashPoint_ExternalBusReset 0xFF
+#define FPOINT_NORMAL_INT 0x00
+#define FPOINT_INTERN_ERR 0xFE
+#define FPOINT_EXT_RESET 0xFF
/*
Define prototypes for the forward referenced BusLogic Driver
Internal Functions.
*/
-static const char *BusLogic_DriverInfo(struct Scsi_Host *);
-static int BusLogic_QueueCommand(struct Scsi_Host *h, struct scsi_cmnd *);
-static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *);
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
-static int BusLogic_SlaveConfigure(struct scsi_device *);
-static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
-static irqreturn_t BusLogic_InterruptHandler(int, void *);
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, bool HardReset);
-static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
-static int __init BusLogic_Setup(char *);
+static const char *blogic_drvr_info(struct Scsi_Host *);
+static int blogic_qcmd(struct Scsi_Host *h, struct scsi_cmnd *);
+static int blogic_diskparam(struct scsi_device *, struct block_device *, sector_t, int *);
+static int blogic_slaveconfig(struct scsi_device *);
+static void blogic_qcompleted_ccb(struct blogic_ccb *);
+static irqreturn_t blogic_inthandler(int, void *);
+static int blogic_resetadapter(struct blogic_adapter *, bool hard_reset);
+static void blogic_msg(enum blogic_msglevel, char *, struct blogic_adapter *, ...);
+static int __init blogic_setup(char *);
#endif /* _BUSLOGIC_H */
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index dcd716d..5c74e4c 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -29,27 +29,27 @@ struct sccb;
typedef void (*CALL_BK_FN) (struct sccb *);
struct sccb_mgr_info {
- unsigned long si_baseaddr;
+ u32 si_baseaddr;
unsigned char si_present;
unsigned char si_intvect;
unsigned char si_id;
unsigned char si_lun;
- unsigned short si_fw_revision;
- unsigned short si_per_targ_init_sync;
- unsigned short si_per_targ_fast_nego;
- unsigned short si_per_targ_ultra_nego;
- unsigned short si_per_targ_no_disc;
- unsigned short si_per_targ_wide_nego;
- unsigned short si_flags;
+ u16 si_fw_revision;
+ u16 si_per_targ_init_sync;
+ u16 si_per_targ_fast_nego;
+ u16 si_per_targ_ultra_nego;
+ u16 si_per_targ_no_disc;
+ u16 si_per_targ_wide_nego;
+ u16 si_flags;
unsigned char si_card_family;
unsigned char si_bustype;
unsigned char si_card_model[3];
unsigned char si_relative_cardnum;
unsigned char si_reserved[4];
- unsigned long si_OS_reserved;
+ u32 si_OS_reserved;
unsigned char si_XlatInfo[4];
- unsigned long si_reserved2[5];
- unsigned long si_secondary_range;
+ u32 si_reserved2[5];
+ u32 si_secondary_range;
};
#define SCSI_PARITY_ENA 0x0001
@@ -70,14 +70,14 @@ struct sccb_mgr_info {
* The UCB Manager treats the SCCB as it's 'native hardware structure'
*/
-#pragma pack(1)
+/*#pragma pack(1)*/
struct sccb {
unsigned char OperationCode;
unsigned char ControlByte;
unsigned char CdbLength;
unsigned char RequestSenseLength;
- unsigned long DataLength;
- unsigned long DataPointer;
+ u32 DataLength;
+ void *DataPointer;
unsigned char CcbRes[2];
unsigned char HostStatus;
unsigned char TargetStatus;
@@ -86,32 +86,32 @@ struct sccb {
unsigned char Cdb[12];
unsigned char CcbRes1;
unsigned char Reserved1;
- unsigned long Reserved2;
- unsigned long SensePointer;
+ u32 Reserved2;
+ u32 SensePointer;
CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
- unsigned long SccbIOPort; /* Identifies board base port */
+ u32 SccbIOPort; /* Identifies board base port */
unsigned char SccbStatus;
unsigned char SCCBRes2;
- unsigned short SccbOSFlags;
-
- unsigned long Sccb_XferCnt; /* actual transfer count */
- unsigned long Sccb_ATC;
- unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */
- unsigned long Sccb_res1;
- unsigned short Sccb_MGRFlags;
- unsigned short Sccb_sgseg;
+ u16 SccbOSFlags;
+
+ u32 Sccb_XferCnt; /* actual transfer count */
+ u32 Sccb_ATC;
+ u32 SccbVirtDataPtr; /* virtual addr for OS/2 */
+ u32 Sccb_res1;
+ u16 Sccb_MGRFlags;
+ u16 Sccb_sgseg;
unsigned char Sccb_scsimsg; /* identify msg for selection */
unsigned char Sccb_tag;
unsigned char Sccb_scsistat;
unsigned char Sccb_idmsg; /* image of last msg in */
struct sccb *Sccb_forwardlink;
struct sccb *Sccb_backlink;
- unsigned long Sccb_savedATC;
+ u32 Sccb_savedATC;
unsigned char Save_Cdb[6];
unsigned char Save_CdbLen;
unsigned char Sccb_XferState;
- unsigned long Sccb_SGoffset;
+ u32 Sccb_SGoffset;
};
#pragma pack()
@@ -223,15 +223,21 @@ struct sccb_mgr_tar_info {
};
struct nvram_info {
- unsigned char niModel; /* Model No. of card */
- unsigned char niCardNo; /* Card no. */
- unsigned long niBaseAddr; /* Port Address of card */
- unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
- unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
- unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
- unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */
- unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */
- unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
+ unsigned char niModel; /* Model No. of card */
+ unsigned char niCardNo; /* Card no. */
+ u32 niBaseAddr; /* Port Address of card */
+ unsigned char niSysConf; /* Adapter Configuration byte -
+ Byte 16 of eeprom map */
+ unsigned char niScsiConf; /* SCSI Configuration byte -
+ Byte 17 of eeprom map */
+ unsigned char niScamConf; /* SCAM Configuration byte -
+ Byte 20 of eeprom map */
+ unsigned char niAdapId; /* Host Adapter ID -
+ Byte 24 of eerpom map */
+ unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte
+ of targets */
+ unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name
+ string of Targets */
};
#define MODEL_LT 1
@@ -243,7 +249,7 @@ struct sccb_card {
struct sccb *currentSCCB;
struct sccb_mgr_info *cardInfo;
- unsigned long ioPort;
+ u32 ioPort;
unsigned short cmdCounter;
unsigned char discQCount;
@@ -780,37 +786,37 @@ typedef struct SCCBscam_info {
#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
(RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
-static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
+static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
unsigned char syncFlag);
-static void FPT_ssel(unsigned long port, unsigned char p_card);
-static void FPT_sres(unsigned long port, unsigned char p_card,
+static void FPT_ssel(u32 port, unsigned char p_card);
+static void FPT_sres(u32 port, unsigned char p_card,
struct sccb_card *pCurrCard);
-static void FPT_shandem(unsigned long port, unsigned char p_card,
+static void FPT_shandem(u32 port, unsigned char p_card,
struct sccb *pCurrSCCB);
-static void FPT_stsyncn(unsigned long port, unsigned char p_card);
-static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
+static void FPT_stsyncn(u32 port, unsigned char p_card);
+static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
unsigned char offset);
-static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
+static void FPT_sssyncv(u32 p_port, unsigned char p_id,
unsigned char p_sync_value,
struct sccb_mgr_tar_info *currTar_Info);
-static void FPT_sresb(unsigned long port, unsigned char p_card);
-static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
-static void FPT_schkdd(unsigned long port, unsigned char p_card);
-static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
-static void FPT_WrStack(unsigned long portBase, unsigned char index,
+static void FPT_sresb(u32 port, unsigned char p_card);
+static void FPT_sxfrp(u32 p_port, unsigned char p_card);
+static void FPT_schkdd(u32 port, unsigned char p_card);
+static unsigned char FPT_RdStack(u32 port, unsigned char index);
+static void FPT_WrStack(u32 portBase, unsigned char index,
unsigned char data);
-static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
+static unsigned char FPT_ChkIfChipInitialized(u32 ioPort);
-static void FPT_SendMsg(unsigned long port, unsigned char message);
+static void FPT_SendMsg(u32 port, unsigned char message);
static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
unsigned char error_code);
static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
-static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
-static void FPT_stwidn(unsigned long port, unsigned char p_card);
-static void FPT_siwidr(unsigned long port, unsigned char width);
+static unsigned char FPT_siwidn(u32 port, unsigned char p_card);
+static void FPT_stwidn(u32 port, unsigned char p_card);
+static void FPT_siwidr(u32 port, unsigned char width);
static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
unsigned char p_card);
@@ -827,45 +833,45 @@ static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
static unsigned char FPT_CalcLrc(unsigned char buffer[]);
-static void FPT_Wait1Second(unsigned long p_port);
-static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
-static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
-static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
+static void FPT_Wait1Second(u32 p_port);
+static void FPT_Wait(u32 p_port, unsigned char p_delay);
+static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode);
+static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
unsigned short ee_addr);
-static unsigned short FPT_utilEERead(unsigned long p_port,
+static unsigned short FPT_utilEERead(u32 p_port,
unsigned short ee_addr);
-static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
+static unsigned short FPT_utilEEReadOrg(u32 p_port,
unsigned short ee_addr);
-static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
+static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
unsigned short ee_addr);
-static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
-static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
-static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
-static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
-static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
-static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
-static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
+static void FPT_phaseDataOut(u32 port, unsigned char p_card);
+static void FPT_phaseDataIn(u32 port, unsigned char p_card);
+static void FPT_phaseCommand(u32 port, unsigned char p_card);
+static void FPT_phaseStatus(u32 port, unsigned char p_card);
+static void FPT_phaseMsgOut(u32 port, unsigned char p_card);
+static void FPT_phaseMsgIn(u32 port, unsigned char p_card);
+static void FPT_phaseIllegal(u32 port, unsigned char p_card);
-static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
-static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
-static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
+static void FPT_phaseDecode(u32 port, unsigned char p_card);
+static void FPT_phaseChkFifo(u32 port, unsigned char p_card);
+static void FPT_phaseBusFree(u32 p_port, unsigned char p_card);
-static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
-static void FPT_BusMasterInit(unsigned long p_port);
-static void FPT_DiagEEPROM(unsigned long p_port);
+static void FPT_XbowInit(u32 port, unsigned char scamFlg);
+static void FPT_BusMasterInit(u32 p_port);
+static void FPT_DiagEEPROM(u32 p_port);
-static void FPT_dataXferProcessor(unsigned long port,
+static void FPT_dataXferProcessor(u32 port,
struct sccb_card *pCurrCard);
-static void FPT_busMstrSGDataXferStart(unsigned long port,
+static void FPT_busMstrSGDataXferStart(u32 port,
struct sccb *pCurrSCCB);
-static void FPT_busMstrDataXferStart(unsigned long port,
+static void FPT_busMstrDataXferStart(u32 port,
struct sccb *pCurrSCCB);
-static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
+static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
struct sccb *pCurrSCCB);
static void FPT_hostDataXferRestart(struct sccb *currSCCB);
-static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
+static unsigned char FPT_SccbMgr_bad_isr(u32 p_port,
unsigned char p_card,
struct sccb_card *pCurrCard,
unsigned short p_int);
@@ -879,28 +885,28 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
unsigned char p_power_up);
-static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
-static void FPT_scbusf(unsigned long p_port);
-static void FPT_scsel(unsigned long p_port);
-static void FPT_scasid(unsigned char p_card, unsigned long p_port);
-static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
-static unsigned char FPT_scsendi(unsigned long p_port,
+static int FPT_scarb(u32 p_port, unsigned char p_sel_type);
+static void FPT_scbusf(u32 p_port);
+static void FPT_scsel(u32 p_port);
+static void FPT_scasid(unsigned char p_card, u32 p_port);
+static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data);
+static unsigned char FPT_scsendi(u32 p_port,
unsigned char p_id_string[]);
-static unsigned char FPT_sciso(unsigned long p_port,
+static unsigned char FPT_sciso(u32 p_port,
unsigned char p_id_string[]);
-static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
-static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
+static void FPT_scwirod(u32 p_port, unsigned char p_data_bit);
+static void FPT_scwiros(u32 p_port, unsigned char p_data_bit);
static unsigned char FPT_scvalq(unsigned char p_quintet);
-static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
-static void FPT_scwtsel(unsigned long p_port);
-static void FPT_inisci(unsigned char p_card, unsigned long p_port,
+static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id);
+static void FPT_scwtsel(u32 p_port);
+static void FPT_inisci(unsigned char p_card, u32 p_port,
unsigned char p_our_id);
-static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
+static void FPT_scsavdi(unsigned char p_card, u32 p_port);
static unsigned char FPT_scmachid(unsigned char p_card,
unsigned char p_id_string[]);
-static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
-static void FPT_autoLoadDefaultMap(unsigned long p_port);
+static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card);
+static void FPT_autoLoadDefaultMap(u32 p_port);
static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
{ {{0}} };
@@ -918,7 +924,7 @@ static unsigned char FPT_scamHAString[] =
static unsigned short FPT_default_intena = 0;
-static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
+static void (*FPT_s_PhaseTbl[8]) (u32, unsigned char) = {
0};
/*---------------------------------------------------------------------
@@ -935,7 +941,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
unsigned char i, j, id, ScamFlg;
unsigned short temp, temp2, temp3, temp4, temp5, temp6;
- unsigned long ioport;
+ u32 ioport;
struct nvram_info *pCurrNvRam;
ioport = pCardInfo->si_baseaddr;
@@ -1201,23 +1207,21 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
*
*---------------------------------------------------------------------*/
-static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
+static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
*pCardInfo)
{
struct sccb_card *CurrCard = NULL;
struct nvram_info *pCurrNvRam;
unsigned char i, j, thisCard, ScamFlg;
unsigned short temp, sync_bit_map, id;
- unsigned long ioport;
+ u32 ioport;
ioport = pCardInfo->si_baseaddr;
for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
- if (thisCard == MAX_CARDS) {
-
- return FAILURE;
- }
+ if (thisCard == MAX_CARDS)
+ return (void *)FAILURE;
if (FPT_BL_Card[thisCard].ioPort == ioport) {
@@ -1384,16 +1388,16 @@ static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
(unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
SCCB_MGR_PRESENT));
- return (unsigned long)CurrCard;
+ return (void *)CurrCard;
}
-static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
+static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
{
unsigned char i;
- unsigned long portBase;
- unsigned long regOffset;
- unsigned long scamData;
- unsigned long *pScamTbl;
+ u32 portBase;
+ u32 regOffset;
+ u32 scamData;
+ u32 *pScamTbl;
struct nvram_info *pCurrNvRam;
pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
@@ -1414,7 +1418,7 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
for (i = 0; i < MAX_SCSI_TAR; i++) {
regOffset = hp_aramBase + 64 + i * 4;
- pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
+ pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
scamData = *pScamTbl;
WR_HARP32(portBase, regOffset, scamData);
}
@@ -1427,10 +1431,10 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
{
unsigned char i;
- unsigned long portBase;
- unsigned long regOffset;
- unsigned long scamData;
- unsigned long *pScamTbl;
+ u32 portBase;
+ u32 regOffset;
+ u32 scamData;
+ u32 *pScamTbl;
pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
@@ -1447,26 +1451,25 @@ static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
for (i = 0; i < MAX_SCSI_TAR; i++) {
regOffset = hp_aramBase + 64 + i * 4;
RD_HARP32(portBase, regOffset, scamData);
- pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
+ pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
*pScamTbl = scamData;
}
}
-static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
+static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
{
WR_HARPOON(portBase + hp_stack_addr, index);
return RD_HARPOON(portBase + hp_stack_data);
}
-static void FPT_WrStack(unsigned long portBase, unsigned char index,
- unsigned char data)
+static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
{
WR_HARPOON(portBase + hp_stack_addr, index);
WR_HARPOON(portBase + hp_stack_data, data);
}
-static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
+static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
{
if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
return 0;
@@ -1489,15 +1492,16 @@ static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
* callback function.
*
*---------------------------------------------------------------------*/
-static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
+static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
{
- unsigned long ioport;
+ u32 ioport;
unsigned char thisCard, lun;
struct sccb *pSaveSccb;
CALL_BK_FN callback;
+ struct sccb_card *pCurrCard = curr_card;
- thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
- ioport = ((struct sccb_card *)pCurrCard)->ioPort;
+ thisCard = pCurrCard->cardIndex;
+ ioport = pCurrCard->ioPort;
if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
@@ -1512,18 +1516,18 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
FPT_sinits(p_Sccb, thisCard);
- if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
+ if (!pCurrCard->cmdCounter) {
WR_HARPOON(ioport + hp_semaphore,
(RD_HARPOON(ioport + hp_semaphore)
| SCCB_MGR_ACTIVE));
- if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
+ if (pCurrCard->globalFlags & F_GREEN_PC) {
WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
}
}
- ((struct sccb_card *)pCurrCard)->cmdCounter++;
+ pCurrCard->cmdCounter++;
if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
@@ -1532,10 +1536,10 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
| TICKLE_ME));
if (p_Sccb->OperationCode == RESET_COMMAND) {
pSaveSccb =
- ((struct sccb_card *)pCurrCard)->currentSCCB;
- ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
+ pCurrCard->currentSCCB;
+ pCurrCard->currentSCCB = p_Sccb;
FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
- ((struct sccb_card *)pCurrCard)->currentSCCB =
+ pCurrCard->currentSCCB =
pSaveSccb;
} else {
FPT_queueAddSccb(p_Sccb, thisCard);
@@ -1546,10 +1550,10 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
if (p_Sccb->OperationCode == RESET_COMMAND) {
pSaveSccb =
- ((struct sccb_card *)pCurrCard)->currentSCCB;
- ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
+ pCurrCard->currentSCCB;
+ pCurrCard->currentSCCB = p_Sccb;
FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
- ((struct sccb_card *)pCurrCard)->currentSCCB =
+ pCurrCard->currentSCCB =
pSaveSccb;
} else {
FPT_queueAddSccb(p_Sccb, thisCard);
@@ -1560,34 +1564,29 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
MDISABLE_INT(ioport);
- if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
- &&
+ if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
lun = p_Sccb->Lun;
else
lun = 0;
- if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
+ if ((pCurrCard->currentSCCB == NULL) &&
(FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
&& (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
== 0)) {
- ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
+ pCurrCard->currentSCCB = p_Sccb;
FPT_ssel(p_Sccb->SccbIOPort, thisCard);
}
else {
if (p_Sccb->OperationCode == RESET_COMMAND) {
- pSaveSccb =
- ((struct sccb_card *)pCurrCard)->
- currentSCCB;
- ((struct sccb_card *)pCurrCard)->currentSCCB =
- p_Sccb;
+ pSaveSccb = pCurrCard->currentSCCB;
+ pCurrCard->currentSCCB = p_Sccb;
FPT_queueSelectFail(&FPT_BL_Card[thisCard],
thisCard);
- ((struct sccb_card *)pCurrCard)->currentSCCB =
- pSaveSccb;
+ pCurrCard->currentSCCB = pSaveSccb;
} else {
FPT_queueAddSccb(p_Sccb, thisCard);
}
@@ -1607,9 +1606,9 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
* callback function.
*
*---------------------------------------------------------------------*/
-static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
+static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
{
- unsigned long ioport;
+ u32 ioport;
unsigned char thisCard;
CALL_BK_FN callback;
@@ -1715,9 +1714,9 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
* interrupt for this card and disable the IRQ Pin if so.
*
*---------------------------------------------------------------------*/
-static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
+static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
{
- unsigned long ioport;
+ u32 ioport;
ioport = ((struct sccb_card *)pCurrCard)->ioPort;
@@ -1739,38 +1738,36 @@ static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
* us.
*
*---------------------------------------------------------------------*/
-static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
+static int FlashPoint_HandleInterrupt(void *pcard)
{
struct sccb *currSCCB;
unsigned char thisCard, result, bm_status, bm_int_st;
unsigned short hp_int;
unsigned char i, target;
- unsigned long ioport;
+ struct sccb_card *pCurrCard = pcard;
+ u32 ioport;
- thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
- ioport = ((struct sccb_card *)pCurrCard)->ioPort;
+ thisCard = pCurrCard->cardIndex;
+ ioport = pCurrCard->ioPort;
MDISABLE_INT(ioport);
if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
- bm_status =
- RD_HARPOON(ioport +
- hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
+ bm_status = RD_HARPOON(ioport + hp_ext_status) &
+ (unsigned char)BAD_EXT_STATUS;
else
bm_status = 0;
WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
- while ((hp_int =
- RDW_HARPOON((ioport +
- hp_intstat)) & FPT_default_intena) | bm_status) {
+ while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
+ FPT_default_intena) | bm_status) {
- currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
+ currSCCB = pCurrCard->currentSCCB;
if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
result =
- FPT_SccbMgr_bad_isr(ioport, thisCard,
- ((struct sccb_card *)pCurrCard),
+ FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
hp_int);
WRW_HARPOON((ioport + hp_intstat),
(FIFO | TIMEOUT | RESET | SCAM_SEL));
@@ -1796,8 +1793,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
(BUS_FREE | RSEL))) ;
}
- if (((struct sccb_card *)pCurrCard)->
- globalFlags & F_HOST_XFER_ACT)
+ if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
FPT_phaseChkFifo(ioport, thisCard);
@@ -1813,14 +1809,11 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
else if (hp_int & ITAR_DISC) {
- if (((struct sccb_card *)pCurrCard)->
- globalFlags & F_HOST_XFER_ACT) {
-
+ if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
FPT_phaseChkFifo(ioport, thisCard);
- }
-
- if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
+ if (RD_HARPOON(ioport + hp_gp_reg_1) ==
+ SMSAVE_DATA_PTR) {
WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
currSCCB->Sccb_XferState |= F_NO_DATA_YET;
@@ -1859,8 +1852,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
WRW_HARPOON((ioport + hp_intstat),
(BUS_FREE | ITAR_DISC));
- ((struct sccb_card *)pCurrCard)->globalFlags |=
- F_NEW_SCCB_CMD;
+ pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
}
@@ -1870,10 +1862,8 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
(PROG_HLT | RSEL | PHASE | BUS_FREE));
if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
- if (((struct sccb_card *)pCurrCard)->
- globalFlags & F_HOST_XFER_ACT) {
+ if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
FPT_phaseChkFifo(ioport, thisCard);
- }
if (RD_HARPOON(ioport + hp_gp_reg_1) ==
SMSAVE_DATA_PTR) {
@@ -1890,8 +1880,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
FPT_queueDisconnect(currSCCB, thisCard);
}
- FPT_sres(ioport, thisCard,
- ((struct sccb_card *)pCurrCard));
+ FPT_sres(ioport, thisCard, pCurrCard);
FPT_phaseDecode(ioport, thisCard);
}
@@ -1948,8 +1937,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
- if (((struct sccb_card *)pCurrCard)->
- globalFlags & F_HOST_XFER_ACT) {
+ if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
FPT_hostDataXferAbort(ioport, thisCard,
currSCCB);
@@ -1961,27 +1949,19 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
else if (hp_int & ITICKLE) {
WRW_HARPOON((ioport + hp_intstat), ITICKLE);
- ((struct sccb_card *)pCurrCard)->globalFlags |=
- F_NEW_SCCB_CMD;
+ pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
}
if (((struct sccb_card *)pCurrCard)->
globalFlags & F_NEW_SCCB_CMD) {
- ((struct sccb_card *)pCurrCard)->globalFlags &=
- ~F_NEW_SCCB_CMD;
+ pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
- if (((struct sccb_card *)pCurrCard)->currentSCCB ==
- NULL) {
-
- FPT_queueSearchSelect(((struct sccb_card *)
- pCurrCard), thisCard);
- }
+ if (pCurrCard->currentSCCB == NULL)
+ FPT_queueSearchSelect(pCurrCard, thisCard);
- if (((struct sccb_card *)pCurrCard)->currentSCCB !=
- NULL) {
- ((struct sccb_card *)pCurrCard)->globalFlags &=
- ~F_NEW_SCCB_CMD;
+ if (pCurrCard->currentSCCB != NULL) {
+ pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
FPT_ssel(ioport, thisCard);
}
@@ -2006,8 +1986,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
* processing time.
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
- unsigned char p_card,
+static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
struct sccb_card *pCurrCard,
unsigned short p_int)
{
@@ -2254,7 +2233,7 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
+static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
{
unsigned char message;
unsigned short TimeOutLoop;
@@ -2322,12 +2301,12 @@ static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
*
*---------------------------------------------------------------------*/
-static void FPT_ssel(unsigned long port, unsigned char p_card)
+static void FPT_ssel(u32 port, unsigned char p_card)
{
unsigned char auto_loaded, i, target, *theCCB;
- unsigned long cdb_reg;
+ u32 cdb_reg;
struct sccb_card *CurrCard;
struct sccb *currSCCB;
struct sccb_mgr_tar_info *currTar_Info;
@@ -2621,7 +2600,7 @@ static void FPT_ssel(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_sres(unsigned long port, unsigned char p_card,
+static void FPT_sres(u32 port, unsigned char p_card,
struct sccb_card *pCurrCard)
{
@@ -2857,7 +2836,7 @@ static void FPT_sres(unsigned long port, unsigned char p_card,
(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
}
-static void FPT_SendMsg(unsigned long port, unsigned char message)
+static void FPT_SendMsg(u32 port, unsigned char message)
{
while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
@@ -2904,8 +2883,7 @@ static void FPT_SendMsg(unsigned long port, unsigned char message)
* target device.
*
*---------------------------------------------------------------------*/
-static void FPT_sdecm(unsigned char message, unsigned long port,
- unsigned char p_card)
+static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
{
struct sccb *currSCCB;
struct sccb_card *CurrCard;
@@ -3085,8 +3063,7 @@ static void FPT_sdecm(unsigned char message, unsigned long port,
* Description: Decide what to do with the extended message.
*
*---------------------------------------------------------------------*/
-static void FPT_shandem(unsigned long port, unsigned char p_card,
- struct sccb *pCurrSCCB)
+static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
{
unsigned char length, message;
@@ -3153,7 +3130,7 @@ static void FPT_shandem(unsigned long port, unsigned char p_card,
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
+static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
unsigned char syncFlag)
{
struct sccb *currSCCB;
@@ -3234,7 +3211,7 @@ static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
* necessary.
*
*---------------------------------------------------------------------*/
-static void FPT_stsyncn(unsigned long port, unsigned char p_card)
+static void FPT_stsyncn(u32 port, unsigned char p_card)
{
unsigned char sync_msg, offset, sync_reg, our_sync_msg;
struct sccb *currSCCB;
@@ -3363,7 +3340,7 @@ static void FPT_stsyncn(unsigned long port, unsigned char p_card)
* Description: Answer the targets sync message.
*
*---------------------------------------------------------------------*/
-static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
+static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
unsigned char offset)
{
ARAM_ACCESS(port);
@@ -3394,7 +3371,7 @@ static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
+static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
{
struct sccb *currSCCB;
struct sccb_mgr_tar_info *currTar_Info;
@@ -3449,7 +3426,7 @@ static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
* necessary.
*
*---------------------------------------------------------------------*/
-static void FPT_stwidn(unsigned long port, unsigned char p_card)
+static void FPT_stwidn(u32 port, unsigned char p_card)
{
unsigned char width;
struct sccb *currSCCB;
@@ -3520,7 +3497,7 @@ static void FPT_stwidn(unsigned long port, unsigned char p_card)
* Description: Answer the targets Wide nego message.
*
*---------------------------------------------------------------------*/
-static void FPT_siwidr(unsigned long port, unsigned char width)
+static void FPT_siwidr(u32 port, unsigned char width)
{
ARAM_ACCESS(port);
WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
@@ -3548,7 +3525,7 @@ static void FPT_siwidr(unsigned long port, unsigned char width)
* ID specified.
*
*---------------------------------------------------------------------*/
-static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
+static void FPT_sssyncv(u32 p_port, unsigned char p_id,
unsigned char p_sync_value,
struct sccb_mgr_tar_info *currTar_Info)
{
@@ -3620,7 +3597,7 @@ static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
* Description: Reset the desired card's SCSI bus.
*
*---------------------------------------------------------------------*/
-static void FPT_sresb(unsigned long port, unsigned char p_card)
+static void FPT_sresb(u32 port, unsigned char p_card)
{
unsigned char scsiID, i;
@@ -3713,7 +3690,7 @@ static void FPT_ssenss(struct sccb_card *pCurrCard)
currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
currSCCB->Cdb[5] = 0x00;
- currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
+ currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
currSCCB->Sccb_ATC = 0x00;
@@ -3737,7 +3714,7 @@ static void FPT_ssenss(struct sccb_card *pCurrCard)
*
*---------------------------------------------------------------------*/
-static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
+static void FPT_sxfrp(u32 p_port, unsigned char p_card)
{
unsigned char curr_phz;
@@ -3819,7 +3796,7 @@ static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_schkdd(unsigned long port, unsigned char p_card)
+static void FPT_schkdd(u32 port, unsigned char p_card)
{
unsigned short TimeOutLoop;
unsigned char sPhase;
@@ -3998,10 +3975,10 @@ static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
+static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
{
unsigned char phase_ref;
- void (*phase) (unsigned long, unsigned char);
+ void (*phase) (u32, unsigned char);
DISABLE_AUTO(p_port);
@@ -4021,7 +3998,7 @@ static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
+static void FPT_phaseDataOut(u32 port, unsigned char p_card)
{
struct sccb *currSCCB;
@@ -4062,7 +4039,7 @@ static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
+static void FPT_phaseDataIn(u32 port, unsigned char p_card)
{
struct sccb *currSCCB;
@@ -4106,10 +4083,10 @@ static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
+static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
{
struct sccb *currSCCB;
- unsigned long cdb_reg;
+ u32 cdb_reg;
unsigned char i;
currSCCB = FPT_BL_Card[p_card].currentSCCB;
@@ -4157,7 +4134,7 @@ static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
+static void FPT_phaseStatus(u32 port, unsigned char p_card)
{
/* Start-up the automation to finish off this command and let the
isr handle the interrupt for command complete when it comes in.
@@ -4178,7 +4155,7 @@ static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
+static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
{
unsigned char message, scsiID;
struct sccb *currSCCB;
@@ -4317,7 +4294,7 @@ static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
+static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
{
unsigned char message;
struct sccb *currSCCB;
@@ -4364,7 +4341,7 @@ static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
+static void FPT_phaseIllegal(u32 port, unsigned char p_card)
{
struct sccb *currSCCB;
@@ -4390,9 +4367,9 @@ static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
+static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
{
- unsigned long xfercnt;
+ u32 xfercnt;
struct sccb *currSCCB;
currSCCB = FPT_BL_Card[p_card].currentSCCB;
@@ -4461,7 +4438,7 @@ static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
* because of command complete or from a disconnect.
*
*---------------------------------------------------------------------*/
-static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
+static void FPT_phaseBusFree(u32 port, unsigned char p_card)
{
struct sccb *currSCCB;
@@ -4557,9 +4534,9 @@ static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
* Description: Load the Automation RAM with the defualt map values.
*
*---------------------------------------------------------------------*/
-static void FPT_autoLoadDefaultMap(unsigned long p_port)
+static void FPT_autoLoadDefaultMap(u32 p_port)
{
- unsigned long map_addr;
+ u32 map_addr;
ARAM_ACCESS(p_port);
map_addr = p_port + hp_aramBase;
@@ -4663,7 +4640,7 @@ static void FPT_autoLoadDefaultMap(unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
+static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
{
struct sccb *currSCCB;
unsigned char status_byte;
@@ -4936,8 +4913,7 @@ static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
*
*---------------------------------------------------------------------*/
-static void FPT_dataXferProcessor(unsigned long port,
- struct sccb_card *pCurrCard)
+static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
{
struct sccb *currSCCB;
@@ -4970,22 +4946,18 @@ static void FPT_dataXferProcessor(unsigned long port,
* Description:
*
*---------------------------------------------------------------------*/
-static void FPT_busMstrSGDataXferStart(unsigned long p_port,
- struct sccb *pcurrSCCB)
+static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
{
- unsigned long count, addr, tmpSGCnt;
+ u32 count, addr, tmpSGCnt;
unsigned int sg_index;
unsigned char sg_count, i;
- unsigned long reg_offset;
-
- if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
+ u32 reg_offset;
+ struct blogic_sg_seg *segp;
- count = ((unsigned long)HOST_RD_CMD) << 24;
- }
-
- else {
- count = ((unsigned long)HOST_WRT_CMD) << 24;
- }
+ if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
+ count = ((u32)HOST_RD_CMD) << 24;
+ else
+ count = ((u32)HOST_WRT_CMD) << 24;
sg_count = 0;
tmpSGCnt = 0;
@@ -4998,25 +4970,20 @@ static void FPT_busMstrSGDataXferStart(unsigned long p_port,
WR_HARPOON(p_port + hp_page_ctrl, i);
while ((sg_count < (unsigned char)SG_BUF_CNT) &&
- ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
- pcurrSCCB->DataLength)) {
-
- tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
- (sg_index * 2));
-
- count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
- (sg_index * 2));
+ ((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
+ pcurrSCCB->DataLength)) {
- addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
- ((sg_index * 2) + 1));
+ segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
+ sg_index;
+ tmpSGCnt += segp->segbytes;
+ count |= segp->segbytes;
+ addr = segp->segdata;
if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
-
addr +=
((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
count =
(count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
-
tmpSGCnt = count & 0x00FFFFFFL;
}
@@ -5072,17 +5039,15 @@ static void FPT_busMstrSGDataXferStart(unsigned long p_port,
* Description:
*
*---------------------------------------------------------------------*/
-static void FPT_busMstrDataXferStart(unsigned long p_port,
- struct sccb *pcurrSCCB)
+static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
{
- unsigned long addr, count;
+ u32 addr, count;
if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
count = pcurrSCCB->Sccb_XferCnt;
- addr =
- (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
+ addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
}
else {
@@ -5127,7 +5092,7 @@ static void FPT_busMstrDataXferStart(unsigned long p_port,
* command busy is also time out, it'll just give up.
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
+static unsigned char FPT_busMstrTimeOut(u32 p_port)
{
unsigned long timeout;
@@ -5166,13 +5131,14 @@ static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
* Description: Abort any in progress transfer.
*
*---------------------------------------------------------------------*/
-static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
+static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
struct sccb *pCurrSCCB)
{
unsigned long timeout;
unsigned long remain_cnt;
- unsigned int sg_ptr;
+ u32 sg_ptr;
+ struct blogic_sg_seg *segp;
FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
@@ -5236,9 +5202,8 @@ static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
(unsigned int)(pCurrSCCB->DataLength /
SG_ELEMENT_SIZE)) {
- sg_ptr =
- (unsigned int)(pCurrSCCB->DataLength /
- SG_ELEMENT_SIZE);
+ sg_ptr = (u32)(pCurrSCCB->DataLength /
+ SG_ELEMENT_SIZE);
}
remain_cnt = pCurrSCCB->Sccb_XferCnt;
@@ -5246,23 +5211,13 @@ static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
while (remain_cnt < 0x01000000L) {
sg_ptr--;
-
- if (remain_cnt >
- (unsigned
- long)(*(((unsigned long *)pCurrSCCB->
- DataPointer) + (sg_ptr * 2)))) {
-
+ segp = (struct blogic_sg_seg *)(pCurrSCCB->
+ DataPointer) + (sg_ptr * 2);
+ if (remain_cnt > (unsigned long)segp->segbytes)
remain_cnt -=
- (unsigned
- long)(*(((unsigned long *)
- pCurrSCCB->DataPointer) +
- (sg_ptr * 2)));
- }
-
- else {
-
+ (unsigned long)segp->segbytes;
+ else
break;
- }
}
if (remain_cnt < 0x01000000L) {
@@ -5418,23 +5373,18 @@ static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
pCurrSCCB->Sccb_SGoffset = 0x00;
- if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
- SG_ELEMENT_SIZE) >=
- pCurrSCCB->DataLength) {
+ if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
+ pCurrSCCB->DataLength) {
pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
-
pCurrSCCB->Sccb_sgseg =
(unsigned short)(pCurrSCCB->DataLength /
SG_ELEMENT_SIZE);
-
}
}
else {
-
if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
-
pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
}
}
@@ -5454,21 +5404,22 @@ static void FPT_hostDataXferRestart(struct sccb *currSCCB)
{
unsigned long data_count;
unsigned int sg_index;
- unsigned long *sg_ptr;
+ struct blogic_sg_seg *segp;
if (currSCCB->Sccb_XferState & F_SG_XFER) {
currSCCB->Sccb_XferCnt = 0;
sg_index = 0xffff; /*Index by long words into sg list. */
- data_count = 0; /*Running count of SG xfer counts. */
+ data_count = 0; /*Running count of SG xfer counts. */
- sg_ptr = (unsigned long *)currSCCB->DataPointer;
while (data_count < currSCCB->Sccb_ATC) {
sg_index++;
- data_count += *(sg_ptr + (sg_index * 2));
+ segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
+ (sg_index * 2);
+ data_count += segp->segbytes;
}
if (data_count == currSCCB->Sccb_ATC) {
@@ -5504,7 +5455,7 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
{
unsigned char loser, assigned_id;
- unsigned long p_port;
+ u32 p_port;
unsigned char i, k, ScamFlg;
struct sccb_card *currCard;
@@ -5709,7 +5660,7 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
*
*---------------------------------------------------------------------*/
-static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
+static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
{
if (p_sel_type == INIT_SELTD) {
@@ -5771,7 +5722,7 @@ static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
*
*---------------------------------------------------------------------*/
-static void FPT_scbusf(unsigned long p_port)
+static void FPT_scbusf(u32 p_port)
{
WR_HARPOON(p_port + hp_page_ctrl,
(RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
@@ -5803,7 +5754,7 @@ static void FPT_scbusf(unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_scasid(unsigned char p_card, unsigned long p_port)
+static void FPT_scasid(unsigned char p_card, u32 p_port)
{
unsigned char temp_id_string[ID_STRING_LENGTH];
@@ -5880,7 +5831,7 @@ static void FPT_scasid(unsigned char p_card, unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_scsel(unsigned long p_port)
+static void FPT_scsel(u32 p_port)
{
WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
@@ -5914,7 +5865,7 @@ static void FPT_scsel(unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
+static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
{
unsigned char curr_data, ret_data;
@@ -5964,8 +5915,7 @@ static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_scsendi(unsigned long p_port,
- unsigned char p_id_string[])
+static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
{
unsigned char ret_data, byte_cnt, bit_cnt, defer;
@@ -6016,8 +5966,7 @@ static unsigned char FPT_scsendi(unsigned long p_port,
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_sciso(unsigned long p_port,
- unsigned char p_id_string[])
+static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
{
unsigned char ret_data, the_data, byte_cnt, bit_cnt;
@@ -6075,7 +6024,7 @@ static unsigned char FPT_sciso(unsigned long p_port,
*
*---------------------------------------------------------------------*/
-static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
+static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
{
unsigned char i;
@@ -6102,7 +6051,7 @@ static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
*
*---------------------------------------------------------------------*/
-static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
+static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
{
unsigned char i;
@@ -6154,7 +6103,7 @@ static unsigned char FPT_scvalq(unsigned char p_quintet)
*
*---------------------------------------------------------------------*/
-static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
+static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
{
unsigned long i;
@@ -6236,7 +6185,7 @@ static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
*
*---------------------------------------------------------------------*/
-static void FPT_scwtsel(unsigned long p_port)
+static void FPT_scwtsel(u32 p_port)
{
while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
}
@@ -6250,8 +6199,7 @@ static void FPT_scwtsel(unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_inisci(unsigned char p_card, unsigned long p_port,
- unsigned char p_our_id)
+static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
{
unsigned char i, k, max_id;
unsigned short ee_data;
@@ -6437,7 +6385,7 @@ static unsigned char FPT_scmachid(unsigned char p_card,
*
*---------------------------------------------------------------------*/
-static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
+static void FPT_scsavdi(unsigned char p_card, u32 p_port)
{
unsigned char i, k, max_id;
unsigned short ee_data, sum_data;
@@ -6482,7 +6430,7 @@ static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
+static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
{
unsigned char i;
@@ -6531,7 +6479,7 @@ static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
*
*---------------------------------------------------------------------*/
-static void FPT_BusMasterInit(unsigned long p_port)
+static void FPT_BusMasterInit(u32 p_port)
{
WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
@@ -6558,7 +6506,7 @@ static void FPT_BusMasterInit(unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_DiagEEPROM(unsigned long p_port)
+static void FPT_DiagEEPROM(u32 p_port)
{
unsigned short index, temp, max_wd_cnt;
@@ -7206,7 +7154,7 @@ static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
{
unsigned long partial_cnt;
unsigned int sg_index;
- unsigned long *sg_ptr;
+ struct blogic_sg_seg *segp;
if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
@@ -7219,7 +7167,6 @@ static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
sg_index = p_SCCB->Sccb_sgseg;
- sg_ptr = (unsigned long *)p_SCCB->DataPointer;
if (p_SCCB->Sccb_SGoffset) {
@@ -7229,8 +7176,9 @@ static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
while (((unsigned long)sg_index *
(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
-
- partial_cnt += *(sg_ptr + (sg_index * 2));
+ segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
+ (sg_index * 2);
+ partial_cnt += segp->segbytes;
sg_index++;
}
@@ -7251,7 +7199,7 @@ static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
*
*---------------------------------------------------------------------*/
-static void FPT_Wait1Second(unsigned long p_port)
+static void FPT_Wait1Second(u32 p_port)
{
unsigned char i;
@@ -7275,7 +7223,7 @@ static void FPT_Wait1Second(unsigned long p_port)
*
*---------------------------------------------------------------------*/
-static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
+static void FPT_Wait(u32 p_port, unsigned char p_delay)
{
unsigned char old_timer;
unsigned char green_flag;
@@ -7321,7 +7269,7 @@ static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
*
*---------------------------------------------------------------------*/
-static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
+static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
{
unsigned char ee_value;
@@ -7350,7 +7298,7 @@ static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
*
*---------------------------------------------------------------------*/
-static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
+static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
unsigned short ee_addr)
{
@@ -7401,7 +7349,7 @@ static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
*
*---------------------------------------------------------------------*/
-static unsigned short FPT_utilEERead(unsigned long p_port,
+static unsigned short FPT_utilEERead(u32 p_port,
unsigned short ee_addr)
{
unsigned short i, ee_data1, ee_data2;
@@ -7431,8 +7379,7 @@ static unsigned short FPT_utilEERead(unsigned long p_port,
*
*---------------------------------------------------------------------*/
-static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
- unsigned short ee_addr)
+static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
{
unsigned char ee_value;
@@ -7479,7 +7426,7 @@ static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
*
*---------------------------------------------------------------------*/
-static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
+static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
unsigned short ee_addr)
{
unsigned char ee_value;
@@ -7573,47 +7520,45 @@ static unsigned char FPT_CalcLrc(unsigned char buffer[])
*/
static inline unsigned char
-FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
+FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
{
return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
FlashPointInfo);
}
-static inline FlashPoint_CardHandle_T
-FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
+static inline void *
+FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
{
return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
FlashPointInfo);
}
static inline void
-FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
+FlashPoint__ReleaseHostAdapter(void *CardHandle)
{
FlashPoint_ReleaseHostAdapter(CardHandle);
}
static inline void
-FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
- struct BusLogic_CCB *CCB)
+FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
{
FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
}
static inline void
-FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
- struct BusLogic_CCB *CCB)
+FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
{
FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
}
static inline bool
-FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
+FlashPoint__InterruptPending(void *CardHandle)
{
return FlashPoint_InterruptPending(CardHandle);
}
static inline int
-FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
+FlashPoint__HandleInterrupt(void *CardHandle)
{
return FlashPoint_HandleInterrupt(CardHandle);
}
@@ -7632,13 +7577,12 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
Define prototypes for the FlashPoint SCCB Manager Functions.
*/
-extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
-extern FlashPoint_CardHandle_T
-FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
-extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
-extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
-extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
-extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
-extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
+extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
+extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
+extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
+extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
+extern bool FlashPoint_InterruptPending(void *);
+extern int FlashPoint_HandleInterrupt(void *);
+extern void FlashPoint_ReleaseHostAdapter(void *);
#endif /* CONFIG_SCSI_FLASHPOINT */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 142f632..48b2918 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -42,7 +42,7 @@ config SCSI_DMA
config SCSI_TGT
tristate "SCSI target support"
- depends on SCSI && EXPERIMENTAL
+ depends on SCSI
---help---
If you want to use SCSI target mode drivers enable this option.
If you choose M, the module will be called scsi_tgt.
@@ -633,7 +633,7 @@ config SCSI_BUSLOGIC
config SCSI_FLASHPOINT
bool "FlashPoint support"
- depends on SCSI_BUSLOGIC && PCI && X86_32
+ depends on SCSI_BUSLOGIC && PCI
help
This option allows you to add FlashPoint support to the
BusLogic SCSI driver. The FlashPoint SCCB Manager code is
@@ -883,7 +883,7 @@ config SCSI_IBMVSCSI
This is the IBM POWER Virtual SCSI Client
To compile this driver as a module, choose M here: the
- module will be called ibmvscsic.
+ module will be called ibmvscsi.
config SCSI_IBMVSCSIS
tristate "IBM Virtual SCSI Server support"
@@ -1353,6 +1353,8 @@ config SCSI_LPFC
tristate "Emulex LightPulse Fibre Channel Support"
depends on PCI && SCSI
select SCSI_FC_ATTRS
+ select GENERIC_CSUM
+ select CRC_T10DIF
help
This lpfc driver supports the Emulex LightPulse
Family of Fibre Channel PCI host adapters.
@@ -1392,8 +1394,8 @@ config SCSI_SYM53C416
module will be called sym53c416.
config SCSI_DC395x
- tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support (EXPERIMENTAL)"
- depends on PCI && SCSI && EXPERIMENTAL
+ tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support"
+ depends on PCI && SCSI
---help---
This driver supports PCI SCSI host adapters based on the ASIC
TRM-S1040 chip, e.g Tekram DC395(U/UW/F) and DC315(U) variants.
@@ -1618,8 +1620,8 @@ config GVP11_SCSI
module will be called gvp11.
config SCSI_A4000T
- tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
- depends on AMIGA && SCSI && EXPERIMENTAL
+ tristate "A4000T NCR53c710 SCSI support"
+ depends on AMIGA && SCSI
select SCSI_SPI_ATTRS
help
If you have an Amiga 4000T and have SCSI devices connected to the
@@ -1629,8 +1631,8 @@ config SCSI_A4000T
module will be called a4000t.
config SCSI_ZORRO7XX
- tristate "Zorro NCR53c710 SCSI support (EXPERIMENTAL)"
- depends on ZORRO && SCSI && EXPERIMENTAL
+ tristate "Zorro NCR53c710 SCSI support"
+ depends on ZORRO && SCSI
select SCSI_SPI_ATTRS
help
Support for various NCR53c710-based SCSI controllers on Zorro
@@ -1807,8 +1809,8 @@ config SCSI_BFA_FC
be called bfa.
config SCSI_VIRTIO
- tristate "virtio-scsi support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && VIRTIO
+ tristate "virtio-scsi support"
+ depends on VIRTIO
help
This is the virtual HBA driver for virtio. If the kernel will
be used in a virtual machine, say Y or M.
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 165e4dd86..1e9d6ad 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -695,33 +695,35 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
* Return the number of bytes read from or written
*/
+static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
+ char *buffer, int length)
+{
+#ifdef DTC_PUBLIC_RELEASE
+ dtc_wmaxi = dtc_maxi = 0;
+#endif
+#ifdef PAS16_PUBLIC_RELEASE
+ pas_wmaxi = pas_maxi = 0;
+#endif
+ return (-ENOSYS); /* Currently this is a no-op */
+}
+
#undef SPRINTF
-#define SPRINTF(args...) do { if(pos < buffer + length-80) pos += sprintf(pos, ## args); } while(0)
+#define SPRINTF(args...) seq_printf(m, ## args)
static
-char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length);
+void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m);
static
-char *lprint_command(unsigned char *cmd, char *pos, char *buffer, int len);
+void lprint_command(unsigned char *cmd, struct seq_file *m);
static
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
+void lprint_opcode(int opcode, struct seq_file *m);
-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
- char *buffer, char **start, off_t offset, int length, int inout)
+static int __maybe_unused NCR5380_show_info(struct seq_file *m,
+ struct Scsi_Host *instance)
{
- char *pos = buffer;
struct NCR5380_hostdata *hostdata;
Scsi_Cmnd *ptr;
hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- if (inout) { /* Has data been written to the file ? */
-#ifdef DTC_PUBLIC_RELEASE
- dtc_wmaxi = dtc_maxi = 0;
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
- pas_wmaxi = pas_maxi = 0;
-#endif
- return (-ENOSYS); /* Currently this is a no-op */
- }
SPRINTF("NCR5380 core release=%d. ", NCR5380_PUBLIC_RELEASE);
if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)
SPRINTF("ncr53c400 release=%d. ", NCR53C400_PUBLIC_RELEASE);
@@ -755,46 +757,37 @@ static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
else
- pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, pos, buffer, length);
+ lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
SPRINTF("scsi%d: issue_queue\n", instance->host_no);
for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
- pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+ lprint_Scsi_Cmnd(ptr, m);
SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
- pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+ lprint_Scsi_Cmnd(ptr, m);
spin_unlock_irq(instance->host_lock);
-
- *start = buffer;
- if (pos - buffer < offset)
- return 0;
- else if (pos - buffer - offset < length)
- return pos - buffer - offset;
- return length;
+ return 0;
}
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
+static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
{
SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
SPRINTF(" command = ");
- pos = lprint_command(cmd->cmnd, pos, buffer, length);
- return (pos);
+ lprint_command(cmd->cmnd, m);
}
-static char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
+static void lprint_command(unsigned char *command, struct seq_file *m)
{
int i, s;
- pos = lprint_opcode(command[0], pos, buffer, length);
+ lprint_opcode(command[0], m);
for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
SPRINTF("%02x ", command[i]);
SPRINTF("\n");
- return (pos);
}
-static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
+static void lprint_opcode(int opcode, struct seq_file *m)
{
SPRINTF("%2d (0x%02x)", opcode, opcode);
- return (pos);
}
@@ -814,7 +807,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
* Locks: interrupts must be enabled when we are called
*/
-static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
+static int NCR5380_init(struct Scsi_Host *instance, int flags)
{
NCR5380_local_declare();
int i, pass;
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index fd40a32..14964d0 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -314,8 +314,10 @@ static void NCR5380_print(struct Scsi_Host *instance);
static int NCR5380_abort(Scsi_Cmnd * cmd);
static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
static int NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
- char *buffer, char **start, off_t offset, int length, int inout);
+static int __maybe_unused NCR5380_show_info(struct seq_file *,
+ struct Scsi_Host *);
+static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
+ char *buffer, int length);
static void NCR5380_reselect(struct Scsi_Host *instance);
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 8647256..b39a240 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -114,7 +114,7 @@ MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
MODULE_LICENSE("GPL");
module_param(NCR_D700, charp, 0);
-static __u8 __devinitdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
+static __u8 id_array[2*(MCA_MAX_SLOT_NR + 1)] =
{ [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 };
#ifdef MODULE
@@ -173,7 +173,7 @@ struct NCR_D700_private {
char pad;
};
-static int __devinit
+static int
NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
int slot, u32 region, int differential)
{
@@ -243,7 +243,7 @@ NCR_D700_intr(int irq, void *data)
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
* adapter with two channels */
-static int __devinit
+static int
NCR_D700_probe(struct device *dev)
{
struct NCR_D700_private *p;
@@ -349,7 +349,7 @@ NCR_D700_probe(struct device *dev)
return 0;
}
-static void __devexit
+static void
NCR_D700_remove_one(struct Scsi_Host *host)
{
scsi_remove_host(host);
@@ -359,7 +359,7 @@ NCR_D700_remove_one(struct Scsi_Host *host)
release_region(host->base, 64);
}
-static int __devexit
+static int
NCR_D700_remove(struct device *dev)
{
struct NCR_D700_private *p = dev_get_drvdata(dev);
@@ -380,7 +380,7 @@ static struct mca_driver NCR_D700_driver = {
.name = "NCR_D700",
.bus = &mca_bus_type,
.probe = NCR_D700_probe,
- .remove = __devexit_p(NCR_D700_remove),
+ .remove = NCR_D700_remove,
},
};
diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
index afdbb9a..05835bf 100644
--- a/drivers/scsi/NCR_Q720.c
+++ b/drivers/scsi/NCR_Q720.c
@@ -351,7 +351,7 @@ static struct mca_driver NCR_Q720_driver = {
.name = "NCR_Q720",
.bus = &mca_bus_type,
.probe = NCR_Q720_probe,
- .remove = __devexit_p(NCR_Q720_remove),
+ .remove = NCR_Q720_remove,
},
};
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index a391090..0163457 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1082,8 +1082,8 @@ static struct scsi_host_template inia100_template = {
.use_clustering = ENABLE_CLUSTERING,
};
-static int __devinit inia100_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int inia100_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct Scsi_Host *shost;
struct orc_host *host;
@@ -1197,7 +1197,7 @@ out:
return error;
}
-static void __devexit inia100_remove_one(struct pci_dev *pdev)
+static void inia100_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct orc_host *host = (struct orc_host *)shost->hostdata;
@@ -1224,7 +1224,7 @@ static struct pci_driver inia100_pci_driver = {
.name = "inia100",
.id_table = inia100_pci_tbl,
.probe = inia100_probe_one,
- .remove = __devexit_p(inia100_remove_one),
+ .remove = inia100_remove_one,
};
static int __init inia100_init(void)
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 79a3063..30fa38a 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -166,7 +166,8 @@ static int a2091_bus_reset(struct scsi_cmnd *cmd)
static struct scsi_host_template a2091_scsi_template = {
.module = THIS_MODULE,
.name = "Commodore A2091/A590 SCSI",
- .proc_info = wd33c93_proc_info,
+ .show_info = wd33c93_show_info,
+ .write_info = wd33c93_write_info,
.proc_name = "A2901",
.queuecommand = wd33c93_queuecommand,
.eh_abort_handler = wd33c93_abort,
@@ -179,8 +180,7 @@ static struct scsi_host_template a2091_scsi_template = {
.use_clustering = DISABLE_CLUSTERING
};
-static int __devinit a2091_probe(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
{
struct Scsi_Host *instance;
int error;
@@ -239,7 +239,7 @@ fail_alloc:
return error;
}
-static void __devexit a2091_remove(struct zorro_dev *z)
+static void a2091_remove(struct zorro_dev *z)
{
struct Scsi_Host *instance = zorro_get_drvdata(z);
struct a2091_hostdata *hdata = shost_priv(instance);
@@ -251,7 +251,7 @@ static void __devexit a2091_remove(struct zorro_dev *z)
release_mem_region(z->resource.start, 256);
}
-static struct zorro_device_id a2091_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id a2091_zorro_tbl[] = {
{ ZORRO_PROD_CBM_A590_A2091_1 },
{ ZORRO_PROD_CBM_A590_A2091_2 },
{ 0 }
@@ -262,7 +262,7 @@ static struct zorro_driver a2091_driver = {
.name = "a2091",
.id_table = a2091_zorro_tbl,
.probe = a2091_probe,
- .remove = __devexit_p(a2091_remove),
+ .remove = a2091_remove,
};
static int __init a2091_init(void)
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index e29fe0e..c0f4f42 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -181,7 +181,8 @@ static int a3000_bus_reset(struct scsi_cmnd *cmd)
static struct scsi_host_template amiga_a3000_scsi_template = {
.module = THIS_MODULE,
.name = "Amiga 3000 built-in SCSI",
- .proc_info = wd33c93_proc_info,
+ .show_info = wd33c93_show_info,
+ .write_info = wd33c93_write_info,
.proc_name = "A3000",
.queuecommand = wd33c93_queuecommand,
.eh_abort_handler = wd33c93_abort,
@@ -279,18 +280,7 @@ static struct platform_driver amiga_a3000_scsi_driver = {
},
};
-static int __init amiga_a3000_scsi_init(void)
-{
- return platform_driver_probe(&amiga_a3000_scsi_driver,
- amiga_a3000_scsi_probe);
-}
-module_init(amiga_a3000_scsi_init);
-
-static void __exit amiga_a3000_scsi_exit(void)
-{
- platform_driver_unregister(&amiga_a3000_scsi_driver);
-}
-module_exit(amiga_a3000_scsi_exit);
+module_platform_driver_probe(amiga_a3000_scsi_driver, amiga_a3000_scsi_probe);
MODULE_DESCRIPTION("Amiga 3000 built-in SCSI");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index 23c76f4..70c521f 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -116,20 +116,7 @@ static struct platform_driver amiga_a4000t_scsi_driver = {
},
};
-static int __init amiga_a4000t_scsi_init(void)
-{
- return platform_driver_probe(&amiga_a4000t_scsi_driver,
- amiga_a4000t_scsi_probe);
-}
-
-module_init(amiga_a4000t_scsi_init);
-
-static void __exit amiga_a4000t_scsi_exit(void)
-{
- platform_driver_unregister(&amiga_a4000t_scsi_driver);
-}
-
-module_exit(amiga_a4000t_scsi_exit);
+module_platform_driver_probe(amiga_a4000t_scsi_driver, amiga_a4000t_scsi_probe);
MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / "
"Kars de Jong <jongk@linux-m68k.org>");
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 742f5d7..9323d05 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,13 +12,13 @@
*----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 29801
+# define AAC_DRIVER_BUILD 30200
# define AAC_DRIVER_BRANCH "-ms"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
#define AAC_NUM_MGT_FIB 8
-#define AAC_NUM_IO_FIB (512 - AAC_NUM_MGT_FIB)
+#define AAC_NUM_IO_FIB (1024 - AAC_NUM_MGT_FIB)
#define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)
#define AAC_MAX_LUN (8)
@@ -36,6 +36,10 @@
#define CONTAINER_TO_ID(cont) (cont)
#define CONTAINER_TO_LUN(cont) (0)
+#define PMC_DEVICE_S7 0x28c
+#define PMC_DEVICE_S8 0x28d
+#define PMC_DEVICE_S9 0x28f
+
#define aac_phys_to_logical(x) ((x)+1)
#define aac_logical_to_phys(x) ((x)?(x)-1:0)
@@ -1914,6 +1918,10 @@ extern struct aac_common aac_config;
#define MONITOR_PANIC 0x00000020
#define KERNEL_UP_AND_RUNNING 0x00000080
#define KERNEL_PANIC 0x00000100
+#define FLASH_UPD_PENDING 0x00002000
+#define FLASH_UPD_SUCCESS 0x00004000
+#define FLASH_UPD_FAILED 0x00008000
+#define FWUPD_TIMEOUT (5 * 60)
/*
* Doorbell bit defines
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 1ef041b..d85ac1a 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -318,7 +318,8 @@ return_fib:
kthread_stop(dev->thread);
ssleep(1);
dev->aif_thread = 0;
- dev->thread = kthread_run(aac_command_thread, dev, dev->name);
+ dev->thread = kthread_run(aac_command_thread, dev,
+ "%s", dev->name);
ssleep(1);
}
if (f.wait) {
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 8e5d3be..177b094 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -214,7 +214,7 @@ int aac_send_shutdown(struct aac_dev * dev)
cmd = (struct aac_close *) fib_data(fibctx);
cmd->command = cpu_to_le32(VM_CloseAll);
- cmd->cid = cpu_to_le32(0xffffffff);
+ cmd->cid = cpu_to_le32(0xfffffffe);
status = aac_fib_send(ContainerCommand,
fibctx,
@@ -404,7 +404,13 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->max_fib_size = status[1] & 0xFFE0;
host->sg_tablesize = status[2] >> 16;
dev->sg_tablesize = status[2] & 0xFFFF;
- host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
+ if (dev->pdev->device == PMC_DEVICE_S7 ||
+ dev->pdev->device == PMC_DEVICE_S8 ||
+ dev->pdev->device == PMC_DEVICE_S9)
+ host->can_queue = ((status[3] >> 16) ? (status[3] >> 16) :
+ (status[3] & 0xFFFF)) - AAC_NUM_MGT_FIB;
+ else
+ host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
dev->max_num_aif = status[4] & 0xFFFF;
/*
* NOTE:
@@ -452,6 +458,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
}
}
+ if (host->can_queue > AAC_NUM_IO_FIB)
+ host->can_queue = AAC_NUM_IO_FIB;
+
/*
* Ok now init the communication subsystem
*/
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 1be0776..cab190a 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1336,7 +1336,8 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
if ((retval = pci_set_dma_mask(aac->pdev, DMA_BIT_MASK(32))))
goto out;
if (jafo) {
- aac->thread = kthread_run(aac_command_thread, aac, aac->name);
+ aac->thread = kthread_run(aac_command_thread, aac, "%s",
+ aac->name);
if (IS_ERR(aac->thread)) {
retval = PTR_ERR(aac->thread);
goto out;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index cb7f158..408a42e 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -88,13 +88,7 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
*
* Note: The last field is used to index into aac_drivers below.
*/
-#ifdef DECLARE_PCI_DEVICE_TABLE
-static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = {
-#elif defined(__devinitconst)
-static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
-#else
-static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
-#endif
+static const struct pci_device_id aac_pci_tbl[] = {
{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */
@@ -1107,8 +1101,7 @@ static void __aac_shutdown(struct aac_dev * aac)
pci_disable_msi(aac->pdev);
}
-static int __devinit aac_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
unsigned index = id->driver_data;
struct Scsi_Host *shost;
@@ -1310,7 +1303,7 @@ static void aac_shutdown(struct pci_dev *dev)
__aac_shutdown((struct aac_dev *)shost->hostdata);
}
-static void __devexit aac_remove_one(struct pci_dev *pdev)
+static void aac_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
@@ -1341,7 +1334,7 @@ static struct pci_driver aac_pci_driver = {
.name = AAC_DRIVERNAME,
.id_table = aac_pci_tbl,
.probe = aac_probe_one,
- .remove = __devexit_p(aac_remove_one),
+ .remove = aac_remove_one,
.shutdown = aac_shutdown,
};
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index 3b021ec..7e17107 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -93,6 +93,9 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
int send_it = 0;
extern int aac_sync_mode;
+ src_writel(dev, MUnit.ODR_C, bellbits);
+ src_readl(dev, MUnit.ODR_C);
+
if (!aac_sync_mode) {
src_writel(dev, MUnit.ODR_C, bellbits);
src_readl(dev, MUnit.ODR_C);
@@ -407,7 +410,7 @@ static int aac_src_deliver_message(struct fib *fib)
fib->hw_fib_va->header.StructType = FIB_MAGIC2;
fib->hw_fib_va->header.SenderFibAddress = (u32)address;
fib->hw_fib_va->header.u.TimeStamp = 0;
- BUG_ON((u32)(address >> 32) != 0L);
+ BUG_ON(upper_32_bits(address) != 0L);
address |= fibsize;
} else {
/* Calculate the amount to the fibsize bits */
@@ -431,7 +434,7 @@ static int aac_src_deliver_message(struct fib *fib)
address |= fibsize;
}
- src_writel(dev, MUnit.IQ_H, (address >> 32) & 0xffffffff);
+ src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff);
src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
return 0;
@@ -703,6 +706,28 @@ int aac_srcv_init(struct aac_dev *dev)
!aac_src_restart_adapter(dev, 0))
++restart;
/*
+ * Check to see if flash update is running.
+ * Wait for the adapter to be up and running. Wait up to 5 minutes
+ */
+ status = src_readl(dev, MUnit.OMR);
+ if (status & FLASH_UPD_PENDING) {
+ start = jiffies;
+ do {
+ status = src_readl(dev, MUnit.OMR);
+ if (time_after(jiffies, start+HZ*FWUPD_TIMEOUT)) {
+ printk(KERN_ERR "%s%d: adapter flash update failed.\n",
+ dev->name, instance);
+ goto error_iounmap;
+ }
+ } while (!(status & FLASH_UPD_SUCCESS) &&
+ !(status & FLASH_UPD_FAILED));
+ /* Delay 10 seconds.
+ * Because right now FW is doing a soft reset,
+ * do not read scratch pad register at this time
+ */
+ ssleep(10);
+ }
+ /*
* Check to see if the board panic'd while booting.
*/
status = src_readl(dev, MUnit.OMR);
@@ -730,7 +755,9 @@ int aac_srcv_init(struct aac_dev *dev)
/*
* Wait for the adapter to be up and running. Wait up to 3 minutes
*/
- while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)) {
+ while (!((status = src_readl(dev, MUnit.OMR)) &
+ KERNEL_UP_AND_RUNNING) ||
+ status == 0xffffffff) {
if ((restart &&
(status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
time_after(jiffies, start+HZ*startup_timeout)) {
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 374c4ed..c67e401 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2178,22 +2178,6 @@ do { \
#define ASC_INFO_SIZE 128 /* advansys_info() line size */
-#ifdef CONFIG_PROC_FS
-/* /proc/scsi/advansys/[0...] related definitions */
-#define ASC_PRTBUF_SIZE 2048
-#define ASC_PRTLINE_SIZE 160
-
-#define ASC_PRT_NEXT() \
- if (cp) { \
- totlen += len; \
- leftlen -= len; \
- if (leftlen == 0) { \
- return totlen; \
- } \
- cp += len; \
- }
-#endif /* CONFIG_PROC_FS */
-
/* Asc Library return codes */
#define ASC_TRUE 1
#define ASC_FALSE 0
@@ -2384,7 +2368,6 @@ struct asc_board {
} eep_config;
ulong last_reset; /* Saved last reset time */
/* /proc/scsi/advansys/[0...] */
- char *prtbuf; /* /proc print buffer */
#ifdef ADVANSYS_STATS
struct asc_stats asc_stats; /* Board statistics */
#endif /* ADVANSYS_STATS */
@@ -2875,64 +2858,21 @@ static const char *advansys_info(struct Scsi_Host *shost)
}
#ifdef CONFIG_PROC_FS
-/*
- * asc_prt_line()
- *
- * If 'cp' is NULL print to the console, otherwise print to a buffer.
- *
- * Return 0 if printing to the console, otherwise return the number of
- * bytes written to the buffer.
- *
- * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
- * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
- */
-static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
-{
- va_list args;
- int ret;
- char s[ASC_PRTLINE_SIZE];
-
- va_start(args, fmt);
- ret = vsprintf(s, fmt, args);
- BUG_ON(ret >= ASC_PRTLINE_SIZE);
- if (buf == NULL) {
- (void)printk(s);
- ret = 0;
- } else {
- ret = min(buflen, ret);
- memcpy(buf, s, ret);
- }
- va_end(args);
- return ret;
-}
/*
* asc_prt_board_devices()
*
* Print driver information for devices attached to the board.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_board_devices(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
- int leftlen;
- int totlen;
- int len;
int chip_scsi_id;
int i;
- leftlen = cplen;
- totlen = len = 0;
-
- len = asc_prt_line(cp, leftlen,
- "\nDevice Information for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ "\nDevice Information for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
if (ASC_NARROW_BOARD(boardp)) {
chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
@@ -2940,60 +2880,42 @@ static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
}
- len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
- ASC_PRT_NEXT();
+ seq_printf(m, "Target IDs Detected:");
for (i = 0; i <= ADV_MAX_TID; i++) {
- if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
- len = asc_prt_line(cp, leftlen, " %X,", i);
- ASC_PRT_NEXT();
- }
+ if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i))
+ seq_printf(m, " %X,", i);
}
- len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
- ASC_PRT_NEXT();
-
- return totlen;
+ seq_printf(m, " (%X=Host Adapter)\n", chip_scsi_id);
}
/*
* Display Wide Board BIOS Information.
*/
-static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_bios(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
- int leftlen;
- int totlen;
- int len;
ushort major, minor, letter;
- leftlen = cplen;
- totlen = len = 0;
-
- len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
- ASC_PRT_NEXT();
+ seq_printf(m, "\nROM BIOS Version: ");
/*
* If the BIOS saved a valid signature, then fill in
* the BIOS code segment base address.
*/
if (boardp->bios_signature != 0x55AA) {
- len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
- ASC_PRT_NEXT();
- len = asc_prt_line(cp, leftlen,
- "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
- ASC_PRT_NEXT();
- len = asc_prt_line(cp, leftlen,
- "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "Disabled or Pre-3.1\n");
+ seq_printf(m,
+ "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
+ seq_printf(m,
+ "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
} else {
major = (boardp->bios_version >> 12) & 0xF;
minor = (boardp->bios_version >> 8) & 0xF;
letter = (boardp->bios_version & 0xFF);
- len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
+ seq_printf(m, "%d.%d%c\n",
major, minor,
letter >= 26 ? '?' : letter + 'A');
- ASC_PRT_NEXT();
-
/*
* Current available ROM BIOS release is 3.1I for UW
* and 3.2I for U2W. This code doesn't differentiate
@@ -3001,16 +2923,12 @@ static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
*/
if (major < 3 || (major <= 3 && minor < 1) ||
(major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
- len = asc_prt_line(cp, leftlen,
- "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
- ASC_PRT_NEXT();
- len = asc_prt_line(cp, leftlen,
- "ftp://ftp.connectcom.net/pub\n");
- ASC_PRT_NEXT();
+ seq_printf(m,
+ "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
+ seq_printf(m,
+ "ftp://ftp.connectcom.net/pub\n");
}
}
-
- return totlen;
}
/*
@@ -3115,20 +3033,11 @@ static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
* asc_prt_asc_board_eeprom()
*
* Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_asc_board_eeprom(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
ASC_DVC_VAR *asc_dvc_varp;
- int leftlen;
- int totlen;
- int len;
ASCEEP_CONFIG *ep;
int i;
#ifdef CONFIG_ISA
@@ -3139,129 +3048,75 @@ static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
ep = &boardp->eep_config.asc_eep;
- leftlen = cplen;
- totlen = len = 0;
-
- len = asc_prt_line(cp, leftlen,
- "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
- == ASC_TRUE) {
- len =
- asc_prt_line(cp, leftlen, " Serial Number: %s\n",
- serialstr);
- ASC_PRT_NEXT();
- } else {
- if (ep->adapter_info[5] == 0xBB) {
- len = asc_prt_line(cp, leftlen,
- " Default Settings Used for EEPROM-less Adapter.\n");
- ASC_PRT_NEXT();
- } else {
- len = asc_prt_line(cp, leftlen,
- " Serial Number Signature Not Present.\n");
- ASC_PRT_NEXT();
- }
- }
-
- len = asc_prt_line(cp, leftlen,
- " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
- ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
- ep->max_tag_qng);
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen,
- " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " Target ID: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ASC_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %d", i);
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " Disconnects: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ASC_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (ep->
- disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " Command Queuing: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ASC_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (ep->
- use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " Start Motor: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ASC_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (ep->
- start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
- ASC_PRT_NEXT();
- for (i = 0; i <= ASC_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (ep->
- init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ == ASC_TRUE)
+ seq_printf(m, " Serial Number: %s\n", serialstr);
+ else if (ep->adapter_info[5] == 0xBB)
+ seq_printf(m,
+ " Default Settings Used for EEPROM-less Adapter.\n");
+ else
+ seq_printf(m,
+ " Serial Number Signature Not Present.\n");
+
+ seq_printf(m,
+ " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+ ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
+ ep->max_tag_qng);
+
+ seq_printf(m,
+ " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
+
+ seq_printf(m, " Target ID: ");
+ for (i = 0; i <= ASC_MAX_TID; i++)
+ seq_printf(m, " %d", i);
+ seq_printf(m, "\n");
+
+ seq_printf(m, " Disconnects: ");
+ for (i = 0; i <= ASC_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
+
+ seq_printf(m, " Command Queuing: ");
+ for (i = 0; i <= ASC_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
+
+ seq_printf(m, " Start Motor: ");
+ for (i = 0; i <= ASC_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
+
+ seq_printf(m, " Synchronous Transfer:");
+ for (i = 0; i <= ASC_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
#ifdef CONFIG_ISA
if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
- len = asc_prt_line(cp, leftlen,
- " Host ISA DMA speed: %d MB/S\n",
- isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " Host ISA DMA speed: %d MB/S\n",
+ isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
}
#endif /* CONFIG_ISA */
-
- return totlen;
}
/*
* asc_prt_adv_board_eeprom()
*
* Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_board_eeprom(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
ADV_DVC_VAR *adv_dvc_varp;
- int leftlen;
- int totlen;
- int len;
int i;
char *termstr;
uchar serialstr[13];
@@ -3281,13 +3136,9 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
}
- leftlen = cplen;
- totlen = len = 0;
-
- len = asc_prt_line(cp, leftlen,
- "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
wordp = &ep_3550->serial_number_word1;
@@ -3297,38 +3148,28 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
wordp = &ep_38C1600->serial_number_word1;
}
- if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
- len =
- asc_prt_line(cp, leftlen, " Serial Number: %s\n",
- serialstr);
- ASC_PRT_NEXT();
- } else {
- len = asc_prt_line(cp, leftlen,
- " Serial Number Signature Not Present.\n");
- ASC_PRT_NEXT();
- }
+ if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE)
+ seq_printf(m, " Serial Number: %s\n", serialstr);
+ else
+ seq_printf(m, " Serial Number Signature Not Present.\n");
- if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
- len = asc_prt_line(cp, leftlen,
- " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
- ep_3550->adapter_scsi_id,
- ep_3550->max_host_qng, ep_3550->max_dvc_qng);
- ASC_PRT_NEXT();
- } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
- len = asc_prt_line(cp, leftlen,
- " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
- ep_38C0800->adapter_scsi_id,
- ep_38C0800->max_host_qng,
- ep_38C0800->max_dvc_qng);
- ASC_PRT_NEXT();
- } else {
- len = asc_prt_line(cp, leftlen,
- " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
- ep_38C1600->adapter_scsi_id,
- ep_38C1600->max_host_qng,
- ep_38C1600->max_dvc_qng);
- ASC_PRT_NEXT();
- }
+ if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
+ seq_printf(m,
+ " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+ ep_3550->adapter_scsi_id,
+ ep_3550->max_host_qng, ep_3550->max_dvc_qng);
+ else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
+ seq_printf(m,
+ " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+ ep_38C0800->adapter_scsi_id,
+ ep_38C0800->max_host_qng,
+ ep_38C0800->max_dvc_qng);
+ else
+ seq_printf(m,
+ " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+ ep_38C1600->adapter_scsi_id,
+ ep_38C1600->max_host_qng,
+ ep_38C1600->max_dvc_qng);
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
word = ep_3550->termination;
} else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
@@ -3352,34 +3193,26 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
break;
}
- if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
- len = asc_prt_line(cp, leftlen,
- " termination: %u (%s), bios_ctrl: 0x%x\n",
- ep_3550->termination, termstr,
- ep_3550->bios_ctrl);
- ASC_PRT_NEXT();
- } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
- len = asc_prt_line(cp, leftlen,
- " termination: %u (%s), bios_ctrl: 0x%x\n",
- ep_38C0800->termination_lvd, termstr,
- ep_38C0800->bios_ctrl);
- ASC_PRT_NEXT();
- } else {
- len = asc_prt_line(cp, leftlen,
- " termination: %u (%s), bios_ctrl: 0x%x\n",
- ep_38C1600->termination_lvd, termstr,
- ep_38C1600->bios_ctrl);
- ASC_PRT_NEXT();
- }
+ if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
+ seq_printf(m,
+ " termination: %u (%s), bios_ctrl: 0x%x\n",
+ ep_3550->termination, termstr,
+ ep_3550->bios_ctrl);
+ else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
+ seq_printf(m,
+ " termination: %u (%s), bios_ctrl: 0x%x\n",
+ ep_38C0800->termination_lvd, termstr,
+ ep_38C0800->bios_ctrl);
+ else
+ seq_printf(m,
+ " termination: %u (%s), bios_ctrl: 0x%x\n",
+ ep_38C1600->termination_lvd, termstr,
+ ep_38C1600->bios_ctrl);
- len = asc_prt_line(cp, leftlen, " Target ID: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %X", i);
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Target ID: ");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %X", i);
+ seq_printf(m, "\n");
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
word = ep_3550->disc_enable;
@@ -3388,15 +3221,11 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
} else {
word = ep_38C1600->disc_enable;
}
- len = asc_prt_line(cp, leftlen, " Disconnects: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Disconnects: ");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
word = ep_3550->tagqng_able;
@@ -3405,15 +3234,11 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
} else {
word = ep_38C1600->tagqng_able;
}
- len = asc_prt_line(cp, leftlen, " Command Queuing: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Command Queuing: ");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
word = ep_3550->start_motor;
@@ -3422,42 +3247,28 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
} else {
word = ep_38C1600->start_motor;
}
- len = asc_prt_line(cp, leftlen, " Start Motor: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Start Motor: ");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
- len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (ep_3550->
- sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
- 'Y' : 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Synchronous Transfer:");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (ep_3550->sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
+ 'Y' : 'N');
+ seq_printf(m, "\n");
}
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
- len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (ep_3550->
- ultra_able & ADV_TID_TO_TIDMASK(i))
- ? 'Y' : 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Ultra Transfer: ");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (ep_3550->ultra_able & ADV_TID_TO_TIDMASK(i))
+ ? 'Y' : 'N');
+ seq_printf(m, "\n");
}
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
@@ -3467,21 +3278,16 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
} else {
word = ep_38C1600->wdtr_able;
}
- len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
- ASC_PRT_NEXT();
- for (i = 0; i <= ADV_MAX_TID; i++) {
- len = asc_prt_line(cp, leftlen, " %c",
- (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
- ASC_PRT_NEXT();
- }
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, " Wide Transfer: ");
+ for (i = 0; i <= ADV_MAX_TID; i++)
+ seq_printf(m, " %c",
+ (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+ seq_printf(m, "\n");
if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
- len = asc_prt_line(cp, leftlen,
- " Synchronous Transfer Speed (Mhz):\n ");
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " Synchronous Transfer Speed (Mhz):\n ");
for (i = 0; i <= ADV_MAX_TID; i++) {
char *speed_str;
@@ -3517,99 +3323,64 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen
speed_str = "Unk";
break;
}
- len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
- ASC_PRT_NEXT();
- if (i == 7) {
- len = asc_prt_line(cp, leftlen, "\n ");
- ASC_PRT_NEXT();
- }
+ seq_printf(m, "%X:%s ", i, speed_str);
+ if (i == 7)
+ seq_printf(m, "\n ");
sdtr_speed >>= 4;
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
}
-
- return totlen;
}
/*
* asc_prt_driver_conf()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
- int leftlen;
- int totlen;
- int len;
int chip_scsi_id;
- leftlen = cplen;
- totlen = len = 0;
+ seq_printf(m,
+ "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
- len = asc_prt_line(cp, leftlen,
- "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " host_busy %u, last_reset %lu, max_id %u, max_lun %u, max_channel %u\n",
+ shost->host_busy, shost->last_reset, shost->max_id,
+ shost->max_lun, shost->max_channel);
- len = asc_prt_line(cp, leftlen,
- " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
- shost->host_busy, shost->last_reset, shost->max_id,
- shost->max_lun, shost->max_channel);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+ shost->unique_id, shost->can_queue, shost->this_id,
+ shost->sg_tablesize, shost->cmd_per_lun);
- len = asc_prt_line(cp, leftlen,
- " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
- shost->unique_id, shost->can_queue, shost->this_id,
- shost->sg_tablesize, shost->cmd_per_lun);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " unchecked_isa_dma %d, use_clustering %d\n",
+ shost->unchecked_isa_dma, shost->use_clustering);
- len = asc_prt_line(cp, leftlen,
- " unchecked_isa_dma %d, use_clustering %d\n",
- shost->unchecked_isa_dma, shost->use_clustering);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " flags 0x%x, last_reset 0x%lx, jiffies 0x%lx, asc_n_io_port 0x%x\n",
+ boardp->flags, boardp->last_reset, jiffies,
+ boardp->asc_n_io_port);
- len = asc_prt_line(cp, leftlen,
- " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
- boardp->flags, boardp->last_reset, jiffies,
- boardp->asc_n_io_port);
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
- ASC_PRT_NEXT();
+ seq_printf(m, " io_port 0x%lx\n", shost->io_port);
if (ASC_NARROW_BOARD(boardp)) {
chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
} else {
chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
}
-
- return totlen;
}
/*
* asc_prt_asc_board_info()
*
* Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_asc_board_info(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
int chip_scsi_id;
- int leftlen;
- int totlen;
- int len;
ASC_DVC_VAR *v;
ASC_DVC_CFG *c;
int i;
@@ -3619,105 +3390,79 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
c = &boardp->dvc_cfg.asc_dvc_cfg;
chip_scsi_id = c->chip_scsi_id;
- leftlen = cplen;
- totlen = len = 0;
+ seq_printf(m,
+ "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
- len = asc_prt_line(cp, leftlen,
- "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
- "mcode_version 0x%x, err_code %u\n",
- c->chip_version, c->mcode_date, c->mcode_version,
- v->err_code);
- ASC_PRT_NEXT();
+ seq_printf(m, " chip_version %u, mcode_date 0x%x, "
+ "mcode_version 0x%x, err_code %u\n",
+ c->chip_version, c->mcode_date, c->mcode_version,
+ v->err_code);
/* Current number of commands waiting for the host. */
- len = asc_prt_line(cp, leftlen,
- " Total Command Pending: %d\n", v->cur_total_qng);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " Total Command Pending: %d\n", v->cur_total_qng);
- len = asc_prt_line(cp, leftlen, " Command Queuing:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Command Queuing:");
for (i = 0; i <= ASC_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%c",
- i,
- (v->
- use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
- 'Y' : 'N');
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%c",
+ i,
+ (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
/* Current number of commands waiting for a device. */
- len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Command Queue Pending:");
for (i = 0; i <= ASC_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%u", i, v->cur_dvc_qng[i]);
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
/* Current limit on number of commands that can be sent to a device. */
- len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Command Queue Limit:");
for (i = 0; i <= ASC_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%u", i, v->max_dvc_qng[i]);
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
/* Indicate whether the device has returned queue full status. */
- len = asc_prt_line(cp, leftlen, " Command Queue Full:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Command Queue Full:");
for (i = 0; i <= ASC_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
- len = asc_prt_line(cp, leftlen, " %X:Y-%d",
- i, boardp->queue_full_cnt[i]);
- } else {
- len = asc_prt_line(cp, leftlen, " %X:N", i);
- }
- ASC_PRT_NEXT();
+ if (boardp->queue_full & ADV_TID_TO_TIDMASK(i))
+ seq_printf(m, " %X:Y-%d",
+ i, boardp->queue_full_cnt[i]);
+ else
+ seq_printf(m, " %X:N", i);
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
- len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Synchronous Transfer:");
for (i = 0; i <= ASC_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%c",
- i,
- (v->
- sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%c",
+ i,
+ (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
for (i = 0; i <= ASC_MAX_TID; i++) {
uchar syn_period_ix;
@@ -3728,69 +3473,48 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:", i);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:", i);
if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
- len = asc_prt_line(cp, leftlen, " Asynchronous");
- ASC_PRT_NEXT();
+ seq_printf(m, " Asynchronous");
} else {
syn_period_ix =
(boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
1);
- len = asc_prt_line(cp, leftlen,
- " Transfer Period Factor: %d (%d.%d Mhz),",
- v->sdtr_period_tbl[syn_period_ix],
- 250 /
- v->sdtr_period_tbl[syn_period_ix],
- ASC_TENTHS(250,
- v->
- sdtr_period_tbl
- [syn_period_ix]));
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " Transfer Period Factor: %d (%d.%d Mhz),",
+ v->sdtr_period_tbl[syn_period_ix],
+ 250 / v->sdtr_period_tbl[syn_period_ix],
+ ASC_TENTHS(250,
+ v->sdtr_period_tbl[syn_period_ix]));
- len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
- boardp->
- sdtr_data[i] & ASC_SYN_MAX_OFFSET);
- ASC_PRT_NEXT();
+ seq_printf(m, " REQ/ACK Offset: %d",
+ boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
}
if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
- len = asc_prt_line(cp, leftlen, "*\n");
+ seq_printf(m, "*\n");
renegotiate = 1;
} else {
- len = asc_prt_line(cp, leftlen, "\n");
+ seq_printf(m, "\n");
}
- ASC_PRT_NEXT();
}
if (renegotiate) {
- len = asc_prt_line(cp, leftlen,
- " * = Re-negotiation pending before next command.\n");
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " * = Re-negotiation pending before next command.\n");
}
-
- return totlen;
}
/*
* asc_prt_adv_board_info()
*
* Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_adv_board_info(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
- int leftlen;
- int totlen;
- int len;
int i;
ADV_DVC_VAR *v;
ADV_DVC_CFG *c;
@@ -3809,47 +3533,35 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
iop_base = v->iop_base;
chip_scsi_id = v->chip_scsi_id;
- leftlen = cplen;
- totlen = len = 0;
-
- len = asc_prt_line(cp, leftlen,
- "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
- len = asc_prt_line(cp, leftlen,
- " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
- v->iop_base,
- AdvReadWordRegister(iop_base,
- IOPW_SCSI_CFG1) & CABLE_DETECT,
- v->err_code);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
+ (unsigned long)v->iop_base,
+ AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT,
+ v->err_code);
- len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, "
- "mcode_version 0x%x\n", c->chip_version,
- c->mcode_date, c->mcode_version);
- ASC_PRT_NEXT();
+ seq_printf(m, " chip_version %u, mcode_date 0x%x, "
+ "mcode_version 0x%x\n", c->chip_version,
+ c->mcode_date, c->mcode_version);
AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
- len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Queuing Enabled:");
for (i = 0; i <= ADV_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%c",
- i,
- (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%c",
+ i,
+ (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
- len = asc_prt_line(cp, leftlen, " Queue Limit:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Queue Limit:");
for (i = 0; i <= ADV_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3859,14 +3571,11 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
lrambyte);
- len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%d", i, lrambyte);
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
- len = asc_prt_line(cp, leftlen, " Command Pending:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Command Pending:");
for (i = 0; i <= ADV_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3876,33 +3585,26 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
lrambyte);
- len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%d", i, lrambyte);
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
- len = asc_prt_line(cp, leftlen, " Wide Enabled:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Wide Enabled:");
for (i = 0; i <= ADV_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%c",
- i,
- (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%c",
+ i,
+ (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
- len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Transfer Bit Width:");
for (i = 0; i <= ADV_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
@@ -3913,37 +3615,30 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
lramword);
- len = asc_prt_line(cp, leftlen, " %X:%d",
- i, (lramword & 0x8000) ? 16 : 8);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%d",
+ i, (lramword & 0x8000) ? 16 : 8);
if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
(wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
- len = asc_prt_line(cp, leftlen, "*");
- ASC_PRT_NEXT();
+ seq_printf(m, "*");
renegotiate = 1;
}
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
- len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
- ASC_PRT_NEXT();
+ seq_printf(m, " Synchronous Enabled:");
for (i = 0; i <= ADV_MAX_TID; i++) {
if ((chip_scsi_id == i) ||
((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:%c",
- i,
- (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
- 'N');
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:%c",
+ i,
+ (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
}
- len = asc_prt_line(cp, leftlen, "\n");
- ASC_PRT_NEXT();
+ seq_printf(m, "\n");
AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
for (i = 0; i <= ADV_MAX_TID; i++) {
@@ -3959,358 +3654,170 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
continue;
}
- len = asc_prt_line(cp, leftlen, " %X:", i);
- ASC_PRT_NEXT();
+ seq_printf(m, " %X:", i);
if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
- len = asc_prt_line(cp, leftlen, " Asynchronous");
- ASC_PRT_NEXT();
+ seq_printf(m, " Asynchronous");
} else {
- len =
- asc_prt_line(cp, leftlen,
- " Transfer Period Factor: ");
- ASC_PRT_NEXT();
+ seq_printf(m, " Transfer Period Factor: ");
if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
- len =
- asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
- ASC_PRT_NEXT();
+ seq_printf(m, "9 (80.0 Mhz),");
} else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
- len =
- asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
- ASC_PRT_NEXT();
+ seq_printf(m, "10 (40.0 Mhz),");
} else { /* 20 Mhz or below. */
period = (((lramword >> 8) * 25) + 50) / 4;
if (period == 0) { /* Should never happen. */
- len =
- asc_prt_line(cp, leftlen,
- "%d (? Mhz), ");
- ASC_PRT_NEXT();
+ seq_printf(m, "%d (? Mhz), ", period);
} else {
- len = asc_prt_line(cp, leftlen,
- "%d (%d.%d Mhz),",
- period, 250 / period,
- ASC_TENTHS(250,
- period));
- ASC_PRT_NEXT();
+ seq_printf(m,
+ "%d (%d.%d Mhz),",
+ period, 250 / period,
+ ASC_TENTHS(250, period));
}
}
- len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
- lramword & 0x1F);
- ASC_PRT_NEXT();
+ seq_printf(m, " REQ/ACK Offset: %d",
+ lramword & 0x1F);
}
if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
- len = asc_prt_line(cp, leftlen, "*\n");
+ seq_printf(m, "*\n");
renegotiate = 1;
} else {
- len = asc_prt_line(cp, leftlen, "\n");
+ seq_printf(m, "\n");
}
- ASC_PRT_NEXT();
}
if (renegotiate) {
- len = asc_prt_line(cp, leftlen,
- " * = Re-negotiation pending before next command.\n");
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " * = Re-negotiation pending before next command.\n");
}
-
- return totlen;
-}
-
-/*
- * asc_proc_copy()
- *
- * Copy proc information to a read buffer taking into account the current
- * read offset in the file and the remaining space in the read buffer.
- */
-static int
-asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
- char *cp, int cplen)
-{
- int cnt = 0;
-
- ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n",
- (unsigned)offset, (unsigned)advoffset, cplen);
- if (offset <= advoffset) {
- /* Read offset below current offset, copy everything. */
- cnt = min(cplen, leftlen);
- ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
- (ulong)curbuf, (ulong)cp, cnt);
- memcpy(curbuf, cp, cnt);
- } else if (offset < advoffset + cplen) {
- /* Read offset within current range, partial copy. */
- cnt = (advoffset + cplen) - offset;
- cp = (cp + cplen) - cnt;
- cnt = min(cnt, leftlen);
- ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n",
- (ulong)curbuf, (ulong)cp, cnt);
- memcpy(curbuf, cp, cnt);
- }
- return cnt;
}
#ifdef ADVANSYS_STATS
/*
* asc_prt_board_stats()
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
*/
-static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
+static void asc_prt_board_stats(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
struct asc_stats *s = &boardp->asc_stats;
- int leftlen = cplen;
- int len, totlen = 0;
+ seq_printf(m,
+ "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
+ shost->host_no);
- len = asc_prt_line(cp, leftlen,
- "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
- shost->host_no);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " queuecommand %u, reset %u, biosparam %u, interrupt %u\n",
+ s->queuecommand, s->reset, s->biosparam,
+ s->interrupt);
- len = asc_prt_line(cp, leftlen,
- " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
- s->queuecommand, s->reset, s->biosparam,
- s->interrupt);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " callback %u, done %u, build_error %u, build_noreq %u, build_nosg %u\n",
+ s->callback, s->done, s->build_error,
+ s->adv_build_noreq, s->adv_build_nosg);
- len = asc_prt_line(cp, leftlen,
- " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
- s->callback, s->done, s->build_error,
- s->adv_build_noreq, s->adv_build_nosg);
- ASC_PRT_NEXT();
-
- len = asc_prt_line(cp, leftlen,
- " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
- s->exe_noerror, s->exe_busy, s->exe_error,
- s->exe_unknown);
- ASC_PRT_NEXT();
+ seq_printf(m,
+ " exe_noerror %u, exe_busy %u, exe_error %u, exe_unknown %u\n",
+ s->exe_noerror, s->exe_busy, s->exe_error,
+ s->exe_unknown);
/*
* Display data transfer statistics.
*/
if (s->xfer_cnt > 0) {
- len = asc_prt_line(cp, leftlen, " xfer_cnt %lu, xfer_elem %lu, ",
- s->xfer_cnt, s->xfer_elem);
- ASC_PRT_NEXT();
+ seq_printf(m, " xfer_cnt %u, xfer_elem %u, ",
+ s->xfer_cnt, s->xfer_elem);
- len = asc_prt_line(cp, leftlen, "xfer_bytes %lu.%01lu kb\n",
- s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
- ASC_PRT_NEXT();
+ seq_printf(m, "xfer_bytes %u.%01u kb\n",
+ s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2));
/* Scatter gather transfer statistics */
- len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
- s->xfer_elem / s->xfer_cnt,
- ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
- ASC_PRT_NEXT();
+ seq_printf(m, " avg_num_elem %u.%01u, ",
+ s->xfer_elem / s->xfer_cnt,
+ ASC_TENTHS(s->xfer_elem, s->xfer_cnt));
- len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
- (s->xfer_sect / 2) / s->xfer_elem,
- ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
- ASC_PRT_NEXT();
+ seq_printf(m, "avg_elem_size %u.%01u kb, ",
+ (s->xfer_sect / 2) / s->xfer_elem,
+ ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem));
- len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
- (s->xfer_sect / 2) / s->xfer_cnt,
- ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
- ASC_PRT_NEXT();
+ seq_printf(m, "avg_xfer_size %u.%01u kb\n",
+ (s->xfer_sect / 2) / s->xfer_cnt,
+ ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt));
}
-
- return totlen;
}
#endif /* ADVANSYS_STATS */
/*
- * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
+ * advansys_show_info() - /proc/scsi/advansys/{0,1,2,3,...}
*
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset into a /proc/scsi/advansys/[0...] file
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
+ * m: seq_file to print into
+ * shost: Scsi_Host
*
* Return the number of bytes read from or written to a
* /proc/scsi/advansys/[0...] file.
- *
- * Note: This function uses the per board buffer 'prtbuf' which is
- * allocated when the board is initialized in advansys_detect(). The
- * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
- * used to write to the buffer. The way asc_proc_copy() is written
- * if 'prtbuf' is too small it will not be overwritten. Instead the
- * user just won't get all the available statistics.
*/
static int
-advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
- off_t offset, int length, int inout)
+advansys_show_info(struct seq_file *m, struct Scsi_Host *shost)
{
struct asc_board *boardp = shost_priv(shost);
- char *cp;
- int cplen;
- int cnt;
- int totcnt;
- int leftlen;
- char *curbuf;
- off_t advoffset;
ASC_DBG(1, "begin\n");
/*
- * User write not supported.
- */
- if (inout == TRUE)
- return -ENOSYS;
-
- /*
* User read of /proc/scsi/advansys/[0...] file.
*/
- /* Copy read data starting at the beginning of the buffer. */
- *start = buffer;
- curbuf = buffer;
- advoffset = 0;
- totcnt = 0;
- leftlen = length;
-
/*
* Get board configuration information.
*
* advansys_info() returns the board string from its own static buffer.
*/
- cp = (char *)advansys_info(shost);
- strcat(cp, "\n");
- cplen = strlen(cp);
/* Copy board information. */
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
-
+ seq_printf(m, "%s\n", (char *)advansys_info(shost));
/*
* Display Wide Board BIOS Information.
*/
- if (!ASC_NARROW_BOARD(boardp)) {
- cp = boardp->prtbuf;
- cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
- BUG_ON(cplen >= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
- cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- }
+ if (!ASC_NARROW_BOARD(boardp))
+ asc_prt_adv_bios(m, shost);
/*
* Display driver information for each device attached to the board.
*/
- cp = boardp->prtbuf;
- cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
- BUG_ON(cplen >= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
+ asc_prt_board_devices(m, shost);
/*
* Display EEPROM configuration for the board.
*/
- cp = boardp->prtbuf;
- if (ASC_NARROW_BOARD(boardp)) {
- cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
- } else {
- cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
- }
- BUG_ON(cplen >= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
+ if (ASC_NARROW_BOARD(boardp))
+ asc_prt_asc_board_eeprom(m, shost);
+ else
+ asc_prt_adv_board_eeprom(m, shost);
/*
* Display driver configuration and information for the board.
*/
- cp = boardp->prtbuf;
- cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
- BUG_ON(cplen >= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
+ asc_prt_driver_conf(m, shost);
#ifdef ADVANSYS_STATS
/*
* Display driver statistics for the board.
*/
- cp = boardp->prtbuf;
- cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
- BUG_ON(cplen >= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
+ asc_prt_board_stats(m, shost);
#endif /* ADVANSYS_STATS */
/*
* Display Asc Library dynamic configuration information
* for the board.
*/
- cp = boardp->prtbuf;
- if (ASC_NARROW_BOARD(boardp)) {
- cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
- } else {
- cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
- }
- BUG_ON(cplen >= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG(1, "totcnt %d\n", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
-
- ASC_DBG(1, "totcnt %d\n", totcnt);
-
- return totcnt;
+ if (ASC_NARROW_BOARD(boardp))
+ asc_prt_asc_board_info(m, shost);
+ else
+ asc_prt_adv_board_info(m, shost);
+ return 0;
}
#endif /* CONFIG_PROC_FS */
@@ -9526,7 +9033,7 @@ advansys_queuecommand_lck(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *
static DEF_SCSI_QCMD(advansys_queuecommand)
-static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
+static ushort AscGetEisaChipCfg(PortAddr iop_base)
{
PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
(PortAddr) (ASC_EISA_CFG_IOP_MASK);
@@ -9537,8 +9044,8 @@ static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
* Return the BIOS address of the adapter at the specified
* I/O port and with the specified bus type.
*/
-static unsigned short __devinit
-AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
+static unsigned short AscGetChipBiosAddress(PortAddr iop_base,
+ unsigned short bus_type)
{
unsigned short cfg_lsw;
unsigned short bios_addr;
@@ -9569,7 +9076,7 @@ AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
return bios_addr;
}
-static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
+static uchar AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
{
ushort cfg_lsw;
@@ -9583,7 +9090,7 @@ static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
return (AscGetChipScsiID(iop_base));
}
-static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
+static unsigned char AscGetChipScsiCtrl(PortAddr iop_base)
{
unsigned char sc;
@@ -9593,8 +9100,8 @@ static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
return sc;
}
-static unsigned char __devinit
-AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
+static unsigned char AscGetChipVersion(PortAddr iop_base,
+ unsigned short bus_type)
{
if (bus_type & ASC_IS_EISA) {
PortAddr eisa_iop;
@@ -9608,7 +9115,7 @@ AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
}
#ifdef CONFIG_ISA
-static void __devinit AscEnableIsaDma(uchar dma_channel)
+static void AscEnableIsaDma(uchar dma_channel)
{
if (dma_channel < 4) {
outp(0x000B, (ushort)(0xC0 | dma_channel));
@@ -9638,7 +9145,7 @@ static int AscStopQueueExe(PortAddr iop_base)
return (0);
}
-static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
+static ASC_DCNT AscGetMaxDmaCount(ushort bus_type)
{
if (bus_type & ASC_IS_ISA)
return ASC_MAX_ISA_DMA_COUNT;
@@ -9648,7 +9155,7 @@ static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
}
#ifdef CONFIG_ISA
-static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
+static ushort AscGetIsaDmaChannel(PortAddr iop_base)
{
ushort channel;
@@ -9660,7 +9167,7 @@ static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
return (channel + 4);
}
-static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
+static ushort AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
{
ushort cfg_lsw;
uchar value;
@@ -9678,7 +9185,7 @@ static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channe
return 0;
}
-static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
+static uchar AscGetIsaDmaSpeed(PortAddr iop_base)
{
uchar speed_value;
@@ -9689,7 +9196,7 @@ static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
return speed_value;
}
-static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
+static uchar AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
{
speed_value &= 0x07;
AscSetBank(iop_base, 1);
@@ -9699,7 +9206,7 @@ static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
}
#endif /* CONFIG_ISA */
-static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
+static ushort AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
{
int i;
PortAddr iop_base;
@@ -9786,7 +9293,7 @@ static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
return warn_code;
}
-static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
+static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
{
int retry;
@@ -9801,12 +9308,12 @@ static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
return 0;
}
-static void __devinit AscWaitEEPRead(void)
+static void AscWaitEEPRead(void)
{
mdelay(1);
}
-static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
+static ushort AscReadEEPWord(PortAddr iop_base, uchar addr)
{
ushort read_wval;
uchar cmd_reg;
@@ -9821,8 +9328,8 @@ static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
return read_wval;
}
-static ushort __devinit
-AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static ushort AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf,
+ ushort bus_type)
{
ushort wval;
ushort sum;
@@ -9868,7 +9375,7 @@ AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
return sum;
}
-static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
+static int AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
{
PortAddr iop_base;
ushort q_addr;
@@ -9890,12 +9397,12 @@ static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
return (sta);
}
-static void __devinit AscWaitEEPWrite(void)
+static void AscWaitEEPWrite(void)
{
mdelay(20);
}
-static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
+static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
{
ushort read_back;
int retry;
@@ -9914,8 +9421,7 @@ static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
}
}
-static ushort __devinit
-AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
+static ushort AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
{
ushort read_wval;
@@ -9935,8 +9441,8 @@ AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
return (read_wval);
}
-static int __devinit
-AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static int AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf,
+ ushort bus_type)
{
int n_error;
ushort *wbuf;
@@ -10031,8 +9537,8 @@ AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
return n_error;
}
-static int __devinit
-AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static int AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf,
+ ushort bus_type)
{
int retry;
int n_error;
@@ -10050,7 +9556,7 @@ AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
return n_error;
}
-static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
+static ushort AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
{
ASCEEP_CONFIG eep_config_buf;
ASCEEP_CONFIG *eep_config;
@@ -10215,7 +9721,7 @@ static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
return (warn_code);
}
-static int __devinit AscInitGetConfig(struct Scsi_Host *shost)
+static int AscInitGetConfig(struct Scsi_Host *shost)
{
struct asc_board *board = shost_priv(shost);
ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
@@ -10269,7 +9775,7 @@ static int __devinit AscInitGetConfig(struct Scsi_Host *shost)
return asc_dvc->err_code;
}
-static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
+static int AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
{
struct asc_board *board = shost_priv(shost);
ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
@@ -10383,7 +9889,7 @@ static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *sh
* on big-endian platforms so char fields read as words are actually being
* unswapped on big-endian platforms.
*/
-static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
+static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config = {
ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
0x0000, /* cfg_msw */
0xFFFF, /* disc_enable */
@@ -10421,7 +9927,7 @@ static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
0 /* num_of_err */
};
-static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
+static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar = {
0, /* cfg_lsw */
0, /* cfg_msw */
0, /* -disc_enable */
@@ -10459,7 +9965,7 @@ static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
0 /* num_of_err */
};
-static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
+static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config = {
ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
0x0000, /* 01 cfg_msw */
0xFFFF, /* 02 disc_enable */
@@ -10524,7 +10030,7 @@ static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
0 /* 63 reserved */
};
-static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
+static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar = {
0, /* 00 cfg_lsw */
0, /* 01 cfg_msw */
0, /* 02 disc_enable */
@@ -10589,7 +10095,7 @@ static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata =
0 /* 63 reserved */
};
-static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
+static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config = {
ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
0x0000, /* 01 cfg_msw */
0xFFFF, /* 02 disc_enable */
@@ -10654,7 +10160,7 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
0 /* 63 reserved */
};
-static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
+static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar = {
0, /* 00 cfg_lsw */
0, /* 01 cfg_msw */
0, /* 02 disc_enable */
@@ -10723,7 +10229,7 @@ static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata =
/*
* Wait for EEPROM command to complete
*/
-static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
+static void AdvWaitEEPCmd(AdvPortAddr iop_base)
{
int eep_delay_ms;
@@ -10742,7 +10248,7 @@ static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
/*
* Read the EEPROM from specified location
*/
-static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
+static ushort AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
{
AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
ASC_EEP_CMD_READ | eep_word_addr);
@@ -10753,8 +10259,8 @@ static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
/*
* Write the EEPROM from 'cfg_buf'.
*/
-static void __devinit
-AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
+static void AdvSet3550EEPConfig(AdvPortAddr iop_base,
+ ADVEEP_3550_CONFIG *cfg_buf)
{
ushort *wbuf;
ushort addr, chksum;
@@ -10820,8 +10326,8 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
/*
* Write the EEPROM from 'cfg_buf'.
*/
-static void __devinit
-AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
+static void AdvSet38C0800EEPConfig(AdvPortAddr iop_base,
+ ADVEEP_38C0800_CONFIG *cfg_buf)
{
ushort *wbuf;
ushort *charfields;
@@ -10887,8 +10393,8 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
/*
* Write the EEPROM from 'cfg_buf'.
*/
-static void __devinit
-AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
+static void AdvSet38C1600EEPConfig(AdvPortAddr iop_base,
+ ADVEEP_38C1600_CONFIG *cfg_buf)
{
ushort *wbuf;
ushort *charfields;
@@ -10956,8 +10462,8 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
*
* Return a checksum based on the EEPROM configuration read.
*/
-static ushort __devinit
-AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
+static ushort AdvGet3550EEPConfig(AdvPortAddr iop_base,
+ ADVEEP_3550_CONFIG *cfg_buf)
{
ushort wval, chksum;
ushort *wbuf;
@@ -10999,8 +10505,8 @@ AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
*
* Return a checksum based on the EEPROM configuration read.
*/
-static ushort __devinit
-AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
+static ushort AdvGet38C0800EEPConfig(AdvPortAddr iop_base,
+ ADVEEP_38C0800_CONFIG *cfg_buf)
{
ushort wval, chksum;
ushort *wbuf;
@@ -11042,8 +10548,8 @@ AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
*
* Return a checksum based on the EEPROM configuration read.
*/
-static ushort __devinit
-AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
+static ushort AdvGet38C1600EEPConfig(AdvPortAddr iop_base,
+ ADVEEP_38C1600_CONFIG *cfg_buf)
{
ushort wval, chksum;
ushort *wbuf;
@@ -11092,7 +10598,7 @@ AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
*
* Note: Chip is stopped on entry.
*/
-static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
+static int AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
{
AdvPortAddr iop_base;
ushort warn_code;
@@ -11242,7 +10748,7 @@ static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
*
* Note: Chip is stopped on entry.
*/
-static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
+static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
{
AdvPortAddr iop_base;
ushort warn_code;
@@ -11441,7 +10947,7 @@ static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
*
* Note: Chip is stopped on entry.
*/
-static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
+static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
{
AdvPortAddr iop_base;
ushort warn_code;
@@ -11661,8 +11167,7 @@ static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
* For a non-fatal error return a warning code. If there are no warnings
* then 0 is returned.
*/
-static int __devinit
-AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
+static int AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
{
struct asc_board *board = shost_priv(shost);
ADV_DVC_VAR *asc_dvc = &board->dvc_var.adv_dvc_var;
@@ -11745,7 +11250,7 @@ AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
static struct scsi_host_template advansys_template = {
.proc_name = DRV_NAME,
#ifdef CONFIG_PROC_FS
- .proc_info = advansys_proc_info,
+ .show_info = advansys_show_info,
#endif
.name = DRV_NAME,
.info = advansys_info,
@@ -11769,7 +11274,7 @@ static struct scsi_host_template advansys_template = {
.use_clustering = ENABLE_CLUSTERING,
};
-static int __devinit advansys_wide_init_chip(struct Scsi_Host *shost)
+static int advansys_wide_init_chip(struct Scsi_Host *shost)
{
struct asc_board *board = shost_priv(shost);
struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
@@ -11882,8 +11387,8 @@ static void advansys_wide_free_mem(struct asc_board *board)
}
}
-static int __devinit advansys_board_found(struct Scsi_Host *shost,
- unsigned int iop, int bus_type)
+static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
+ int bus_type)
{
struct pci_dev *pdev;
struct asc_board *boardp = shost_priv(shost);
@@ -11941,20 +11446,6 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
#endif /* CONFIG_PCI */
}
-#ifdef CONFIG_PROC_FS
- /*
- * Allocate buffer for printing information from
- * /proc/scsi/advansys/[0...].
- */
- boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
- if (!boardp->prtbuf) {
- shost_printk(KERN_ERR, shost, "kmalloc(%d) returned NULL\n",
- ASC_PRTBUF_SIZE);
- ret = -ENOMEM;
- goto err_unmap;
- }
-#endif /* CONFIG_PROC_FS */
-
if (ASC_NARROW_BOARD(boardp)) {
/*
* Set the board bus type and PCI IRQ before
@@ -12012,7 +11503,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
}
if (ret)
- goto err_free_proc;
+ goto err_unmap;
/*
* Save the EEPROM configuration so that it can be displayed
@@ -12057,7 +11548,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
ASC_DBG(2, "AscInitSetConfig()\n");
ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0;
if (ret)
- goto err_free_proc;
+ goto err_unmap;
} else {
ADVEEP_3550_CONFIG *ep_3550;
ADVEEP_38C0800_CONFIG *ep_38C0800;
@@ -12292,7 +11783,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
shost_printk(KERN_ERR, shost, "request_dma() "
"%d failed %d\n",
shost->dma_channel, ret);
- goto err_free_proc;
+ goto err_unmap;
}
AscEnableIsaDma(shost->dma_channel);
}
@@ -12373,8 +11864,6 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
if (shost->dma_channel != NO_ISA_DMA)
free_dma(shost->dma_channel);
#endif
- err_free_proc:
- kfree(boardp->prtbuf);
err_unmap:
if (boardp->ioremap_addr)
iounmap(boardp->ioremap_addr);
@@ -12408,7 +11897,6 @@ static int advansys_release(struct Scsi_Host *shost)
iounmap(board->ioremap_addr);
advansys_wide_free_mem(board);
}
- kfree(board->prtbuf);
scsi_host_put(shost);
ASC_DBG(1, "end\n");
return 0;
@@ -12428,7 +11916,7 @@ static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] = {
* 10: 12
* 11: 15
*/
-static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
+static unsigned int advansys_isa_irq_no(PortAddr iop_base)
{
unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
@@ -12437,7 +11925,7 @@ static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
return chip_irq;
}
-static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
+static int advansys_isa_probe(struct device *dev, unsigned int id)
{
int err = -ENODEV;
PortAddr iop_base = _asc_def_iop_base[id];
@@ -12477,7 +11965,7 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
return err;
}
-static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
+static int advansys_isa_remove(struct device *dev, unsigned int id)
{
int ioport = _asc_def_iop_base[id];
advansys_release(dev_get_drvdata(dev));
@@ -12487,7 +11975,7 @@ static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
static struct isa_driver advansys_isa_driver = {
.probe = advansys_isa_probe,
- .remove = __devexit_p(advansys_isa_remove),
+ .remove = advansys_isa_remove,
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
@@ -12505,7 +11993,7 @@ static struct isa_driver advansys_isa_driver = {
* 110: 15
* 111: invalid
*/
-static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
+static unsigned int advansys_vlb_irq_no(PortAddr iop_base)
{
unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
@@ -12514,7 +12002,7 @@ static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
return chip_irq;
}
-static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
+static int advansys_vlb_probe(struct device *dev, unsigned int id)
{
int err = -ENODEV;
PortAddr iop_base = _asc_def_iop_base[id];
@@ -12561,14 +12049,14 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
static struct isa_driver advansys_vlb_driver = {
.probe = advansys_vlb_probe,
- .remove = __devexit_p(advansys_isa_remove),
+ .remove = advansys_isa_remove,
.driver = {
.owner = THIS_MODULE,
.name = "advansys_vlb",
},
};
-static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
+static struct eisa_device_id advansys_eisa_table[] = {
{ "ABP7401" },
{ "ABP7501" },
{ "" }
@@ -12595,7 +12083,7 @@ struct eisa_scsi_data {
* 110: invalid
* 111: invalid
*/
-static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
+static unsigned int advansys_eisa_irq_no(struct eisa_device *edev)
{
unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
@@ -12604,7 +12092,7 @@ static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
return chip_irq;
}
-static int __devinit advansys_eisa_probe(struct device *dev)
+static int advansys_eisa_probe(struct device *dev)
{
int i, ioport, irq = 0;
int err;
@@ -12677,7 +12165,7 @@ static int __devinit advansys_eisa_probe(struct device *dev)
return err;
}
-static __devexit int advansys_eisa_remove(struct device *dev)
+static int advansys_eisa_remove(struct device *dev)
{
int i;
struct eisa_scsi_data *data = dev_get_drvdata(dev);
@@ -12701,12 +12189,12 @@ static struct eisa_driver advansys_eisa_driver = {
.driver = {
.name = DRV_NAME,
.probe = advansys_eisa_probe,
- .remove = __devexit_p(advansys_eisa_remove),
+ .remove = advansys_eisa_remove,
}
};
/* PCI Devices supported by this driver */
-static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
+static struct pci_device_id advansys_pci_tbl[] = {
{PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
@@ -12724,7 +12212,7 @@ static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
-static void __devinit advansys_set_latency(struct pci_dev *pdev)
+static void advansys_set_latency(struct pci_dev *pdev)
{
if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
(pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
@@ -12737,8 +12225,8 @@ static void __devinit advansys_set_latency(struct pci_dev *pdev)
}
}
-static int __devinit
-advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int advansys_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int err, ioport;
struct Scsi_Host *shost;
@@ -12791,7 +12279,7 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
-static void __devexit advansys_pci_remove(struct pci_dev *pdev)
+static void advansys_pci_remove(struct pci_dev *pdev)
{
advansys_release(pci_get_drvdata(pdev));
pci_release_regions(pdev);
@@ -12802,7 +12290,7 @@ static struct pci_driver advansys_pci_driver = {
.name = DRV_NAME,
.id_table = advansys_pci_tbl,
.probe = advansys_pci_probe,
- .remove = __devexit_p(advansys_pci_remove),
+ .remove = advansys_pci_remove,
};
static int __init advansys_init(void)
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index dd4547b..3f7b6fe 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -420,7 +420,7 @@ MODULE_PARM_DESC(aha152x1, "parameters for second controller");
#endif /* MODULE */
#ifdef __ISAPNP__
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
@@ -2977,11 +2977,10 @@ static void show_queues(struct Scsi_Host *shpnt)
}
#undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, ## args)
+#define SPRINTF(args...) seq_printf(m, ##args)
-static int get_command(char *pos, Scsi_Cmnd * ptr)
+static void get_command(struct seq_file *m, Scsi_Cmnd * ptr)
{
- char *start = pos;
int i;
SPRINTF("%p: target=%d; lun=%d; cmnd=( ",
@@ -3011,13 +3010,10 @@ static int get_command(char *pos, Scsi_Cmnd * ptr)
if (ptr->SCp.phase & syncneg)
SPRINTF("syncneg|");
SPRINTF("; next=0x%p\n", SCNEXT(ptr));
-
- return (pos - start);
}
-static int get_ports(struct Scsi_Host *shpnt, char *pos)
+static void get_ports(struct seq_file *m, struct Scsi_Host *shpnt)
{
- char *start = pos;
int s;
SPRINTF("\n%s: %s(%s) ", CURRENT_SC ? "on bus" : "waiting", states[STATE].name, states[PREVSTATE].name);
@@ -3273,11 +3269,9 @@ static int get_ports(struct Scsi_Host *shpnt, char *pos)
if (s & ENREQINIT)
SPRINTF("ENREQINIT ");
SPRINTF(")\n");
-
- return (pos - start);
}
-static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
+static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
{
if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
return -EINVAL;
@@ -3320,26 +3314,11 @@ static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
return length;
}
-#undef SPRINTF
-#define SPRINTF(args...) \
- do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
-
-static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
- off_t offset, int length, int inout)
+static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
{
int i;
- char *pos = buffer;
Scsi_Cmnd *ptr;
unsigned long flags;
- int thislength;
-
- DPRINTK(debug_procinfo,
- KERN_DEBUG "aha152x_proc_info: buffer=%p offset=%ld length=%d hostno=%d inout=%d\n",
- buffer, offset, length, shpnt->host_no, inout);
-
-
- if (inout)
- return aha152x_set_info(buffer, length, shpnt);
SPRINTF(AHA152X_REVID "\n");
@@ -3392,25 +3371,25 @@ static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start
if (ISSUE_SC) {
SPRINTF("not yet issued commands:\n");
for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
- pos += get_command(pos, ptr);
+ get_command(m, ptr);
} else
SPRINTF("no not yet issued commands\n");
DO_UNLOCK(flags);
if (CURRENT_SC) {
SPRINTF("current command:\n");
- pos += get_command(pos, CURRENT_SC);
+ get_command(m, CURRENT_SC);
} else
SPRINTF("no current command\n");
if (DISCONNECTED_SC) {
SPRINTF("disconnected commands:\n");
for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
- pos += get_command(pos, ptr);
+ get_command(m, ptr);
} else
SPRINTF("no disconnected commands\n");
- pos += get_ports(shpnt, pos);
+ get_ports(m, shpnt);
#if defined(AHA152X_STAT)
SPRINTF("statistics:\n"
@@ -3440,24 +3419,7 @@ static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start
HOSTDATA(shpnt)->time[i]);
}
#endif
-
- DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: pos=%p\n", pos);
-
- thislength = pos - (buffer + offset);
- DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: length=%d thislength=%d\n", length, thislength);
-
- if(thislength<0) {
- DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: output too short\n");
- *start = NULL;
- return 0;
- }
-
- thislength = thislength<length ? thislength : length;
-
- DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: return %d\n", thislength);
-
- *start = buffer + offset;
- return thislength < length ? thislength : length;
+ return 0;
}
static int aha152x_adjust_queue(struct scsi_device *device)
@@ -3470,7 +3432,8 @@ static struct scsi_host_template aha152x_driver_template = {
.module = THIS_MODULE,
.name = AHA152X_REVID,
.proc_name = "aha152x",
- .proc_info = aha152x_proc_info,
+ .show_info = aha152x_show_info,
+ .write_info = aha152x_set_info,
.queuecommand = aha152x_queue,
.eh_abort_handler = aha152x_abort,
.eh_device_reset_handler = aha152x_device_reset,
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index a3e6ed3..5f31017 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -106,33 +106,14 @@ static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
return hdata->ecb_dma_addr + offset;
}
-static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer,
- char **start, off_t offset,
- int length, int inout)
+static int aha1740_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
{
- int len;
- struct aha1740_hostdata *host;
-
- if (inout)
- return-ENOSYS;
-
- host = HOSTDATA(shpnt);
-
- len = sprintf(buffer, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
+ struct aha1740_hostdata *host = HOSTDATA(shpnt);
+ seq_printf(m, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
"Extended translation %sabled.\n",
shpnt->io_port, shpnt->irq, host->edev->slot,
host->translation ? "en" : "dis");
-
- if (offset > len) {
- *start = buffer;
- return 0;
- }
-
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- return len;
+ return 0;
}
static int aha1740_makecode(unchar *sense, unchar *status)
@@ -556,7 +537,7 @@ static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
static struct scsi_host_template aha1740_template = {
.module = THIS_MODULE,
.proc_name = "aha1740",
- .proc_info = aha1740_proc_info,
+ .show_info = aha1740_show_info,
.name = "Adaptec 174x (EISA)",
.queuecommand = aha1740_queuecommand,
.bios_param = aha1740_biosparam,
@@ -646,7 +627,7 @@ static int aha1740_probe (struct device *dev)
return -ENODEV;
}
-static __devexit int aha1740_remove (struct device *dev)
+static int aha1740_remove (struct device *dev)
{
struct Scsi_Host *shpnt = dev_get_drvdata(dev);
struct aha1740_hostdata *host = HOSTDATA (shpnt);
@@ -677,7 +658,7 @@ static struct eisa_driver aha1740_driver = {
.driver = {
.name = "aha1740",
.probe = aha1740_probe,
- .remove = __devexit_p (aha1740_remove),
+ .remove = aha1740_remove,
},
};
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 9328121..69d5c43 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -906,7 +906,8 @@ struct scsi_host_template aic79xx_driver_template = {
.module = THIS_MODULE,
.name = "aic79xx",
.proc_name = "aic79xx",
- .proc_info = ahd_linux_proc_info,
+ .show_info = ahd_linux_show_info,
+ .write_info = ahd_proc_write_seeprom,
.info = ahd_linux_info,
.queuecommand = ahd_linux_queue,
.eh_abort_handler = ahd_linux_abort,
@@ -1702,19 +1703,13 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
switch (code) {
case AC_TRANSFER_NEG:
{
- char buf[80];
struct scsi_target *starget;
- struct info_str info;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
unsigned int target_ppr_options;
BUG_ON(target == CAM_TARGET_WILDCARD);
- info.buffer = buf;
- info.length = sizeof(buf);
- info.offset = 0;
- info.pos = 0;
tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
target, &tstate);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 28e4349..c58fa33 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -379,14 +379,6 @@ void ahd_insb(struct ahd_softc * ahd, long port,
int ahd_linux_register_host(struct ahd_softc *,
struct scsi_host_template *);
-/*************************** Pretty Printing **********************************/
-struct info_str {
- char *buffer;
- int length;
- off_t offset;
- int pos;
-};
-
/******************************** Locking *************************************/
static inline void
ahd_lockinit(struct ahd_softc *ahd)
@@ -513,8 +505,8 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
}
/**************************** Proc FS Support *********************************/
-int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
- off_t, int, int);
+int ahd_proc_write_seeprom(struct Scsi_Host *, char *, int);
+int ahd_linux_show_info(struct seq_file *,struct Scsi_Host *);
/*********************** Transaction Access Wrappers **************************/
static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index 59c85d5..e9778b4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -42,16 +42,12 @@
#include "aic79xx_osm.h"
#include "aic79xx_inline.h"
-static void copy_mem_info(struct info_str *info, char *data, int len);
-static int copy_info(struct info_str *info, char *fmt, ...);
static void ahd_dump_target_state(struct ahd_softc *ahd,
- struct info_str *info,
+ struct seq_file *m,
u_int our_id, char channel,
u_int target_id);
-static void ahd_dump_device_state(struct info_str *info,
+static void ahd_dump_device_state(struct seq_file *m,
struct scsi_device *sdev);
-static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
- char *buffer, int length);
/*
* Table of syncrates that don't follow the "divisible by 4"
@@ -93,58 +89,15 @@ ahd_calc_syncsrate(u_int period_factor)
return (10000000 / (period_factor * 4 * 10));
}
-
-static void
-copy_mem_info(struct info_str *info, char *data, int len)
-{
- if (info->pos + len > info->offset + info->length)
- len = info->offset + info->length - info->pos;
-
- if (info->pos + len < info->offset) {
- info->pos += len;
- return;
- }
-
- if (info->pos < info->offset) {
- off_t partial;
-
- partial = info->offset - info->pos;
- data += partial;
- info->pos += partial;
- len -= partial;
- }
-
- if (len > 0) {
- memcpy(info->buffer, data, len);
- info->pos += len;
- info->buffer += len;
- }
-}
-
-static int
-copy_info(struct info_str *info, char *fmt, ...)
-{
- va_list args;
- char buf[256];
- int len;
-
- va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
- va_end(args);
-
- copy_mem_info(info, buf, len);
- return (len);
-}
-
static void
-ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
+ahd_format_transinfo(struct seq_file *m, struct ahd_transinfo *tinfo)
{
u_int speed;
u_int freq;
u_int mb;
if (tinfo->period == AHD_PERIOD_UNKNOWN) {
- copy_info(info, "Renegotiation Pending\n");
+ seq_printf(m, "Renegotiation Pending\n");
return;
}
speed = 3300;
@@ -156,34 +109,34 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
speed *= (0x01 << tinfo->width);
mb = speed / 1000;
if (mb > 0)
- copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000);
+ seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
else
- copy_info(info, "%dKB/s transfers", speed);
+ seq_printf(m, "%dKB/s transfers", speed);
if (freq != 0) {
int printed_options;
printed_options = 0;
- copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000);
+ seq_printf(m, " (%d.%03dMHz", freq / 1000, freq % 1000);
if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
- copy_info(info, " RDSTRM");
+ seq_printf(m, " RDSTRM");
printed_options++;
}
if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
- copy_info(info, "%s", printed_options ? "|DT" : " DT");
+ seq_printf(m, "%s", printed_options ? "|DT" : " DT");
printed_options++;
}
if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- copy_info(info, "%s", printed_options ? "|IU" : " IU");
+ seq_printf(m, "%s", printed_options ? "|IU" : " IU");
printed_options++;
}
if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) {
- copy_info(info, "%s",
+ seq_printf(m, "%s",
printed_options ? "|RTI" : " RTI");
printed_options++;
}
if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
- copy_info(info, "%s",
+ seq_printf(m, "%s",
printed_options ? "|QAS" : " QAS");
printed_options++;
}
@@ -191,19 +144,19 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
if (tinfo->width > 0) {
if (freq != 0) {
- copy_info(info, ", ");
+ seq_printf(m, ", ");
} else {
- copy_info(info, " (");
+ seq_printf(m, " (");
}
- copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width));
+ seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
} else if (freq != 0) {
- copy_info(info, ")");
+ seq_printf(m, ")");
}
- copy_info(info, "\n");
+ seq_printf(m, "\n");
}
static void
-ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
+ahd_dump_target_state(struct ahd_softc *ahd, struct seq_file *m,
u_int our_id, char channel, u_int target_id)
{
struct scsi_target *starget;
@@ -213,17 +166,17 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
target_id, &tstate);
- copy_info(info, "Target %d Negotiation Settings\n", target_id);
- copy_info(info, "\tUser: ");
- ahd_format_transinfo(info, &tinfo->user);
+ seq_printf(m, "Target %d Negotiation Settings\n", target_id);
+ seq_printf(m, "\tUser: ");
+ ahd_format_transinfo(m, &tinfo->user);
starget = ahd->platform_data->starget[target_id];
if (starget == NULL)
return;
- copy_info(info, "\tGoal: ");
- ahd_format_transinfo(info, &tinfo->goal);
- copy_info(info, "\tCurr: ");
- ahd_format_transinfo(info, &tinfo->curr);
+ seq_printf(m, "\tGoal: ");
+ ahd_format_transinfo(m, &tinfo->goal);
+ seq_printf(m, "\tCurr: ");
+ ahd_format_transinfo(m, &tinfo->curr);
for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
struct scsi_device *dev;
@@ -233,29 +186,30 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
if (dev == NULL)
continue;
- ahd_dump_device_state(info, dev);
+ ahd_dump_device_state(m, dev);
}
}
static void
-ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
+ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
{
struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
- copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
+ seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
sdev->sdev_target->channel + 'A',
sdev->sdev_target->id, sdev->lun);
- copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
- copy_info(info, "\t\tCommands Active %d\n", dev->active);
- copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
- copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
- copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
+ seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
+ seq_printf(m, "\t\tCommands Active %d\n", dev->active);
+ seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
+ seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
+ seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
}
-static int
-ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length)
+int
+ahd_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
{
+ struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
ahd_mode_state saved_modes;
int have_seeprom;
u_long s;
@@ -319,64 +273,45 @@ done:
* Return information to handle /proc support for the driver.
*/
int
-ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
- off_t offset, int length, int inout)
+ahd_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
{
struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
- struct info_str info;
char ahd_info[256];
u_int max_targ;
u_int i;
- int retval;
- /* Has data been written to the file? */
- if (inout == TRUE) {
- retval = ahd_proc_write_seeprom(ahd, buffer, length);
- goto done;
- }
-
- if (start)
- *start = buffer;
-
- info.buffer = buffer;
- info.length = length;
- info.offset = offset;
- info.pos = 0;
-
- copy_info(&info, "Adaptec AIC79xx driver version: %s\n",
+ seq_printf(m, "Adaptec AIC79xx driver version: %s\n",
AIC79XX_DRIVER_VERSION);
- copy_info(&info, "%s\n", ahd->description);
+ seq_printf(m, "%s\n", ahd->description);
ahd_controller_info(ahd, ahd_info);
- copy_info(&info, "%s\n", ahd_info);
- copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
+ seq_printf(m, "%s\n", ahd_info);
+ seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahd->scb_data.numscbs, AHD_NSEG);
max_targ = 16;
if (ahd->seep_config == NULL)
- copy_info(&info, "No Serial EEPROM\n");
+ seq_printf(m, "No Serial EEPROM\n");
else {
- copy_info(&info, "Serial EEPROM:\n");
+ seq_printf(m, "Serial EEPROM:\n");
for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) {
if (((i % 8) == 0) && (i != 0)) {
- copy_info(&info, "\n");
+ seq_printf(m, "\n");
}
- copy_info(&info, "0x%.4x ",
+ seq_printf(m, "0x%.4x ",
((uint16_t*)ahd->seep_config)[i]);
}
- copy_info(&info, "\n");
+ seq_printf(m, "\n");
}
- copy_info(&info, "\n");
+ seq_printf(m, "\n");
if ((ahd->features & AHD_WIDE) == 0)
max_targ = 8;
for (i = 0; i < max_targ; i++) {
- ahd_dump_target_state(ahd, &info, ahd->our_id, 'A',
+ ahd_dump_target_state(ahd, m, ahd->our_id, 'A',
/*target_id*/i);
}
- retval = info.pos > info.offset ? info.pos - info.offset : 0;
-done:
- return (retval);
+ return 0;
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 5a477cd..c0c6258 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -803,7 +803,8 @@ struct scsi_host_template aic7xxx_driver_template = {
.module = THIS_MODULE,
.name = "aic7xxx",
.proc_name = "aic7xxx",
- .proc_info = ahc_linux_proc_info,
+ .show_info = ahc_linux_show_info,
+ .write_info = ahc_proc_write_seeprom,
.info = ahc_linux_info,
.queuecommand = ahc_linux_queue,
.eh_abort_handler = ahc_linux_abort,
@@ -1631,10 +1632,8 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
switch (code) {
case AC_TRANSFER_NEG:
{
- char buf[80];
struct scsi_target *starget;
struct ahc_linux_target *targ;
- struct info_str info;
struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate;
int target_offset;
@@ -1642,10 +1641,6 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
BUG_ON(target == CAM_TARGET_WILDCARD);
- info.buffer = buf;
- info.length = sizeof(buf);
- info.offset = 0;
- info.pos = 0;
tinfo = ahc_fetch_transinfo(ahc, channel,
channel == 'A' ? ahc->our_id
: ahc->our_id_b,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index bca0fb83..bc4cca9 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -383,14 +383,6 @@ void ahc_insb(struct ahc_softc * ahc, long port,
int ahc_linux_register_host(struct ahc_softc *,
struct scsi_host_template *);
-/*************************** Pretty Printing **********************************/
-struct info_str {
- char *buffer;
- int length;
- off_t offset;
- int pos;
-};
-
/******************************** Locking *************************************/
/* Lock protecting internal data structures */
@@ -523,8 +515,8 @@ ahc_flush_device_writes(struct ahc_softc *ahc)
}
/**************************** Proc FS Support *********************************/
-int ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
- off_t, int, int);
+int ahc_proc_write_seeprom(struct Scsi_Host *, char *, int);
+int ahc_linux_show_info(struct seq_file *, struct Scsi_Host *);
/*************************** Domain Validation ********************************/
/*********************** Transaction Access Wrappers *************************/
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index f2525f8..383a3d1 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -43,16 +43,12 @@
#include "aic7xxx_inline.h"
#include "aic7xxx_93cx6.h"
-static void copy_mem_info(struct info_str *info, char *data, int len);
-static int copy_info(struct info_str *info, char *fmt, ...);
static void ahc_dump_target_state(struct ahc_softc *ahc,
- struct info_str *info,
+ struct seq_file *m,
u_int our_id, char channel,
u_int target_id, u_int target_offset);
-static void ahc_dump_device_state(struct info_str *info,
+static void ahc_dump_device_state(struct seq_file *m,
struct scsi_device *dev);
-static int ahc_proc_write_seeprom(struct ahc_softc *ahc,
- char *buffer, int length);
/*
* Table of syncrates that don't follow the "divisible by 4"
@@ -94,51 +90,8 @@ ahc_calc_syncsrate(u_int period_factor)
return (10000000 / (period_factor * 4 * 10));
}
-
-static void
-copy_mem_info(struct info_str *info, char *data, int len)
-{
- if (info->pos + len > info->offset + info->length)
- len = info->offset + info->length - info->pos;
-
- if (info->pos + len < info->offset) {
- info->pos += len;
- return;
- }
-
- if (info->pos < info->offset) {
- off_t partial;
-
- partial = info->offset - info->pos;
- data += partial;
- info->pos += partial;
- len -= partial;
- }
-
- if (len > 0) {
- memcpy(info->buffer, data, len);
- info->pos += len;
- info->buffer += len;
- }
-}
-
-static int
-copy_info(struct info_str *info, char *fmt, ...)
-{
- va_list args;
- char buf[256];
- int len;
-
- va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
- va_end(args);
-
- copy_mem_info(info, buf, len);
- return (len);
-}
-
static void
-ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
+ahc_format_transinfo(struct seq_file *m, struct ahc_transinfo *tinfo)
{
u_int speed;
u_int freq;
@@ -153,12 +106,12 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
speed *= (0x01 << tinfo->width);
mb = speed / 1000;
if (mb > 0)
- copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000);
+ seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
else
- copy_info(info, "%dKB/s transfers", speed);
+ seq_printf(m, "%dKB/s transfers", speed);
if (freq != 0) {
- copy_info(info, " (%d.%03dMHz%s, offset %d",
+ seq_printf(m, " (%d.%03dMHz%s, offset %d",
freq / 1000, freq % 1000,
(tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
? " DT" : "", tinfo->offset);
@@ -166,19 +119,19 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
if (tinfo->width > 0) {
if (freq != 0) {
- copy_info(info, ", ");
+ seq_printf(m, ", ");
} else {
- copy_info(info, " (");
+ seq_printf(m, " (");
}
- copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width));
+ seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
} else if (freq != 0) {
- copy_info(info, ")");
+ seq_printf(m, ")");
}
- copy_info(info, "\n");
+ seq_printf(m, "\n");
}
static void
-ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
+ahc_dump_target_state(struct ahc_softc *ahc, struct seq_file *m,
u_int our_id, char channel, u_int target_id,
u_int target_offset)
{
@@ -190,18 +143,18 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
target_id, &tstate);
if ((ahc->features & AHC_TWIN) != 0)
- copy_info(info, "Channel %c ", channel);
- copy_info(info, "Target %d Negotiation Settings\n", target_id);
- copy_info(info, "\tUser: ");
- ahc_format_transinfo(info, &tinfo->user);
+ seq_printf(m, "Channel %c ", channel);
+ seq_printf(m, "Target %d Negotiation Settings\n", target_id);
+ seq_printf(m, "\tUser: ");
+ ahc_format_transinfo(m, &tinfo->user);
starget = ahc->platform_data->starget[target_offset];
if (!starget)
return;
- copy_info(info, "\tGoal: ");
- ahc_format_transinfo(info, &tinfo->goal);
- copy_info(info, "\tCurr: ");
- ahc_format_transinfo(info, &tinfo->curr);
+ seq_printf(m, "\tGoal: ");
+ ahc_format_transinfo(m, &tinfo->goal);
+ seq_printf(m, "\tCurr: ");
+ ahc_format_transinfo(m, &tinfo->curr);
for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
struct scsi_device *sdev;
@@ -211,29 +164,30 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
if (sdev == NULL)
continue;
- ahc_dump_device_state(info, sdev);
+ ahc_dump_device_state(m, sdev);
}
}
static void
-ahc_dump_device_state(struct info_str *info, struct scsi_device *sdev)
+ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
{
struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
- copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
+ seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
sdev->sdev_target->channel + 'A',
sdev->sdev_target->id, sdev->lun);
- copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
- copy_info(info, "\t\tCommands Active %d\n", dev->active);
- copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
- copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
- copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
+ seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
+ seq_printf(m, "\t\tCommands Active %d\n", dev->active);
+ seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
+ seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
+ seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
}
-static int
-ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length)
+int
+ahc_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
{
+ struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
struct seeprom_descriptor sd;
int have_seeprom;
u_long s;
@@ -332,53 +286,36 @@ done:
* Return information to handle /proc support for the driver.
*/
int
-ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
- off_t offset, int length, int inout)
+ahc_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
{
struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
- struct info_str info;
char ahc_info[256];
u_int max_targ;
u_int i;
- int retval;
- /* Has data been written to the file? */
- if (inout == TRUE) {
- retval = ahc_proc_write_seeprom(ahc, buffer, length);
- goto done;
- }
-
- if (start)
- *start = buffer;
-
- info.buffer = buffer;
- info.length = length;
- info.offset = offset;
- info.pos = 0;
-
- copy_info(&info, "Adaptec AIC7xxx driver version: %s\n",
+ seq_printf(m, "Adaptec AIC7xxx driver version: %s\n",
AIC7XXX_DRIVER_VERSION);
- copy_info(&info, "%s\n", ahc->description);
+ seq_printf(m, "%s\n", ahc->description);
ahc_controller_info(ahc, ahc_info);
- copy_info(&info, "%s\n", ahc_info);
- copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
+ seq_printf(m, "%s\n", ahc_info);
+ seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahc->scb_data->numscbs, AHC_NSEG);
if (ahc->seep_config == NULL)
- copy_info(&info, "No Serial EEPROM\n");
+ seq_printf(m, "No Serial EEPROM\n");
else {
- copy_info(&info, "Serial EEPROM:\n");
+ seq_printf(m, "Serial EEPROM:\n");
for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) {
if (((i % 8) == 0) && (i != 0)) {
- copy_info(&info, "\n");
+ seq_printf(m, "\n");
}
- copy_info(&info, "0x%.4x ",
+ seq_printf(m, "0x%.4x ",
((uint16_t*)ahc->seep_config)[i]);
}
- copy_info(&info, "\n");
+ seq_printf(m, "\n");
}
- copy_info(&info, "\n");
+ seq_printf(m, "\n");
max_targ = 16;
if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
@@ -398,10 +335,8 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
target_id = i % 8;
}
- ahc_dump_target_state(ahc, &info, our_id,
+ ahc_dump_target_state(ahc, m, our_id,
channel, target_id, i);
}
- retval = info.pos > info.offset ? info.pos - info.offset : 0;
-done:
- return (retval);
+ return 0;
}
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 5b212f0..33ec9c6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -11108,7 +11108,7 @@ MODULE_VERSION(AIC7XXX_H_VERSION);
static struct scsi_host_template driver_template = {
- .proc_info = aic7xxx_proc_info,
+ .show_info = aic7xxx_show_info,
.detect = aic7xxx_detect,
.release = aic7xxx_release,
.info = aic7xxx_info,
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.seq b/drivers/scsi/aic7xxx_old/aic7xxx.seq
index 823ff28..dc3bb81 100644
--- a/drivers/scsi/aic7xxx_old/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx_old/aic7xxx.seq
@@ -693,7 +693,7 @@ p_status:
* it's own message.
*
* If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
- * This is done to allow the hsot to send messages outside of an identify
+ * This is done to allow the host to send messages outside of an identify
* sequence while protecting the seqencer from testing the MK_MESSAGE bit
* on an SCB that might not be for the current nexus. (For example, a
* BDR message in response to a bad reselection would leave us pointed to
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
index b07e4f0..976f45c 100644
--- a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
@@ -30,62 +30,23 @@
*-M*************************************************************************/
-#define BLS (&aic7xxx_buffer[size])
#define HDRB \
" 0 - 4K 4 - 16K 16 - 64K 64 - 256K 256K - 1M 1M+"
-#ifdef PROC_DEBUG
-extern int vsprintf(char *, const char *, va_list);
-
-static void
-proc_debug(const char *fmt, ...)
-{
- va_list ap;
- char buf[256];
-
- va_start(ap, fmt);
- vsprintf(buf, fmt, ap);
- printk(buf);
- va_end(ap);
-}
-#else /* PROC_DEBUG */
-# define proc_debug(fmt, args...)
-#endif /* PROC_DEBUG */
-
-static int aic7xxx_buffer_size = 0;
-static char *aic7xxx_buffer = NULL;
-
/*+F*************************************************************************
* Function:
- * aic7xxx_set_info
- *
- * Description:
- * Set parameters for the driver from the /proc filesystem.
- *-F*************************************************************************/
-static int
-aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
-{
- proc_debug("aic7xxx_set_info(): %s\n", buffer);
- return (-ENOSYS); /* Currently this is a no-op */
-}
-
-
-/*+F*************************************************************************
- * Function:
- * aic7xxx_proc_info
+ * aic7xxx_show_info
*
* Description:
* Return information to handle /proc support for the driver.
*-F*************************************************************************/
int
-aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length,
- int inout)
+aic7xxx_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
{
struct aic7xxx_host *p;
struct aic_dev_data *aic_dev;
struct scsi_device *sdptr;
- int size = 0;
unsigned char i;
unsigned char tindex;
@@ -94,66 +55,21 @@ aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t
if (!p)
{
- size += sprintf(buffer, "Can't find adapter for host number %d\n", HBAptr->host_no);
- if (size > length)
- {
- return (size);
- }
- else
- {
- return (length);
- }
- }
-
- if (inout == TRUE) /* Has data been written to the file? */
- {
- return (aic7xxx_set_info(buffer, length, HBAptr));
+ seq_printf(m, "Can't find adapter for host number %d\n", HBAptr->host_no);
+ return 0;
}
p = (struct aic7xxx_host *) HBAptr->hostdata;
- /*
- * It takes roughly 1K of space to hold all relevant card info, not
- * counting any proc stats, so we start out with a 1.5k buffer size and
- * if proc_stats is defined, then we sweep the stats structure to see
- * how many drives we will be printing out for and add 384 bytes per
- * device with active stats.
- *
- * Hmmmm...that 1.5k seems to keep growing as items get added so they
- * can be easily viewed for debugging purposes. So, we bumped that
- * 1.5k to 4k so we can quit having to bump it all the time.
- */
-
- size = 4096;
- list_for_each_entry(aic_dev, &p->aic_devs, list)
- size += 512;
- if (aic7xxx_buffer_size != size)
- {
- if (aic7xxx_buffer != NULL)
- {
- kfree(aic7xxx_buffer);
- aic7xxx_buffer_size = 0;
- }
- aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
- }
- if (aic7xxx_buffer == NULL)
- {
- size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
- __LINE__);
- return size;
- }
- aic7xxx_buffer_size = size;
-
- size = 0;
- size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
- size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
- size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, "Adapter Configuration:\n");
- size += sprintf(BLS, " SCSI Adapter: %s\n",
+ seq_printf(m, "Adaptec AIC7xxx driver version: ");
+ seq_printf(m, "%s/", AIC7XXX_C_VERSION);
+ seq_printf(m, "%s", AIC7XXX_H_VERSION);
+ seq_printf(m, "\n");
+ seq_printf(m, "Adapter Configuration:\n");
+ seq_printf(m, " SCSI Adapter: %s\n",
board_names[p->board_name_index]);
if (p->flags & AHC_TWIN)
- size += sprintf(BLS, " Twin Channel Controller ");
+ seq_printf(m, " Twin Channel Controller ");
else
{
char *channel = "";
@@ -184,86 +100,86 @@ aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t
ultra = "Ultra-2 LVD/SE ";
else if (p->features & AHC_ULTRA)
ultra = "Ultra ";
- size += sprintf(BLS, " %s%sController%s ",
+ seq_printf(m, " %s%sController%s ",
ultra, wide, channel);
}
switch(p->chip & ~AHC_CHIPID_MASK)
{
case AHC_VL:
- size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
+ seq_printf(m, "at VLB slot %d\n", p->pci_device_fn);
break;
case AHC_EISA:
- size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
+ seq_printf(m, "at EISA slot %d\n", p->pci_device_fn);
break;
default:
- size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
+ seq_printf(m, "at PCI %d/%d/%d\n", p->pci_bus,
PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
break;
}
if( !(p->maddr) )
{
- size += sprintf(BLS, " Programmed I/O Base: %lx\n", p->base);
+ seq_printf(m, " Programmed I/O Base: %lx\n", p->base);
}
else
{
- size += sprintf(BLS, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
+ seq_printf(m, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
}
if( (p->chip & (AHC_VL | AHC_EISA)) )
{
- size += sprintf(BLS, " BIOS Memory Address: 0x%08x\n", p->bios_address);
+ seq_printf(m, " BIOS Memory Address: 0x%08x\n", p->bios_address);
}
- size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
+ seq_printf(m, " Adapter SEEPROM Config: %s\n",
(p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
"SEEPROM not found, using leftover BIOS values.") );
- size += sprintf(BLS, " Adaptec SCSI BIOS: %s\n",
+ seq_printf(m, " Adaptec SCSI BIOS: %s\n",
(p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
- size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
- size += sprintf(BLS, " SCBs: Active %d, Max Active %d,\n",
+ seq_printf(m, " IRQ: %d\n", HBAptr->irq);
+ seq_printf(m, " SCBs: Active %d, Max Active %d,\n",
p->activescbs, p->max_activescbs);
- size += sprintf(BLS, " Allocated %d, HW %d, "
+ seq_printf(m, " Allocated %d, HW %d, "
"Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
p->scb_data->maxscbs);
if (p->flags & AHC_EXTERNAL_SRAM)
- size += sprintf(BLS, " Using External SCB SRAM\n");
- size += sprintf(BLS, " Interrupts: %ld", p->isr_count);
+ seq_printf(m, " Using External SCB SRAM\n");
+ seq_printf(m, " Interrupts: %ld", p->isr_count);
if (p->chip & AHC_EISA)
{
- size += sprintf(BLS, " %s\n",
+ seq_printf(m, " %s\n",
(p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
}
else
{
- size += sprintf(BLS, "\n");
+ seq_printf(m, "\n");
}
- size += sprintf(BLS, " BIOS Control Word: 0x%04x\n",
+ seq_printf(m, " BIOS Control Word: 0x%04x\n",
p->bios_control);
- size += sprintf(BLS, " Adapter Control Word: 0x%04x\n",
+ seq_printf(m, " Adapter Control Word: 0x%04x\n",
p->adapter_control);
- size += sprintf(BLS, " Extended Translation: %sabled\n",
+ seq_printf(m, " Extended Translation: %sabled\n",
(p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
- size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
+ seq_printf(m, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
if (p->features & (AHC_ULTRA | AHC_ULTRA2))
{
- size += sprintf(BLS, " Ultra Enable Flags: 0x%04x\n", p->ultraenb);
+ seq_printf(m, " Ultra Enable Flags: 0x%04x\n", p->ultraenb);
}
- size += sprintf(BLS, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
- size += sprintf(BLS, " Tagged Queue By Device array for aic7xxx host "
+ seq_printf(m, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
+ seq_printf(m, " Tagged Queue By Device array for aic7xxx host "
"instance %d:\n", p->instance);
- size += sprintf(BLS, " {");
+ seq_printf(m, " {");
for(i=0; i < (MAX_TARGETS - 1); i++)
- size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
- size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
+ seq_printf(m, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
+ seq_printf(m, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, "Statistics:\n\n");
+ seq_printf(m, "\n");
+ seq_printf(m, "Statistics:\n\n");
list_for_each_entry(aic_dev, &p->aic_devs, list)
{
sdptr = aic_dev->SDptr;
tindex = sdptr->channel << 3 | sdptr->id;
- size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+ seq_printf(m, "(scsi%d:%d:%d:%d)\n",
p->host_no, sdptr->channel, sdptr->id, sdptr->lun);
- size += sprintf(BLS, " Device using %s/%s",
+ seq_printf(m, " Device using %s/%s",
(aic_dev->cur.width == MSG_EXT_WDTR_BUS_16_BIT) ?
"Wide" : "Narrow",
(aic_dev->cur.offset != 0) ?
@@ -279,78 +195,59 @@ aic7xxx_proc_info ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t
sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
if (sync_rate != NULL)
{
- size += sprintf(BLS, "%s MByte/sec, offset %d\n",
+ seq_printf(m, "%s MByte/sec, offset %d\n",
sync_rate->rate[rate],
aic_dev->cur.offset );
}
else
{
- size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
+ seq_printf(m, "3.3 MByte/sec, offset %d\n",
aic_dev->cur.offset );
}
}
- size += sprintf(BLS, " Transinfo settings: ");
- size += sprintf(BLS, "current(%d/%d/%d/%d), ",
+ seq_printf(m, " Transinfo settings: ");
+ seq_printf(m, "current(%d/%d/%d/%d), ",
aic_dev->cur.period,
aic_dev->cur.offset,
aic_dev->cur.width,
aic_dev->cur.options);
- size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
+ seq_printf(m, "goal(%d/%d/%d/%d), ",
aic_dev->goal.period,
aic_dev->goal.offset,
aic_dev->goal.width,
aic_dev->goal.options);
- size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
+ seq_printf(m, "user(%d/%d/%d/%d)\n",
p->user[tindex].period,
p->user[tindex].offset,
p->user[tindex].width,
p->user[tindex].options);
if(sdptr->simple_tags)
{
- size += sprintf(BLS, " Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
+ seq_printf(m, " Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
}
if(aic_dev->barrier_total)
- size += sprintf(BLS, " Total transfers %ld:\n (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
+ seq_printf(m, " Total transfers %ld:\n (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total,
aic_dev->barrier_total, aic_dev->ordered_total);
else
- size += sprintf(BLS, " Total transfers %ld:\n (%ld/%ld reads/writes)\n",
+ seq_printf(m, " Total transfers %ld:\n (%ld/%ld reads/writes)\n",
aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total);
- size += sprintf(BLS, "%s\n", HDRB);
- size += sprintf(BLS, " Reads:");
+ seq_printf(m, "%s\n", HDRB);
+ seq_printf(m, " Reads:");
for (i = 0; i < ARRAY_SIZE(aic_dev->r_bins); i++)
{
- size += sprintf(BLS, " %10ld", aic_dev->r_bins[i]);
+ seq_printf(m, " %10ld", aic_dev->r_bins[i]);
}
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, " Writes:");
+ seq_printf(m, "\n");
+ seq_printf(m, " Writes:");
for (i = 0; i < ARRAY_SIZE(aic_dev->w_bins); i++)
{
- size += sprintf(BLS, " %10ld", aic_dev->w_bins[i]);
+ seq_printf(m, " %10ld", aic_dev->w_bins[i]);
}
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, "\n\n");
- }
- if (size >= aic7xxx_buffer_size)
- {
- printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
- }
-
- if (offset > size - 1)
- {
- kfree(aic7xxx_buffer);
- aic7xxx_buffer = NULL;
- aic7xxx_buffer_size = length = 0;
- *start = NULL;
+ seq_printf(m, "\n");
+ seq_printf(m, "\n\n");
}
- else
- {
- *start = buffer;
- length = min_t(int, length, size - offset);
- memcpy(buffer, &aic7xxx_buffer[offset], length);
- }
-
- return (length);
+ return 0;
}
/*
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
index 64136c56..3307238 100644
--- a/drivers/scsi/aic94xx/aic94xx_dev.c
+++ b/drivers/scsi/aic94xx/aic94xx_dev.c
@@ -84,7 +84,7 @@ static void asd_set_ddb_type(struct domain_device *dev)
struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
int ddb = (int) (unsigned long) dev->lldd_dev;
- if (dev->dev_type == SATA_PM_PORT)
+ if (dev->dev_type == SAS_SATA_PM_PORT)
asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT);
else if (dev->tproto)
asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET);
@@ -116,7 +116,7 @@ void asd_set_dmamode(struct domain_device *dev)
int ddb = (int) (unsigned long) dev->lldd_dev;
u32 qdepth = 0;
- if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) {
+ if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM_PORT) {
if (ata_id_has_ncq(ata_dev->id))
qdepth = ata_id_queue_depth(ata_dev->id);
asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK,
@@ -140,8 +140,8 @@ static int asd_init_sata(struct domain_device *dev)
int ddb = (int) (unsigned long) dev->lldd_dev;
asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF);
- if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
- dev->dev_type == SATA_PM_PORT) {
+ if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM ||
+ dev->dev_type == SAS_SATA_PM_PORT) {
struct dev_to_host_fis *fis = (struct dev_to_host_fis *)
dev->frame_rcvd;
asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status);
@@ -174,7 +174,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask);
if (dev->port->oob_mode != SATA_OOB_MODE) {
flags |= OPEN_REQUIRED;
- if ((dev->dev_type == SATA_DEV) ||
+ if ((dev->dev_type == SAS_SATA_DEV) ||
(dev->tproto & SAS_PROTOCOL_STP)) {
struct smp_resp *rps_resp = &dev->sata_dev.rps_resp;
if (rps_resp->frame_type == SMP_RESPONSE &&
@@ -188,8 +188,8 @@ static int asd_init_target_ddb(struct domain_device *dev)
} else {
flags |= CONCURRENT_CONN_SUPP;
if (!dev->parent &&
- (dev->dev_type == EDGE_DEV ||
- dev->dev_type == FANOUT_DEV))
+ (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE))
asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN,
4);
else
@@ -198,7 +198,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1);
}
}
- if (dev->dev_type == SATA_PM)
+ if (dev->dev_type == SAS_SATA_PM)
flags |= SATA_MULTIPORT;
asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags);
@@ -211,7 +211,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF);
asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF);
- if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+ if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
i = asd_init_sata(dev);
if (i < 0) {
asd_free_ddb(asd_ha, ddb);
@@ -219,7 +219,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
}
}
- if (dev->dev_type == SAS_END_DEV) {
+ if (dev->dev_type == SAS_END_DEVICE) {
struct sas_end_device *rdev = rphy_to_end_device(dev->rphy);
if (rdev->I_T_nexus_loss_timeout > 0)
asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT,
@@ -328,10 +328,10 @@ int asd_dev_found(struct domain_device *dev)
spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
switch (dev->dev_type) {
- case SATA_PM:
+ case SAS_SATA_PM:
res = asd_init_sata_pm_ddb(dev);
break;
- case SATA_PM_PORT:
+ case SAS_SATA_PM_PORT:
res = asd_init_sata_pm_port_ddb(dev);
break;
default:
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index 81b736c..4df867e 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -74,7 +74,7 @@ static void asd_init_phy_identify(struct asd_phy *phy)
memset(phy->identify_frame, 0, sizeof(*phy->identify_frame));
- phy->identify_frame->dev_type = SAS_END_DEV;
+ phy->identify_frame->dev_type = SAS_END_DEVICE;
if (phy->sas_phy.role & PHY_ROLE_INITIATOR)
phy->identify_frame->initiator_bits = phy->sas_phy.iproto;
if (phy->sas_phy.role & PHY_ROLE_TARGET)
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 1c4120c..c56741f 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -85,7 +85,7 @@ static struct scsi_host_template aic94xx_sht = {
.ioctl = sas_ioctl,
};
-static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha)
+static int asd_map_memio(struct asd_ha_struct *asd_ha)
{
int err, i;
struct asd_ha_addrspace *io_handle;
@@ -146,7 +146,7 @@ static void asd_unmap_memio(struct asd_ha_struct *asd_ha)
pci_release_region(asd_ha->pcidev, 0);
}
-static int __devinit asd_map_ioport(struct asd_ha_struct *asd_ha)
+static int asd_map_ioport(struct asd_ha_struct *asd_ha)
{
int i = PCI_IOBAR_OFFSET, err;
struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];
@@ -175,7 +175,7 @@ static void asd_unmap_ioport(struct asd_ha_struct *asd_ha)
pci_release_region(asd_ha->pcidev, PCI_IOBAR_OFFSET);
}
-static int __devinit asd_map_ha(struct asd_ha_struct *asd_ha)
+static int asd_map_ha(struct asd_ha_struct *asd_ha)
{
int err;
u16 cmd_reg;
@@ -221,7 +221,7 @@ static const char *asd_dev_rev[30] = {
[8] = "B0",
};
-static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha)
+static int asd_common_setup(struct asd_ha_struct *asd_ha)
{
int err, i;
@@ -257,7 +257,7 @@ Err:
return err;
}
-static int __devinit asd_aic9410_setup(struct asd_ha_struct *asd_ha)
+static int asd_aic9410_setup(struct asd_ha_struct *asd_ha)
{
int err = asd_common_setup(asd_ha);
@@ -272,7 +272,7 @@ static int __devinit asd_aic9410_setup(struct asd_ha_struct *asd_ha)
return 0;
}
-static int __devinit asd_aic9405_setup(struct asd_ha_struct *asd_ha)
+static int asd_aic9405_setup(struct asd_ha_struct *asd_ha)
{
int err = asd_common_setup(asd_ha);
@@ -531,7 +531,7 @@ static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
static const struct asd_pcidev_struct {
const char * name;
int (*setup)(struct asd_ha_struct *asd_ha);
-} asd_pcidev_data[] __devinitconst = {
+} asd_pcidev_data[] = {
/* Id 0 is used for dynamic ids. */
{ .name = "Adaptec AIC-94xx SAS/SATA Host Adapter",
.setup = asd_aic9410_setup
@@ -731,8 +731,7 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha)
return err;
}
-static int __devinit asd_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int asd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
const struct asd_pcidev_struct *asd_dev;
unsigned asd_id = (unsigned) id->driver_data;
@@ -924,7 +923,7 @@ static void asd_turn_off_leds(struct asd_ha_struct *asd_ha)
}
}
-static void __devexit asd_pci_remove(struct pci_dev *dev)
+static void asd_pci_remove(struct pci_dev *dev)
{
struct asd_ha_struct *asd_ha = pci_get_drvdata(dev);
@@ -1012,7 +1011,7 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
.lldd_ata_set_dmamode = asd_set_dmamode,
};
-static const struct pci_device_id aic94xx_pci_table[] __devinitconst = {
+static const struct pci_device_id aic94xx_pci_table[] = {
{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1},
{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1},
{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1},
@@ -1031,7 +1030,7 @@ static struct pci_driver aic94xx_pci_driver = {
.name = ASD_DRIVER_NAME,
.id_table = aic94xx_pci_table,
.probe = asd_pci_probe,
- .remove = __devexit_p(asd_pci_remove),
+ .remove = asd_pci_remove,
};
static int __init aic94xx_init(void)
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index 393e7ce..59b86e2 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -505,7 +505,8 @@ static int asd_build_ssp_ascb(struct asd_ascb *ascb, struct sas_task *task,
scb->ssp_task.ssp_cmd.efb_prio_attr |= EFB_MASK;
scb->ssp_task.ssp_cmd.efb_prio_attr |= (task->ssp_task.task_prio << 3);
scb->ssp_task.ssp_cmd.efb_prio_attr |= (task->ssp_task.task_attr & 7);
- memcpy(scb->ssp_task.ssp_cmd.cdb, task->ssp_task.cdb, 16);
+ memcpy(scb->ssp_task.ssp_cmd.cdb, task->ssp_task.cmd->cmnd,
+ task->ssp_task.cmd->cmd_len);
scb->ssp_task.sister_scb = cpu_to_le16(0xFFFF);
scb->ssp_task.conn_handle = cpu_to_le16(
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index cf90409..d4c35df 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -184,7 +184,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
struct sas_phy *phy = sas_get_local_phy(dev);
/* Standard mandates link reset for ATA (type 0) and
* hard reset for SSP (type 1) */
- int reset_type = (dev->dev_type == SATA_DEV ||
+ int reset_type = (dev->dev_type == SAS_SATA_DEV ||
(dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE);
diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig
index a8587f1..cfd172a 100644
--- a/drivers/scsi/arm/Kconfig
+++ b/drivers/scsi/arm/Kconfig
@@ -64,19 +64,19 @@ config SCSI_POWERTECSCSI
you have one of these, say Y. If unsure, say N.
comment "The following drivers are not fully supported"
- depends on ARCH_ACORN && EXPERIMENTAL
+ depends on ARCH_ACORN
config SCSI_CUMANA_1
- tristate "CumanaSCSI I support (EXPERIMENTAL)"
- depends on ARCH_ACORN && EXPERIMENTAL && SCSI
+ tristate "CumanaSCSI I support"
+ depends on ARCH_ACORN && SCSI
select SCSI_SPI_ATTRS
help
This enables support for the Cumana SCSI I card. If you have an
Acorn system with one of these, say Y. If unsure, say N.
config SCSI_OAK1
- tristate "Oak SCSI support (EXPERIMENTAL)"
- depends on ARCH_ACORN && EXPERIMENTAL && SCSI
+ tristate "Oak SCSI support"
+ depends on ARCH_ACORN && SCSI
select SCSI_SPI_ATTRS
help
This enables support for the Oak SCSI card. If you have an Acorn
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index b330438..09ba186 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2836,20 +2836,15 @@ char *acornscsi_info(struct Scsi_Host *host)
return string;
}
-int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance)
{
- int pos, begin = 0, devidx;
+ int devidx;
struct scsi_device *scd;
AS_Host *host;
- char *p = buffer;
-
- if (inout == 1)
- return -EINVAL;
host = (AS_Host *)instance->hostdata;
- p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
+ seq_printf(m, "AcornSCSI driver v%d.%d.%d"
#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
" SYNC"
#endif
@@ -2864,14 +2859,14 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
#endif
"\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
- p += sprintf(p, "SBIC: WD33C93A Address: %p IRQ : %d\n",
+ seq_printf(m, "SBIC: WD33C93A Address: %p IRQ : %d\n",
host->base + SBIC_REGIDX, host->scsi.irq);
#ifdef USE_DMAC
- p += sprintf(p, "DMAC: uPC71071 Address: %p IRQ : %d\n\n",
+ seq_printf(m, "DMAC: uPC71071 Address: %p IRQ : %d\n\n",
host->base + DMAC_OFFSET, host->scsi.irq);
#endif
- p += sprintf(p, "Statistics:\n"
+ seq_printf(m, "Statistics:\n"
"Queued commands: %-10u Issued commands: %-10u\n"
"Done commands : %-10u Reads : %-10u\n"
"Writes : %-10u Others : %-10u\n"
@@ -2886,7 +2881,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
for (devidx = 0; devidx < 9; devidx ++) {
unsigned int statptr, prev;
- p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
+ seq_printf(m, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
statptr = host->status_ptr[devidx] - 10;
if ((signed int)statptr < 0)
@@ -2896,7 +2891,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
if (host->status[devidx][statptr].when) {
- p += sprintf(p, "%c%02X:%02X+%2ld",
+ seq_printf(m, "%c%02X:%02X+%2ld",
host->status[devidx][statptr].irq ? '-' : ' ',
host->status[devidx][statptr].ph,
host->status[devidx][statptr].ssr,
@@ -2907,51 +2902,32 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
}
}
- p += sprintf(p, "\nAttached devices:\n");
+ seq_printf(m, "\nAttached devices:\n");
shost_for_each_device(scd, instance) {
- p += sprintf(p, "Device/Lun TaggedQ Sync\n");
- p += sprintf(p, " %d/%d ", scd->id, scd->lun);
+ seq_printf(m, "Device/Lun TaggedQ Sync\n");
+ seq_printf(m, " %d/%d ", scd->id, scd->lun);
if (scd->tagged_supported)
- p += sprintf(p, "%3sabled(%3d) ",
+ seq_printf(m, "%3sabled(%3d) ",
scd->simple_tags ? "en" : "dis",
scd->current_tag);
else
- p += sprintf(p, "unsupported ");
+ seq_printf(m, "unsupported ");
if (host->device[scd->id].sync_xfer & 15)
- p += sprintf(p, "offset %d, %d ns\n",
+ seq_printf(m, "offset %d, %d ns\n",
host->device[scd->id].sync_xfer & 15,
acornscsi_getperiod(host->device[scd->id].sync_xfer));
else
- p += sprintf(p, "async\n");
+ seq_printf(m, "async\n");
- pos = p - buffer;
- if (pos + begin < offset) {
- begin += pos;
- p = buffer;
- }
- pos = p - buffer;
- if (pos + begin > offset + length) {
- scsi_device_put(scd);
- break;
- }
}
-
- pos = p - buffer;
-
- *start = buffer + (offset - begin);
- pos -= offset - begin;
-
- if (pos > length)
- pos = length;
-
- return pos;
+ return 0;
}
static struct scsi_host_template acornscsi_template = {
.module = THIS_MODULE,
- .proc_info = acornscsi_proc_info,
+ .show_info = acornscsi_show_info,
.name = "AcornSCSI",
.info = acornscsi_info,
.queuecommand = acornscsi_queuecmd,
@@ -2965,8 +2941,7 @@ static struct scsi_host_template acornscsi_template = {
.proc_name = "acornscsi",
};
-static int __devinit
-acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
AS_Host *ashost;
@@ -3032,7 +3007,7 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit acornscsi_remove(struct expansion_card *ec)
+static void acornscsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
AS_Host *ashost = (AS_Host *)host->hostdata;
@@ -3063,7 +3038,7 @@ static const struct ecard_id acornscsi_cids[] = {
static struct ecard_driver acornscsi_driver = {
.probe = acornscsi_probe,
- .remove = __devexit_p(acornscsi_remove),
+ .remove = acornscsi_remove,
.id_table = acornscsi_cids,
.drv = {
.name = "acornscsi",
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 2a28b4a..32d2321 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -220,47 +220,21 @@ static const char *arxescsi_info(struct Scsi_Host *host)
return string;
}
-/*
- * Function: int arxescsi_proc_info(char *buffer, char **start, off_t offset,
- * int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- * the /proc filesystem.
- * Params : buffer - a buffer to write information to
- * start - a pointer into this buffer set by this routine to the start
- * of the required information.
- * offset - offset into information that we have read up to.
- * length - length of buffer
- * host_no - host number to return information for
- * inout - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
- */
static int
-arxescsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,
- int inout)
+arxescsi_show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct arxescsi_info *info;
- char *p = buffer;
- int pos;
-
info = (struct arxescsi_info *)host->hostdata;
- if (inout == 1)
- return -EINVAL;
-
- p += sprintf(p, "ARXE 16-bit SCSI driver v%s\n", VERSION);
- p += fas216_print_host(&info->info, p);
- p += fas216_print_stats(&info->info, p);
- p += fas216_print_devices(&info->info, p);
-
- *start = buffer + offset;
- pos = p - buffer - offset;
- if (pos > length)
- pos = length;
- return pos;
+ seq_printf(m, "ARXE 16-bit SCSI driver v%s\n", VERSION);
+ fas216_print_host(&info->info, m);
+ fas216_print_stats(&info->info, m);
+ fas216_print_devices(&info->info, m);
+ return 0;
}
static struct scsi_host_template arxescsi_template = {
- .proc_info = arxescsi_proc_info,
+ .show_info = arxescsi_show_info,
.name = "ARXE SCSI card",
.info = arxescsi_info,
.queuecommand = fas216_noqueue_command,
@@ -276,8 +250,7 @@ static struct scsi_host_template arxescsi_template = {
.proc_name = "arxescsi",
};
-static int __devinit
-arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
struct arxescsi_info *info;
@@ -340,7 +313,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit arxescsi_remove(struct expansion_card *ec)
+static void arxescsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -359,7 +332,7 @@ static const struct ecard_id arxescsi_cids[] = {
static struct ecard_driver arxescsi_driver = {
.probe = arxescsi_probe,
- .remove = __devexit_p(arxescsi_remove),
+ .remove = arxescsi_remove,
.id_table = arxescsi_cids,
.drv = {
.name = "arxescsi",
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index c3b99c9..b679778 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -30,7 +30,6 @@
#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
#define NCR5380_intr cumanascsi_intr
#define NCR5380_queue_command cumanascsi_queue_command
-#define NCR5380_proc_info cumanascsi_proc_info
#define NCR5380_implementation_fields \
unsigned ctrl; \
@@ -225,8 +224,8 @@ static struct scsi_host_template cumanascsi_template = {
.proc_name = "CumanaSCSI-1",
};
-static int __devinit
-cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int cumanascsi1_probe(struct expansion_card *ec,
+ const struct ecard_id *id)
{
struct Scsi_Host *host;
int ret;
@@ -298,7 +297,7 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit cumanascsi1_remove(struct expansion_card *ec)
+static void cumanascsi1_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -320,7 +319,7 @@ static const struct ecard_id cumanascsi1_cids[] = {
static struct ecard_driver cumanascsi1_driver = {
.probe = cumanascsi1_probe,
- .remove = __devexit_p(cumanascsi1_remove),
+ .remove = cumanascsi1_remove,
.id_table = cumanascsi1_cids,
.drv = {
.name = "cumanascsi1",
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 547987b..58915f2 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -337,50 +337,25 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
return ret;
}
-/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset,
- * int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- * the /proc filesystem.
- * Params : buffer - a buffer to write information to
- * start - a pointer into this buffer set by this routine to the start
- * of the required information.
- * offset - offset into information that we have read up to.
- * length - length of buffer
- * host_no - host number to return information for
- * inout - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
- */
-int cumanascsi_2_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int cumanascsi_2_show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct cumanascsi2_info *info;
- char *p = buffer;
- int pos;
-
- if (inout == 1)
- return cumanascsi_2_set_proc_info(host, buffer, length);
-
info = (struct cumanascsi2_info *)host->hostdata;
- p += sprintf(p, "Cumana SCSI II driver v%s\n", VERSION);
- p += fas216_print_host(&info->info, p);
- p += sprintf(p, "Term : o%s\n",
+ seq_printf(m, "Cumana SCSI II driver v%s\n", VERSION);
+ fas216_print_host(&info->info, m);
+ seq_printf(m, "Term : o%s\n",
info->terms ? "n" : "ff");
- p += fas216_print_stats(&info->info, p);
- p += fas216_print_devices(&info->info, p);
-
- *start = buffer + offset;
- pos = p - buffer - offset;
- if (pos > length)
- pos = length;
-
- return pos;
+ fas216_print_stats(&info->info, m);
+ fas216_print_devices(&info->info, m);
+ return 0;
}
static struct scsi_host_template cumanascsi2_template = {
.module = THIS_MODULE,
- .proc_info = cumanascsi_2_proc_info,
+ .show_info = cumanascsi_2_show_info,
+ .write_info = cumanascsi_2_set_proc_info,
.name = "Cumana SCSI II",
.info = cumanascsi_2_info,
.queuecommand = fas216_queue_command,
@@ -397,8 +372,8 @@ static struct scsi_host_template cumanascsi2_template = {
.proc_name = "cumanascsi2",
};
-static int __devinit
-cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int cumanascsi2_probe(struct expansion_card *ec,
+ const struct ecard_id *id)
{
struct Scsi_Host *host;
struct cumanascsi2_info *info;
@@ -495,7 +470,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit cumanascsi2_remove(struct expansion_card *ec)
+static void cumanascsi2_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
@@ -519,7 +494,7 @@ static const struct ecard_id cumanascsi2_cids[] = {
static struct ecard_driver cumanascsi2_driver = {
.probe = cumanascsi2_probe,
- .remove = __devexit_p(cumanascsi2_remove),
+ .remove = cumanascsi2_remove,
.id_table = cumanascsi2_cids,
.drv = {
.name = "cumanascsi2",
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 968d083..5bf3c0d 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -422,45 +422,20 @@ eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
return ret;
}
-/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
- * int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- * the /proc filesystem.
- * Params : buffer - a buffer to write information to
- * start - a pointer into this buffer set by this routine to the start
- * of the required information.
- * offset - offset into information that we have read up to.
- * length - length of buffer
- * host_no - host number to return information for
- * inout - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
- */
-int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int eesoxscsi_show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct eesoxscsi_info *info;
- char *p = buffer;
- int pos;
-
- if (inout == 1)
- return eesoxscsi_set_proc_info(host, buffer, length);
info = (struct eesoxscsi_info *)host->hostdata;
- p += sprintf(p, "EESOX SCSI driver v%s\n", VERSION);
- p += fas216_print_host(&info->info, p);
- p += sprintf(p, "Term : o%s\n",
+ seq_printf(m, "EESOX SCSI driver v%s\n", VERSION);
+ fas216_print_host(&info->info, m);
+ seq_printf(m, "Term : o%s\n",
info->control & EESOX_TERM_ENABLE ? "n" : "ff");
- p += fas216_print_stats(&info->info, p);
- p += fas216_print_devices(&info->info, p);
-
- *start = buffer + offset;
- pos = p - buffer - offset;
- if (pos > length)
- pos = length;
-
- return pos;
+ fas216_print_stats(&info->info, m);
+ fas216_print_devices(&info->info, m);
+ return 0;
}
static ssize_t eesoxscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
@@ -498,7 +473,8 @@ static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
static struct scsi_host_template eesox_template = {
.module = THIS_MODULE,
- .proc_info = eesoxscsi_proc_info,
+ .show_info = eesoxscsi_show_info,
+ .write_info = eesoxscsi_set_proc_info,
.name = "EESOX SCSI",
.info = eesoxscsi_info,
.queuecommand = fas216_queue_command,
@@ -515,8 +491,7 @@ static struct scsi_host_template eesox_template = {
.proc_name = "eesox",
};
-static int __devinit
-eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
struct eesoxscsi_info *info;
@@ -617,7 +592,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit eesoxscsi_remove(struct expansion_card *ec)
+static void eesoxscsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
@@ -643,7 +618,7 @@ static const struct ecard_id eesoxscsi_cids[] = {
static struct ecard_driver eesoxscsi_driver = {
.probe = eesoxscsi_probe,
- .remove = __devexit_p(eesoxscsi_remove),
+ .remove = eesoxscsi_remove,
.id_table = eesoxscsi_cids,
.drv = {
.name = "eesoxscsi",
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 737554c..b46a6f6 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2958,9 +2958,9 @@ void fas216_release(struct Scsi_Host *host)
queue_free(&info->queues.issue);
}
-int fas216_print_host(FAS216_Info *info, char *buffer)
+void fas216_print_host(FAS216_Info *info, struct seq_file *m)
{
- return sprintf(buffer,
+ seq_printf(m,
"\n"
"Chip : %s\n"
" Address: 0x%p\n"
@@ -2970,11 +2970,9 @@ int fas216_print_host(FAS216_Info *info, char *buffer)
info->scsi.irq, info->scsi.dma);
}
-int fas216_print_stats(FAS216_Info *info, char *buffer)
+void fas216_print_stats(FAS216_Info *info, struct seq_file *m)
{
- char *p = buffer;
-
- p += sprintf(p, "\n"
+ seq_printf(m, "\n"
"Command Statistics:\n"
" Queued : %u\n"
" Issued : %u\n"
@@ -2991,38 +2989,33 @@ int fas216_print_stats(FAS216_Info *info, char *buffer)
info->stats.writes, info->stats.miscs,
info->stats.disconnects, info->stats.aborts,
info->stats.bus_resets, info->stats.host_resets);
-
- return p - buffer;
}
-int fas216_print_devices(FAS216_Info *info, char *buffer)
+void fas216_print_devices(FAS216_Info *info, struct seq_file *m)
{
struct fas216_device *dev;
struct scsi_device *scd;
- char *p = buffer;
- p += sprintf(p, "Device/Lun TaggedQ Parity Sync\n");
+ seq_printf(m, "Device/Lun TaggedQ Parity Sync\n");
shost_for_each_device(scd, info->host) {
dev = &info->device[scd->id];
- p += sprintf(p, " %d/%d ", scd->id, scd->lun);
+ seq_printf(m, " %d/%d ", scd->id, scd->lun);
if (scd->tagged_supported)
- p += sprintf(p, "%3sabled(%3d) ",
+ seq_printf(m, "%3sabled(%3d) ",
scd->simple_tags ? "en" : "dis",
scd->current_tag);
else
- p += sprintf(p, "unsupported ");
+ seq_printf(m, "unsupported ");
- p += sprintf(p, "%3sabled ", dev->parity_enabled ? "en" : "dis");
+ seq_printf(m, "%3sabled ", dev->parity_enabled ? "en" : "dis");
if (dev->sof)
- p += sprintf(p, "offset %d, %d ns\n",
+ seq_printf(m, "offset %d, %d ns\n",
dev->sof, dev->period * 4);
else
- p += sprintf(p, "async\n");
+ seq_printf(m, "async\n");
}
-
- return p - buffer;
}
EXPORT_SYMBOL(fas216_init);
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
index df2e1b3..c57c16e 100644
--- a/drivers/scsi/arm/fas216.h
+++ b/drivers/scsi/arm/fas216.h
@@ -358,9 +358,9 @@ extern void fas216_remove (struct Scsi_Host *instance);
*/
extern void fas216_release (struct Scsi_Host *instance);
-extern int fas216_print_host(FAS216_Info *info, char *buffer);
-extern int fas216_print_stats(FAS216_Info *info, char *buffer);
-extern int fas216_print_devices(FAS216_Info *info, char *buffer);
+extern void fas216_print_host(FAS216_Info *info, struct seq_file *m);
+extern void fas216_print_stats(FAS216_Info *info, struct seq_file *m);
+extern void fas216_print_devices(FAS216_Info *info, struct seq_file *m);
/* Function: int fas216_eh_abort(struct scsi_cmnd *SCpnt)
* Purpose : abort this command
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index fc6a5aa..4266eef 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -31,7 +31,8 @@
#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2))
#define NCR5380_intr oakscsi_intr
#define NCR5380_queue_command oakscsi_queue_command
-#define NCR5380_proc_info oakscsi_proc_info
+#define NCR5380_show_info oakscsi_show_info
+#define NCR5380_write_info oakscsi_write_info
#define NCR5380_implementation_fields \
void __iomem *base
@@ -115,7 +116,8 @@ printk("reading %p len %d\n", addr, len);
static struct scsi_host_template oakscsi_template = {
.module = THIS_MODULE,
- .proc_info = oakscsi_proc_info,
+ .show_info = oakscsi_show_info,
+ .write_info = oakscsi_write_info,
.name = "Oak 16-bit SCSI",
.info = oakscsi_info,
.queuecommand = oakscsi_queue_command,
@@ -129,8 +131,7 @@ static struct scsi_host_template oakscsi_template = {
.proc_name = "oakscsi",
};
-static int __devinit
-oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
int ret = -ENOMEM;
@@ -182,7 +183,7 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit oakscsi_remove(struct expansion_card *ec)
+static void oakscsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -202,7 +203,7 @@ static const struct ecard_id oakscsi_cids[] = {
static struct ecard_driver oakscsi_driver = {
.probe = oakscsi_probe,
- .remove = __devexit_p(oakscsi_remove),
+ .remove = oakscsi_remove,
.id_table = oakscsi_cids,
.drv = {
.name = "oakscsi",
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 9274c06..abc9593 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -237,32 +237,20 @@ powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
* inout - 0 for reading, 1 for writing.
* Returns : length of data written to buffer.
*/
-int powertecscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int powertecscsi_show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct powertec_info *info;
- char *p = buffer;
- int pos;
-
- if (inout == 1)
- return powertecscsi_set_proc_info(host, buffer, length);
info = (struct powertec_info *)host->hostdata;
- p += sprintf(p, "PowerTec SCSI driver v%s\n", VERSION);
- p += fas216_print_host(&info->info, p);
- p += sprintf(p, "Term : o%s\n",
+ seq_printf(m, "PowerTec SCSI driver v%s\n", VERSION);
+ fas216_print_host(&info->info, m);
+ seq_printf(m, "Term : o%s\n",
info->term_ctl ? "n" : "ff");
- p += fas216_print_stats(&info->info, p);
- p += fas216_print_devices(&info->info, p);
-
- *start = buffer + offset;
- pos = p - buffer - offset;
- if (pos > length)
- pos = length;
-
- return pos;
+ fas216_print_stats(&info->info, m);
+ fas216_print_devices(&info->info, m);
+ return 0;
}
static ssize_t powertecscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
@@ -291,7 +279,8 @@ static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
static struct scsi_host_template powertecscsi_template = {
.module = THIS_MODULE,
- .proc_info = powertecscsi_proc_info,
+ .show_info = powertecscsi_show_info,
+ .write_info = powertecscsi_set_proc_info,
.name = "PowerTec SCSI",
.info = powertecscsi_info,
.queuecommand = fas216_queue_command,
@@ -309,8 +298,8 @@ static struct scsi_host_template powertecscsi_template = {
.proc_name = "powertec",
};
-static int __devinit
-powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int powertecscsi_probe(struct expansion_card *ec,
+ const struct ecard_id *id)
{
struct Scsi_Host *host;
struct powertec_info *info;
@@ -409,7 +398,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
return ret;
}
-static void __devexit powertecscsi_remove(struct expansion_card *ec)
+static void powertecscsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
struct powertec_info *info = (struct powertec_info *)host->hostdata;
@@ -435,7 +424,7 @@ static const struct ecard_id powertecscsi_cids[] = {
static struct ecard_driver powertecscsi_driver = {
.probe = powertecscsi_probe,
- .remove = __devexit_p(powertecscsi_remove),
+ .remove = powertecscsi_remove,
.id_table = powertecscsi_cids,
.drv = {
.name = "powertecscsi",
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 2db79b4..0f3cdbc 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -719,119 +719,94 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
* Inputs : instance, pointer to this instance.
*/
-static void NCR5380_print_status(struct Scsi_Host *instance)
+static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
{
- char *pr_bfr;
- char *start;
- int len;
-
- NCR_PRINT(NDEBUG_ANY);
- NCR_PRINT_PHASE(NDEBUG_ANY);
-
- pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
- if (!pr_bfr) {
- printk("NCR5380_print_status: no memory for print buffer\n");
- return;
- }
- len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
- pr_bfr[len] = 0;
- printk("\n%s\n", pr_bfr);
- free_page((unsigned long)pr_bfr);
+ int i, s;
+ unsigned char *command;
+ printk("scsi%d: destination target %d, lun %d\n",
+ H_NO(cmd), cmd->device->id, cmd->device->lun);
+ printk(KERN_CONT " command = ");
+ command = cmd->cmnd;
+ printk(KERN_CONT "%2d (0x%02x)", command[0], command[0]);
+ for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+ printk(KERN_CONT " %02x", command[i]);
+ printk("\n");
}
-
-/******************************************/
-/*
- * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
- *
- * Return the number of bytes read from or written
-*/
-
-#undef SPRINTF
-#define SPRINTF(fmt,args...) \
- do { \
- if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
- pos += sprintf(pos, fmt , ## args); \
- } while(0)
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-
-static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
- char **start, off_t offset, int length, int inout)
+static void NCR5380_print_status(struct Scsi_Host *instance)
{
- char *pos = buffer;
struct NCR5380_hostdata *hostdata;
Scsi_Cmnd *ptr;
unsigned long flags;
- off_t begin = 0;
-#define check_offset() \
- do { \
- if (pos - buffer < offset - begin) { \
- begin += pos - buffer; \
- pos = buffer; \
- } \
- } while (0)
+
+ NCR_PRINT(NDEBUG_ANY);
+ NCR_PRINT_PHASE(NDEBUG_ANY);
hostdata = (struct NCR5380_hostdata *)instance->hostdata;
- if (inout) /* Has data been written to the file ? */
- return -ENOSYS; /* Currently this is a no-op */
- SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
- check_offset();
+ printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
local_irq_save(flags);
- SPRINTF("NCR5380: coroutine is%s running.\n",
+ printk("NCR5380: coroutine is%s running.\n",
main_running ? "" : "n't");
- check_offset();
if (!hostdata->connected)
- SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+ printk("scsi%d: no currently connected command\n", HOSTNO);
else
- pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
- pos, buffer, length);
- SPRINTF("scsi%d: issue_queue\n", HOSTNO);
- check_offset();
- for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
- pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
- check_offset();
- }
+ lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
+ printk("scsi%d: issue_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ lprint_Scsi_Cmnd(ptr);
- SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
- check_offset();
+ printk("scsi%d: disconnected_queue\n", HOSTNO);
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
- ptr = NEXT(ptr)) {
- pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
- check_offset();
- }
+ ptr = NEXT(ptr))
+ lprint_Scsi_Cmnd(ptr);
local_irq_restore(flags);
- *start = buffer + (offset - begin);
- if (pos - buffer < offset - begin)
- return 0;
- else if (pos - buffer - (offset - begin) < length)
- return pos - buffer - (offset - begin);
- return length;
+ printk("\n");
}
-static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
{
int i, s;
unsigned char *command;
- SPRINTF("scsi%d: destination target %d, lun %d\n",
+ seq_printf(m, "scsi%d: destination target %d, lun %d\n",
H_NO(cmd), cmd->device->id, cmd->device->lun);
- SPRINTF(" command = ");
+ seq_printf(m, " command = ");
command = cmd->cmnd;
- SPRINTF("%2d (0x%02x)", command[0], command[0]);
+ seq_printf(m, "%2d (0x%02x)", command[0], command[0]);
for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
- SPRINTF(" %02x", command[i]);
- SPRINTF("\n");
- return pos;
+ seq_printf(m, " %02x", command[i]);
+ seq_printf(m, "\n");
}
+static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+ struct NCR5380_hostdata *hostdata;
+ Scsi_Cmnd *ptr;
+ unsigned long flags;
+
+ hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+ seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+ local_irq_save(flags);
+ seq_printf(m, "NCR5380: coroutine is%s running.\n",
+ main_running ? "" : "n't");
+ if (!hostdata->connected)
+ seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
+ else
+ show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+ seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ show_Scsi_Cmnd(ptr, m);
+
+ seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+ ptr = NEXT(ptr))
+ show_Scsi_Cmnd(ptr, m);
+
+ local_irq_restore(flags);
+ return 0;
+}
/*
* Function : void NCR5380_init (struct Scsi_Host *instance)
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index df740cb..a3e6c8a 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -1100,7 +1100,7 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
#include "atari_NCR5380.c"
static struct scsi_host_template driver_template = {
- .proc_info = atari_scsi_proc_info,
+ .show_info = atari_scsi_show_info,
.name = "Atari native SCSI",
.detect = atari_scsi_detect,
.release = atari_scsi_release,
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index bd52df7..11c624b 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -47,7 +47,7 @@
#define NCR5380_intr atari_scsi_intr
#define NCR5380_queue_command atari_scsi_queue_command
#define NCR5380_abort atari_scsi_abort
-#define NCR5380_proc_info atari_scsi_proc_info
+#define NCR5380_show_info atari_scsi_show_info
#define NCR5380_dma_read_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 0)
#define NCR5380_dma_write_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 1)
#define NCR5380_dma_residual(inst) atari_scsi_dma_residual( inst )
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index a540162..15a629d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -3099,38 +3099,14 @@ static const char *atp870u_info(struct Scsi_Host *notused)
return buffer;
}
-#define BLS buffer + len + size
-static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
- char **start, off_t offset, int length, int inout)
+static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
{
- static u8 buff[512];
- int size = 0;
- int len = 0;
- off_t begin = 0;
- off_t pos = 0;
-
- if (inout)
- return -EINVAL;
- if (offset == 0)
- memset(buff, 0, sizeof(buff));
- size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
- len += size;
- pos = begin + len;
- size = 0;
-
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, "Adapter Configuration:\n");
- size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port);
- size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
- len += size;
- pos = begin + len;
-
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin); /* Start slop */
- if (len > length) {
- len = length; /* Ending slop */
- }
- return (len);
+ seq_printf(m, "ACARD AEC-671X Driver Version: 2.6+ac\n");
+ seq_printf(m, "\n");
+ seq_printf(m, "Adapter Configuration:\n");
+ seq_printf(m, " Base IO: %#.4lx\n", HBAptr->io_port);
+ seq_printf(m, " IRQ: %d\n", HBAptr->irq);
+ return 0;
}
@@ -3177,7 +3153,7 @@ static struct scsi_host_template atp870u_template = {
.module = THIS_MODULE,
.name = "atp870u" /* name */,
.proc_name = "atp870u",
- .proc_info = atp870u_proc_info,
+ .show_info = atp870u_show_info,
.info = atp870u_info /* info */,
.queuecommand = atp870u_queuecommand /* queuecommand */,
.eh_abort_handler = atp870u_abort /* abort */,
@@ -3210,7 +3186,7 @@ static struct pci_driver atp870u_driver = {
.id_table = atp870u_id_table,
.name = "atp870u",
.probe = atp870u_probe,
- .remove = __devexit_p(atp870u_remove),
+ .remove = atp870u_remove,
};
static int __init atp870u_init(void)
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index f1733df..777e7c0 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 5c87768..e66aa7c 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -155,6 +155,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
uint16_t status = 0, addl_status = 0, wrb_num = 0;
struct be_mcc_wrb *temp_wrb;
struct be_cmd_req_hdr *ioctl_hdr;
+ struct be_cmd_resp_hdr *ioctl_resp_hdr;
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
if (beiscsi_error(phba))
@@ -204,6 +205,12 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
ioctl_hdr->subsystem,
ioctl_hdr->opcode,
status, addl_status);
+
+ if (status == MCC_STATUS_INSUFFICIENT_BUFFER) {
+ ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr;
+ if (ioctl_resp_hdr->response_length)
+ goto release_mcc_tag;
+ }
rc = -EAGAIN;
}
@@ -267,6 +274,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
struct be_cmd_req_hdr *hdr = embedded_payload(wrb);
+ struct be_cmd_resp_hdr *resp_hdr;
be_dws_le_to_cpu(compl, 4);
@@ -284,6 +292,11 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
hdr->subsystem, hdr->opcode,
compl_status, extd_status);
+ if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) {
+ resp_hdr = (struct be_cmd_resp_hdr *) hdr;
+ if (resp_hdr->response_length)
+ return 0;
+ }
return -EBUSY;
}
return 0;
@@ -335,30 +348,26 @@ static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session)
void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
struct be_async_event_link_state *evt)
{
- switch (evt->port_link_status) {
- case ASYNC_EVENT_LINK_DOWN:
+ if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) ||
+ ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
+ (evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) {
+ phba->state = BE_ADAPTER_LINK_DOWN;
+
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
- "BC_%d : Link Down on Physical Port %d\n",
+ "BC_%d : Link Down on Port %d\n",
evt->physical_port);
- phba->state |= BE_ADAPTER_LINK_DOWN;
iscsi_host_for_each_session(phba->shost,
be2iscsi_fail_session);
- break;
- case ASYNC_EVENT_LINK_UP:
+ } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) ||
+ ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
+ (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) {
phba->state = BE_ADAPTER_UP;
+
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
- "BC_%d : Link UP on Physical Port %d\n",
- evt->physical_port);
- break;
- default:
- beiscsi_log(phba, KERN_ERR,
- BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
- "BC_%d : Unexpected Async Notification %d on"
- "Physical Port %d\n",
- evt->port_link_status,
+ "BC_%d : Link UP on Port %d\n",
evt->physical_port);
}
}
@@ -479,7 +488,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
{
void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
- int wait = 0;
+ uint32_t wait = 0;
u32 ready;
do {
@@ -527,6 +536,10 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
struct be_mcc_compl *compl = &mbox->compl;
struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+ status = be_mbox_db_ready_wait(ctrl);
+ if (status)
+ return status;
+
val &= ~MPU_MAILBOX_DB_RDY_MASK;
val |= MPU_MAILBOX_DB_HI_MASK;
val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
@@ -580,6 +593,10 @@ static int be_mbox_notify_wait(struct beiscsi_hba *phba)
struct be_mcc_compl *compl = &mbox->compl;
struct be_ctrl_info *ctrl = &phba->ctrl;
+ status = be_mbox_db_ready_wait(ctrl);
+ if (status)
+ return status;
+
val |= MPU_MAILBOX_DB_HI_MASK;
/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
@@ -732,6 +749,16 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
return status;
}
+/**
+ * be_cmd_fw_initialize()- Initialize FW
+ * @ctrl: Pointer to function control structure
+ *
+ * Send FW initialize pattern for the function.
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero value
+ **/
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
{
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
@@ -762,6 +789,47 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
return status;
}
+/**
+ * be_cmd_fw_uninit()- Uinitialize FW
+ * @ctrl: Pointer to function control structure
+ *
+ * Send FW uninitialize pattern for the function
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero value
+ **/
+int be_cmd_fw_uninit(struct be_ctrl_info *ctrl)
+{
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+ int status;
+ u8 *endian_check;
+
+ spin_lock(&ctrl->mbox_lock);
+ memset(wrb, 0, sizeof(*wrb));
+
+ endian_check = (u8 *) wrb;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xAA;
+ *endian_check++ = 0xBB;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xCC;
+ *endian_check++ = 0xDD;
+ *endian_check = 0xFF;
+
+ be_dws_cpu_to_le(wrb, sizeof(*wrb));
+
+ status = be_mbox_notify(ctrl);
+ if (status)
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+ "BC_%d : be_cmd_fw_uninit Failed\n");
+
+ spin_unlock(&ctrl->mbox_lock);
+ return status;
+}
+
int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *cq, struct be_queue_info *eq,
bool sol_evts, bool no_delay, int coalesce_wm)
@@ -783,20 +851,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
OPCODE_COMMON_CQ_CREATE, sizeof(*req));
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
- if (chip_skh_r(ctrl->pdev)) {
- req->hdr.version = MBX_CMD_VER2;
- req->page_size = 1;
- AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
- ctxt, coalesce_wm);
- AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
- ctxt, no_delay);
- AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
- __ilog2_u32(cq->len / 256));
- AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
- AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
- AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
- AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
- } else {
+ if (is_chip_be2_be3r(phba)) {
AMAP_SET_BITS(struct amap_cq_context, coalescwm,
ctxt, coalesce_wm);
AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
@@ -809,6 +864,19 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
PCI_FUNC(ctrl->pdev->devfn));
+ } else {
+ req->hdr.version = MBX_CMD_VER2;
+ req->page_size = 1;
+ AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+ ctxt, coalesce_wm);
+ AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
+ ctxt, no_delay);
+ AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
+ __ilog2_u32(cq->len / 256));
+ AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
+ AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
+ AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
+ AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
}
be_dws_cpu_to_le(ctxt, sizeof(req->context));
@@ -949,6 +1017,7 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_defq_create_req *req = embedded_payload(wrb);
struct be_dma_mem *q_mem = &dq->dma_mem;
+ struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
void *ctxt = &req->context;
int status;
@@ -961,17 +1030,36 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
- AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0);
- AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt,
- 1);
- AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt,
- PCI_FUNC(ctrl->pdev->devfn));
- AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt,
- be_encoded_q_len(length / sizeof(struct phys_addr)));
- AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size,
- ctxt, entry_size);
- AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt,
- cq->id);
+
+ if (is_chip_be2_be3r(phba)) {
+ AMAP_SET_BITS(struct amap_be_default_pdu_context,
+ rx_pdid, ctxt, 0);
+ AMAP_SET_BITS(struct amap_be_default_pdu_context,
+ rx_pdid_valid, ctxt, 1);
+ AMAP_SET_BITS(struct amap_be_default_pdu_context,
+ pci_func_id, ctxt, PCI_FUNC(ctrl->pdev->devfn));
+ AMAP_SET_BITS(struct amap_be_default_pdu_context,
+ ring_size, ctxt,
+ be_encoded_q_len(length /
+ sizeof(struct phys_addr)));
+ AMAP_SET_BITS(struct amap_be_default_pdu_context,
+ default_buffer_size, ctxt, entry_size);
+ AMAP_SET_BITS(struct amap_be_default_pdu_context,
+ cq_id_recv, ctxt, cq->id);
+ } else {
+ AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+ rx_pdid, ctxt, 0);
+ AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+ rx_pdid_valid, ctxt, 1);
+ AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+ ring_size, ctxt,
+ be_encoded_q_len(length /
+ sizeof(struct phys_addr)));
+ AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+ default_buffer_size, ctxt, entry_size);
+ AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+ cq_id_recv, ctxt, cq->id);
+ }
be_dws_cpu_to_le(ctxt, sizeof(req->context));
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 23397d5..9907308 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -52,6 +52,10 @@ struct be_mcc_wrb {
/* Completion Status */
#define MCC_STATUS_SUCCESS 0x0
+#define MCC_STATUS_FAILED 0x1
+#define MCC_STATUS_ILLEGAL_REQUEST 0x2
+#define MCC_STATUS_ILLEGAL_FIELD 0x3
+#define MCC_STATUS_INSUFFICIENT_BUFFER 0x4
#define CQE_STATUS_COMPL_MASK 0xFFFF
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
@@ -118,7 +122,8 @@ struct be_async_event_trailer {
enum {
ASYNC_EVENT_LINK_DOWN = 0x0,
- ASYNC_EVENT_LINK_UP = 0x1
+ ASYNC_EVENT_LINK_UP = 0x1,
+ ASYNC_EVENT_LOGICAL = 0x2
};
/**
@@ -130,6 +135,9 @@ struct be_async_event_link_state {
u8 port_link_status;
u8 port_duplex;
u8 port_speed;
+#define BEISCSI_PHY_LINK_FAULT_NONE 0x00
+#define BEISCSI_PHY_LINK_FAULT_LOCAL 0x01
+#define BEISCSI_PHY_LINK_FAULT_REMOTE 0x02
u8 port_fault;
u8 rsvd0[7];
struct be_async_event_trailer trailer;
@@ -697,6 +705,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va);
/*ISCSI Functuions */
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
+int be_cmd_fw_uninit(struct be_ctrl_info *ctrl);
struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba);
@@ -751,6 +760,18 @@ struct amap_be_default_pdu_context {
u8 rsvd4[32]; /* dword 3 */
} __packed;
+struct amap_default_pdu_context_ext {
+ u8 rsvd0[16]; /* dword 0 */
+ u8 ring_size[4]; /* dword 0 */
+ u8 rsvd1[12]; /* dword 0 */
+ u8 rsvd2[22]; /* dword 1 */
+ u8 rx_pdid[9]; /* dword 1 */
+ u8 rx_pdid_valid; /* dword 1 */
+ u8 default_buffer_size[16]; /* dword 2 */
+ u8 cq_id_recv[16]; /* dword 2 */
+ u8 rsvd3[32]; /* dword 3 */
+} __packed;
+
struct be_defq_create_req {
struct be_cmd_req_hdr hdr;
u16 num_pages;
@@ -896,7 +917,7 @@ struct amap_it_dmsg_cqe_v2 {
* stack to notify the
* controller of a posted Work Request Block
*/
-#define DB_WRB_POST_CID_MASK 0x3FF /* bits 0 - 9 */
+#define DB_WRB_POST_CID_MASK 0xFFFF /* bits 0 - 16 */
#define DB_DEF_PDU_WRB_INDEX_MASK 0xFF /* bits 0 - 9 */
#define DB_DEF_PDU_WRB_INDEX_SHIFT 16
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 214d691..ef36be00 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -161,7 +161,9 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
struct beiscsi_conn *beiscsi_conn,
unsigned int cid)
{
- if (phba->conn_table[cid]) {
+ uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
+
+ if (phba->conn_table[cri_index]) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Connection table already occupied. Detected clash\n");
@@ -169,9 +171,9 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
} else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n",
- cid, beiscsi_conn);
+ cri_index, beiscsi_conn);
- phba->conn_table[cid] = beiscsi_conn;
+ phba->conn_table[cri_index] = beiscsi_conn;
}
return 0;
}
@@ -369,7 +371,7 @@ beiscsi_set_vlan_tag(struct Scsi_Host *shost,
break;
default:
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
- "BS_%d : Unkown Param Type : %d\n",
+ "BS_%d : Unknown Param Type : %d\n",
iface_param->param);
return -ENOSYS;
}
@@ -990,9 +992,27 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
{
struct beiscsi_hba *phba = beiscsi_ep->phba;
+ struct beiscsi_conn *beiscsi_conn;
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
beiscsi_ep->phba = NULL;
+ phba->ep_array[BE_GET_CRI_FROM_CID
+ (beiscsi_ep->ep_cid)] = NULL;
+
+ /**
+ * Check if any connection resource allocated by driver
+ * is to be freed.This case occurs when target redirection
+ * or connection retry is done.
+ **/
+ if (!beiscsi_ep->conn)
+ return;
+
+ beiscsi_conn = beiscsi_ep->conn;
+ if (beiscsi_conn->login_in_progress) {
+ beiscsi_free_mgmt_task_handles(beiscsi_conn,
+ beiscsi_conn->task);
+ beiscsi_conn->login_in_progress = 0;
+ }
}
/**
@@ -1009,7 +1029,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
{
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
struct beiscsi_hba *phba = beiscsi_ep->phba;
- struct be_mcc_wrb *wrb;
struct tcp_connect_and_offload_out *ptcpcnct_out;
struct be_dma_mem nonemb_cmd;
unsigned int tag;
@@ -1029,15 +1048,8 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
"BS_%d : In beiscsi_open_conn, ep_cid=%d\n",
beiscsi_ep->ep_cid);
- phba->ep_array[beiscsi_ep->ep_cid -
- phba->fw_config.iscsi_cid_start] = ep;
- if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
- phba->params.cxns_per_ctrl * 2)) {
-
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
- "BS_%d : Failed in allocate iscsi cid\n");
- goto free_ep;
- }
+ phba->ep_array[BE_GET_CRI_FROM_CID
+ (beiscsi_ep->ep_cid)] = ep;
beiscsi_ep->cid_vld = 0;
nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
@@ -1049,24 +1061,24 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
"BS_%d : Failed to allocate memory for"
" mgmt_open_connection\n");
- beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
+ beiscsi_free_ep(beiscsi_ep);
return -ENOMEM;
}
nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
memset(nonemb_cmd.va, 0, nonemb_cmd.size);
tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
- if (!tag) {
+ if (tag <= 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : mgmt_open_connection Failed for cid=%d\n",
beiscsi_ep->ep_cid);
- beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
+ beiscsi_free_ep(beiscsi_ep);
return -EAGAIN;
}
- ret = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+ ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
if (ret) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
@@ -1074,10 +1086,11 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
- goto free_ep;
+ beiscsi_free_ep(beiscsi_ep);
+ return -EBUSY;
}
- ptcpcnct_out = embedded_payload(wrb);
+ ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va;
beiscsi_ep = ep->dd_data;
beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
beiscsi_ep->cid_vld = 1;
@@ -1087,10 +1100,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return 0;
-
-free_ep:
- beiscsi_free_ep(beiscsi_ep);
- return -EBUSY;
}
/**
@@ -1119,6 +1128,13 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
return ERR_PTR(ret);
}
+ if (beiscsi_error(phba)) {
+ ret = -EIO;
+ beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+ "BS_%d : The FW state Not Stable!!!\n");
+ return ERR_PTR(ret);
+ }
+
if (phba->state != BE_ADAPTER_UP) {
ret = -EBUSY;
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
@@ -1201,8 +1217,10 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
unsigned int cid)
{
- if (phba->conn_table[cid])
- phba->conn_table[cid] = NULL;
+ uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
+
+ if (phba->conn_table[cri_index])
+ phba->conn_table[cri_index] = NULL;
else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : Connection table Not occupied.\n");
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index 38eab72..31ddc84 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 48d37dd..a1f5ac7 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -153,10 +153,14 @@ BEISCSI_RW_ATTR(log_enable, 0x00,
DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL);
DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL);
+DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL);
+DEVICE_ATTR(beiscsi_active_cid_count, S_IRUGO, beiscsi_active_cid_disp, NULL);
struct device_attribute *beiscsi_attrs[] = {
&dev_attr_beiscsi_log_enable,
&dev_attr_beiscsi_drvr_ver,
&dev_attr_beiscsi_adapter_family,
+ &dev_attr_beiscsi_fw_ver,
+ &dev_attr_beiscsi_active_cid_count,
NULL,
};
@@ -702,7 +706,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba)
+ BE2_TMFS
+ BE2_NOPOUT_REQ));
phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count;
- phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2;
+ phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count;
phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;
phba->params.num_sge_per_io = BE2_SGE;
phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
@@ -1032,7 +1036,6 @@ static void hwi_ring_cq_db(struct beiscsi_hba *phba,
static unsigned int
beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_hba *phba,
- unsigned short cid,
struct pdu_base *ppdu,
unsigned long pdu_len,
void *pbuffer, unsigned long buf_len)
@@ -1144,9 +1147,10 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
+ uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
phwi_ctrlr = phba->phwi_ctrlr;
- pwrb_context = &phwi_ctrlr->wrb_context[cid];
+ pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
if (pwrb_context->wrb_handles_available >= 2) {
pwrb_handle = pwrb_context->pwrb_handle_base[
pwrb_context->alloc_index];
@@ -1322,8 +1326,9 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
hdr->t2retain = 0;
hdr->flags = csol_cqe->i_flags;
hdr->response = csol_cqe->i_resp;
- hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
- hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1);
+ hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+ hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn +
+ csol_cqe->cmd_wnd - 1);
hdr->dlength[0] = 0;
hdr->dlength[1] = 0;
@@ -1346,9 +1351,9 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
hdr->flags = csol_cqe->i_flags;
hdr->response = csol_cqe->i_resp;
- hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
- hdr->max_cmdsn = (csol_cqe->exp_cmdsn +
- csol_cqe->cmd_wnd - 1);
+ hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+ hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn +
+ csol_cqe->cmd_wnd - 1);
hdr->itt = io_task->libiscsi_itt;
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -1363,35 +1368,29 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
struct hwi_controller *phwi_ctrlr;
struct iscsi_task *task;
struct beiscsi_io_task *io_task;
- struct iscsi_conn *conn = beiscsi_conn->conn;
- struct iscsi_session *session = conn->session;
- uint16_t wrb_index, cid;
+ uint16_t wrb_index, cid, cri_index;
phwi_ctrlr = phba->phwi_ctrlr;
- if (chip_skh_r(phba->pcidev)) {
- wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+ if (is_chip_be2_be3r(phba)) {
+ wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
wrb_idx, psol);
- cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+ cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
cid, psol);
} else {
- wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+ wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
wrb_idx, psol);
- cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+ cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
cid, psol);
}
- pwrb_context = &phwi_ctrlr->wrb_context[
- cid - phba->fw_config.iscsi_cid_start];
+ cri_index = BE_GET_CRI_FROM_CID(cid);
+ pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];
task = pwrb_handle->pio_handle;
io_task = task->dd_data;
- spin_lock_bh(&phba->mgmt_sgl_lock);
- free_mgmt_sgl_handle(phba, io_task->psgl_handle);
- spin_unlock_bh(&phba->mgmt_sgl_lock);
- spin_lock_bh(&session->lock);
- free_wrb_handle(phba, pwrb_context, pwrb_handle);
- spin_unlock_bh(&session->lock);
+ memset(io_task->pwrb_handle->pwrb, 0, sizeof(struct iscsi_wrb));
+ iscsi_put_task(task);
}
static void
@@ -1406,8 +1405,8 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
hdr = (struct iscsi_nopin *)task->hdr;
hdr->flags = csol_cqe->i_flags;
hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
- hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn +
- csol_cqe->cmd_wnd - 1);
+ hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn +
+ csol_cqe->cmd_wnd - 1);
hdr->opcode = ISCSI_OP_NOOP_IN;
hdr->itt = io_task->libiscsi_itt;
@@ -1418,7 +1417,26 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
struct sol_cqe *psol,
struct common_sol_cqe *csol_cqe)
{
- if (chip_skh_r(phba->pcidev)) {
+ if (is_chip_be2_be3r(phba)) {
+ csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
+ i_exp_cmd_sn, psol);
+ csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
+ i_res_cnt, psol);
+ csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+ i_cmd_wnd, psol);
+ csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
+ wrb_index, psol);
+ csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
+ cid, psol);
+ csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+ hw_sts, psol);
+ csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
+ i_resp, psol);
+ csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+ i_sts, psol);
+ csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
+ i_flags, psol);
+ } else {
csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2,
i_exp_cmd_sn, psol);
csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2,
@@ -1429,7 +1447,7 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
cid, psol);
csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
hw_sts, psol);
- csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+ csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe_v2,
i_cmd_wnd, psol);
if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
cmd_cmpl, psol))
@@ -1445,25 +1463,6 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
o, psol))
csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW;
- } else {
- csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
- i_exp_cmd_sn, psol);
- csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
- i_res_cnt, psol);
- csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
- i_cmd_wnd, psol);
- csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
- wrb_index, psol);
- csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
- cid, psol);
- csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
- hw_sts, psol);
- csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
- i_resp, psol);
- csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
- i_sts, psol);
- csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
- i_flags, psol);
}
}
@@ -1480,14 +1479,15 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
struct iscsi_conn *conn = beiscsi_conn->conn;
struct iscsi_session *session = conn->session;
struct common_sol_cqe csol_cqe = {0};
+ uint16_t cri_index = 0;
phwi_ctrlr = phba->phwi_ctrlr;
/* Copy the elements to a common structure */
adapter_get_sol_cqe(phba, psol, &csol_cqe);
- pwrb_context = &phwi_ctrlr->wrb_context[
- csol_cqe.cid - phba->fw_config.iscsi_cid_start];
+ cri_index = BE_GET_CRI_FROM_CID(csol_cqe.cid);
+ pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
pwrb_handle = pwrb_context->pwrb_handle_basestd[
csol_cqe.wrb_index];
@@ -1561,15 +1561,15 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
unsigned char is_header = 0;
unsigned int index, dpl;
- if (chip_skh_r(phba->pcidev)) {
- dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+ if (is_chip_be2_be3r(phba)) {
+ dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
dpl, pdpdu_cqe);
- index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+ index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
index, pdpdu_cqe);
} else {
- dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+ dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
dpl, pdpdu_cqe);
- index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+ index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
index, pdpdu_cqe);
}
@@ -1613,8 +1613,8 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
WARN_ON(!pasync_handle);
- pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start;
+ pasync_handle->cri =
+ BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid);
pasync_handle->is_header = is_header;
pasync_handle->buffer_len = dpl;
*pcq_index = index;
@@ -1856,8 +1856,6 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
}
status = beiscsi_process_async_pdu(beiscsi_conn, phba,
- (beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start),
phdr, hdr_len, pfirst_buffer,
offset);
@@ -2011,6 +2009,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
unsigned int num_processed = 0;
unsigned int tot_nump = 0;
unsigned short code = 0, cid = 0;
+ uint16_t cri_index = 0;
struct beiscsi_conn *beiscsi_conn;
struct beiscsi_endpoint *beiscsi_ep;
struct iscsi_endpoint *ep;
@@ -2028,7 +2027,9 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
32] & CQE_CODE_MASK);
/* Get the CID */
- if (chip_skh_r(phba->pcidev)) {
+ if (is_chip_be2_be3r(phba)) {
+ cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
+ } else {
if ((code == DRIVERMSG_NOTIFY) ||
(code == UNSOL_HDR_NOTIFY) ||
(code == UNSOL_DATA_NOTIFY))
@@ -2038,10 +2039,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
else
cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
cid, sol);
- } else
- cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
+ }
- ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
+ cri_index = BE_GET_CRI_FROM_CID(cid);
+ ep = phba->ep_array[cri_index];
beiscsi_ep = ep->dd_data;
beiscsi_conn = beiscsi_ep->conn;
@@ -2191,7 +2192,7 @@ void beiscsi_process_all_cqs(struct work_struct *work)
static int be_iopoll(struct blk_iopoll *iop, int budget)
{
- static unsigned int ret;
+ unsigned int ret;
struct beiscsi_hba *phba;
struct be_eq_obj *pbe_eq;
@@ -2416,11 +2417,11 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
/* Check for the data_count */
dsp_value = (task->data_count) ? 1 : 0;
- if (chip_skh_r(phba->pcidev))
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp,
+ if (is_chip_be2_be3r(phba))
+ AMAP_SET_BITS(struct amap_iscsi_wrb, dsp,
pwrb, dsp_value);
else
- AMAP_SET_BITS(struct amap_iscsi_wrb, dsp,
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp,
pwrb, dsp_value);
/* Map addr only if there is data_count */
@@ -2538,8 +2539,9 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
{
- struct be_mem_descriptor *mem_descr;
dma_addr_t bus_add;
+ struct hwi_controller *phwi_ctrlr;
+ struct be_mem_descriptor *mem_descr;
struct mem_array *mem_arr, *mem_arr_orig;
unsigned int i, j, alloc_size, curr_alloc_size;
@@ -2547,9 +2549,18 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
if (!phba->phwi_ctrlr)
return -ENOMEM;
+ /* Allocate memory for wrb_context */
+ phwi_ctrlr = phba->phwi_ctrlr;
+ phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) *
+ phba->params.cxns_per_ctrl,
+ GFP_KERNEL);
+ if (!phwi_ctrlr->wrb_context)
+ return -ENOMEM;
+
phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),
GFP_KERNEL);
if (!phba->init_mem) {
+ kfree(phwi_ctrlr->wrb_context);
kfree(phba->phwi_ctrlr);
return -ENOMEM;
}
@@ -2558,6 +2569,7 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
GFP_KERNEL);
if (!mem_arr_orig) {
kfree(phba->init_mem);
+ kfree(phwi_ctrlr->wrb_context);
kfree(phba->phwi_ctrlr);
return -ENOMEM;
}
@@ -2628,6 +2640,7 @@ free_mem:
}
kfree(mem_arr_orig);
kfree(phba->init_mem);
+ kfree(phba->phwi_ctrlr->wrb_context);
kfree(phba->phwi_ctrlr);
return -ENOMEM;
}
@@ -2666,6 +2679,7 @@ static void iscsi_init_global_templates(struct beiscsi_hba *phba)
static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
{
struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb;
+ struct hwi_context_memory *phwi_ctxt;
struct wrb_handle *pwrb_handle = NULL;
struct hwi_controller *phwi_ctrlr;
struct hwi_wrb_context *pwrb_context;
@@ -2680,7 +2694,18 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
mem_descr_wrb += HWI_MEM_WRB;
phwi_ctrlr = phba->phwi_ctrlr;
- for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+ /* Allocate memory for WRBQ */
+ phwi_ctxt = phwi_ctrlr->phwi_ctxt;
+ phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) *
+ phba->fw_config.iscsi_cid_count,
+ GFP_KERNEL);
+ if (!phwi_ctxt->be_wrbq) {
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+ "BM_%d : WRBQ Mem Alloc Failed\n");
+ return -ENOMEM;
+ }
+
+ for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
pwrb_context = &phwi_ctrlr->wrb_context[index];
pwrb_context->pwrb_handle_base =
kzalloc(sizeof(struct wrb_handle *) *
@@ -2723,7 +2748,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
}
}
idx = 0;
- for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+ for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
pwrb_context = &phwi_ctrlr->wrb_context[index];
if (!num_cxn_wrb) {
pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
@@ -2752,7 +2777,7 @@ init_wrb_hndl_failed:
return -ENOMEM;
}
-static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
+static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
{
struct hwi_controller *phwi_ctrlr;
struct hba_parameters *p = &phba->params;
@@ -2770,6 +2795,15 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
memset(pasync_ctx, 0, sizeof(*pasync_ctx));
+ pasync_ctx->async_entry = kzalloc(sizeof(struct hwi_async_entry) *
+ phba->fw_config.iscsi_cid_count,
+ GFP_KERNEL);
+ if (!pasync_ctx->async_entry) {
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+ "BM_%d : hwi_init_async_pdu_ctx Mem Alloc Failed\n");
+ return -ENOMEM;
+ }
+
pasync_ctx->num_entries = p->asyncpdus_per_ctrl;
pasync_ctx->buffer_size = p->defpdu_hdr_sz;
@@ -2934,6 +2968,8 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
pasync_ctx->async_header.ep_read_ptr = -1;
pasync_ctx->async_data.host_write_ptr = 0;
pasync_ctx->async_data.ep_read_ptr = -1;
+
+ return 0;
}
static int
@@ -3293,6 +3329,7 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
void *wrb_vaddr;
struct be_dma_mem sgl;
struct be_mem_descriptor *mem_descr;
+ struct hwi_wrb_context *pwrb_context;
int status;
idx = 0;
@@ -3351,8 +3388,9 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
kfree(pwrb_arr);
return status;
}
- phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i].
- id;
+ pwrb_context = &phwi_ctrlr->wrb_context[i];
+ pwrb_context->cid = phwi_context->be_wrbq[i].id;
+ BE_SET_CID_TO_CRI(i, pwrb_context->cid);
}
kfree(pwrb_arr);
return 0;
@@ -3365,7 +3403,7 @@ static void free_wrb_handles(struct beiscsi_hba *phba)
struct hwi_wrb_context *pwrb_context;
phwi_ctrlr = phba->phwi_ctrlr;
- for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+ for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
pwrb_context = &phwi_ctrlr->wrb_context[index];
kfree(pwrb_context->pwrb_handle_base);
kfree(pwrb_context->pwrb_handle_basestd);
@@ -3394,6 +3432,7 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
struct be_ctrl_info *ctrl = &phba->ctrl;
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
+ struct hwi_async_pdu_context *pasync_ctx;
int i, eq_num;
phwi_ctrlr = phba->phwi_ctrlr;
@@ -3403,6 +3442,7 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
if (q->created)
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);
}
+ kfree(phwi_context->be_wrbq);
free_wrb_handles(phba);
q = &phwi_context->be_def_hdrq;
@@ -3430,6 +3470,10 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
}
be_mcc_queues_destroy(phba);
+
+ pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
+ kfree(pasync_ctx->async_entry);
+ be_cmd_fw_uninit(ctrl);
}
static int be_mcc_queues_create(struct beiscsi_hba *phba,
@@ -3607,7 +3651,12 @@ static int hwi_init_controller(struct beiscsi_hba *phba)
if (beiscsi_init_wrb_handle(phba))
return -ENOMEM;
- hwi_init_async_pdu_ctx(phba);
+ if (hwi_init_async_pdu_ctx(phba)) {
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+ "BM_%d : hwi_init_async_pdu_ctx failed\n");
+ return -ENOMEM;
+ }
+
if (hwi_init_port(phba) != 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : hwi_init_controller failed\n");
@@ -3637,6 +3686,7 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba)
mem_descr++;
}
kfree(phba->init_mem);
+ kfree(phba->phwi_ctrlr->wrb_context);
kfree(phba->phwi_ctrlr);
}
@@ -3769,7 +3819,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
{
- int i, new_cid;
+ int i;
phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
GFP_KERNEL);
@@ -3780,19 +3830,33 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
return -ENOMEM;
}
phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) *
- phba->params.cxns_per_ctrl * 2, GFP_KERNEL);
+ phba->params.cxns_per_ctrl, GFP_KERNEL);
if (!phba->ep_array) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed to allocate memory in "
"hba_setup_cid_tbls\n");
kfree(phba->cid_array);
+ phba->cid_array = NULL;
return -ENOMEM;
}
- new_cid = phba->fw_config.iscsi_cid_start;
- for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
- phba->cid_array[i] = new_cid;
- new_cid += 2;
+
+ phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) *
+ phba->params.cxns_per_ctrl, GFP_KERNEL);
+ if (!phba->conn_table) {
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+ "BM_%d : Failed to allocate memory in"
+ "hba_setup_cid_tbls\n");
+
+ kfree(phba->cid_array);
+ kfree(phba->ep_array);
+ phba->cid_array = NULL;
+ phba->ep_array = NULL;
+ return -ENOMEM;
}
+
+ for (i = 0; i < phba->params.cxns_per_ctrl; i++)
+ phba->cid_array[i] = phba->phwi_ctrlr->wrb_context[i].cid;
+
phba->avlbl_cids = phba->params.cxns_per_ctrl;
return 0;
}
@@ -4062,6 +4126,53 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
kfree(phba->eh_sgl_hndl_base);
kfree(phba->cid_array);
kfree(phba->ep_array);
+ kfree(phba->conn_table);
+}
+
+/**
+ * beiscsi_free_mgmt_task_handles()- Free driver CXN resources
+ * @beiscsi_conn: ptr to the conn to be cleaned up
+ * @task: ptr to iscsi_task resource to be freed.
+ *
+ * Free driver mgmt resources binded to CXN.
+ **/
+void
+beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
+ struct iscsi_task *task)
+{
+ struct beiscsi_io_task *io_task;
+ struct beiscsi_hba *phba = beiscsi_conn->phba;
+ struct hwi_wrb_context *pwrb_context;
+ struct hwi_controller *phwi_ctrlr;
+ uint16_t cri_index = BE_GET_CRI_FROM_CID(
+ beiscsi_conn->beiscsi_conn_cid);
+
+ phwi_ctrlr = phba->phwi_ctrlr;
+ pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
+
+ io_task = task->dd_data;
+
+ if (io_task->pwrb_handle) {
+ memset(io_task->pwrb_handle->pwrb, 0,
+ sizeof(struct iscsi_wrb));
+ free_wrb_handle(phba, pwrb_context,
+ io_task->pwrb_handle);
+ io_task->pwrb_handle = NULL;
+ }
+
+ if (io_task->psgl_handle) {
+ spin_lock_bh(&phba->mgmt_sgl_lock);
+ free_mgmt_sgl_handle(phba,
+ io_task->psgl_handle);
+ io_task->psgl_handle = NULL;
+ spin_unlock_bh(&phba->mgmt_sgl_lock);
+ }
+
+ if (io_task->mtask_addr)
+ pci_unmap_single(phba->pcidev,
+ io_task->mtask_addr,
+ io_task->mtask_data_count,
+ PCI_DMA_TODEVICE);
}
/**
@@ -4078,10 +4189,11 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
+ uint16_t cri_index = BE_GET_CRI_FROM_CID(
+ beiscsi_conn->beiscsi_conn_cid);
phwi_ctrlr = phba->phwi_ctrlr;
- pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
- - phba->fw_config.iscsi_cid_start];
+ pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
if (io_task->cmd_bhs) {
pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
@@ -4103,27 +4215,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
io_task->psgl_handle = NULL;
}
} else {
- if (!beiscsi_conn->login_in_progress) {
- if (io_task->pwrb_handle) {
- free_wrb_handle(phba, pwrb_context,
- io_task->pwrb_handle);
- io_task->pwrb_handle = NULL;
- }
- if (io_task->psgl_handle) {
- spin_lock(&phba->mgmt_sgl_lock);
- free_mgmt_sgl_handle(phba,
- io_task->psgl_handle);
- spin_unlock(&phba->mgmt_sgl_lock);
- io_task->psgl_handle = NULL;
- }
- if (io_task->mtask_addr) {
- pci_unmap_single(phba->pcidev,
- io_task->mtask_addr,
- io_task->mtask_data_count,
- PCI_DMA_TODEVICE);
- io_task->mtask_addr = 0;
- }
- }
+ if (!beiscsi_conn->login_in_progress)
+ beiscsi_free_mgmt_task_handles(beiscsi_conn, task);
}
}
@@ -4146,15 +4239,14 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
beiscsi_cleanup_task(task);
spin_unlock_bh(&session->lock);
- pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start));
+ pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid);
/* Check for the adapter family */
- if (chip_skh_r(phba->pcidev))
- beiscsi_offload_cxn_v2(params, pwrb_handle);
- else
+ if (is_chip_be2_be3r(phba))
beiscsi_offload_cxn_v0(params, pwrb_handle,
phba->init_mem);
+ else
+ beiscsi_offload_cxn_v2(params, pwrb_handle);
be_dws_le_to_cpu(pwrb_handle->pwrb,
sizeof(struct iscsi_target_context_update_wrb));
@@ -4194,6 +4286,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
itt_t itt;
+ uint16_t cri_index = 0;
struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
dma_addr_t paddr;
@@ -4223,8 +4316,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
goto free_hndls;
}
io_task->pwrb_handle = alloc_wrb_handle(phba,
- beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start);
+ beiscsi_conn->beiscsi_conn_cid);
if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4236,6 +4328,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
} else {
io_task->scsi_cmnd = NULL;
if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
+ beiscsi_conn->task = task;
if (!beiscsi_conn->login_in_progress) {
spin_lock(&phba->mgmt_sgl_lock);
io_task->psgl_handle = (struct sgl_handle *)
@@ -4257,8 +4350,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
io_task->psgl_handle;
io_task->pwrb_handle =
alloc_wrb_handle(phba,
- beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start);
+ beiscsi_conn->beiscsi_conn_cid);
if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO |
@@ -4278,7 +4370,6 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
io_task->pwrb_handle =
beiscsi_conn->plogin_wrb_handle;
}
- beiscsi_conn->task = task;
} else {
spin_lock(&phba->mgmt_sgl_lock);
io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
@@ -4295,8 +4386,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
}
io_task->pwrb_handle =
alloc_wrb_handle(phba,
- beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start);
+ beiscsi_conn->beiscsi_conn_cid);
if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4324,12 +4414,13 @@ free_io_hndls:
free_mgmt_hndls:
spin_lock(&phba->mgmt_sgl_lock);
free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+ io_task->psgl_handle = NULL;
spin_unlock(&phba->mgmt_sgl_lock);
free_hndls:
phwi_ctrlr = phba->phwi_ctrlr;
- pwrb_context = &phwi_ctrlr->wrb_context[
- beiscsi_conn->beiscsi_conn_cid -
- phba->fw_config.iscsi_cid_start];
+ cri_index = BE_GET_CRI_FROM_CID(
+ beiscsi_conn->beiscsi_conn_cid);
+ pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
if (io_task->pwrb_handle)
free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
io_task->pwrb_handle = NULL;
@@ -4351,7 +4442,6 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
unsigned int doorbell = 0;
pwrb = io_task->pwrb_handle->pwrb;
- memset(pwrb, 0, sizeof(*pwrb));
io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
io_task->bhs_len = sizeof(struct be_cmd_bhs);
@@ -4465,19 +4555,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
pwrb = io_task->pwrb_handle->pwrb;
memset(pwrb, 0, sizeof(*pwrb));
- if (chip_skh_r(phba->pcidev)) {
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
- be32_to_cpu(task->cmdsn));
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
- io_task->pwrb_handle->wrb_index);
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
- io_task->psgl_handle->sgl_index);
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
- task->data_count);
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
- io_task->pwrb_handle->nxt_wrb_index);
- pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
- } else {
+ if (is_chip_be2_be3r(phba)) {
AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
be32_to_cpu(task->cmdsn));
AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
@@ -4489,6 +4567,18 @@ static int beiscsi_mtask(struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
io_task->pwrb_handle->nxt_wrb_index);
pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
+ } else {
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
+ be32_to_cpu(task->cmdsn));
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
+ io_task->pwrb_handle->wrb_index);
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
+ io_task->psgl_handle->sgl_index);
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
+ task->data_count);
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
+ io_task->pwrb_handle->nxt_wrb_index);
+ pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
}
@@ -4501,19 +4591,19 @@ static int beiscsi_mtask(struct iscsi_task *task)
case ISCSI_OP_NOOP_OUT:
if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
- if (chip_skh_r(phba->pcidev))
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+ if (is_chip_be2_be3r(phba))
+ AMAP_SET_BITS(struct amap_iscsi_wrb,
dmsg, pwrb, 1);
else
- AMAP_SET_BITS(struct amap_iscsi_wrb,
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
dmsg, pwrb, 1);
} else {
ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset);
- if (chip_skh_r(phba->pcidev))
- AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+ if (is_chip_be2_be3r(phba))
+ AMAP_SET_BITS(struct amap_iscsi_wrb,
dmsg, pwrb, 0);
else
- AMAP_SET_BITS(struct amap_iscsi_wrb,
+ AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
dmsg, pwrb, 0);
}
hwi_write_buffer(pwrb, task);
@@ -4540,9 +4630,9 @@ static int beiscsi_mtask(struct iscsi_task *task)
}
/* Set the task type */
- io_task->wrb_type = (chip_skh_r(phba->pcidev)) ?
- AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb) :
- AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb);
+ io_task->wrb_type = (is_chip_be2_be3r(phba)) ?
+ AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb) :
+ AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb);
doorbell |= cid & DB_WRB_POST_CID_MASK;
doorbell |= (io_task->pwrb_handle->wrb_index &
@@ -4790,8 +4880,8 @@ beiscsi_hw_health_check(struct work_struct *work)
msecs_to_jiffies(1000));
}
-static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
- const struct pci_device_id *id)
+static int beiscsi_dev_probe(struct pci_dev *pcidev,
+ const struct pci_device_id *id)
{
struct beiscsi_hba *phba = NULL;
struct hwi_controller *phwi_ctrlr;
@@ -4834,6 +4924,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
case OC_SKH_ID1:
phba->generation = BE_GEN4;
phba->iotask_fn = beiscsi_iotask_v2;
+ break;
default:
phba->generation = 0;
}
@@ -4905,7 +4996,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq",
phba->shost->host_no);
- phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
+ phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, phba->wq_name);
if (!phba->wq) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe-"
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 5946577..2c06ef3 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -36,7 +36,7 @@
#include "be.h"
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "10.0.272.0"
+#define BUILD_STR "10.0.467.0"
#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@@ -66,8 +66,9 @@
#define MAX_CPUS 64
#define BEISCSI_MAX_NUM_CPUS 7
-#define OC_SKH_MAX_NUM_CPUS 63
+#define OC_SKH_MAX_NUM_CPUS 31
+#define BEISCSI_VER_STRLEN 32
#define BEISCSI_SGLIST_ELEMENTS 30
@@ -265,7 +266,9 @@ struct invalidate_command_table {
unsigned short cid;
} __packed;
-#define chip_skh_r(pdev) (pdev->device == OC_SKH_ID1)
+#define chip_be2(phba) (phba->generation == BE_GEN2)
+#define chip_be3_r(phba) (phba->generation == BE_GEN3)
+#define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba)))
struct beiscsi_hba {
struct hba_parameters params;
struct hwi_controller *phwi_ctrlr;
@@ -304,10 +307,15 @@ struct beiscsi_hba {
unsigned short avlbl_cids;
unsigned short cid_alloc;
unsigned short cid_free;
- struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2];
struct list_head hba_queue;
+#define BE_MAX_SESSION 2048
+#define BE_SET_CID_TO_CRI(cri_index, cid) \
+ (phba->cid_to_cri_map[cid] = cri_index)
+#define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid])
+ unsigned short cid_to_cri_map[BE_MAX_SESSION];
unsigned short *cid_array;
struct iscsi_endpoint **ep_array;
+ struct beiscsi_conn **conn_table;
struct iscsi_boot_kset *boot_kset;
struct Scsi_Host *shost;
struct iscsi_iface *ipv4_iface;
@@ -339,6 +347,7 @@ struct beiscsi_hba {
struct delayed_work beiscsi_hw_check_task;
u8 mac_address[ETH_ALEN];
+ char fw_ver_str[BEISCSI_VER_STRLEN];
char wq_name[20];
struct workqueue_struct *wq; /* The actuak work queue */
struct be_ctrl_info ctrl;
@@ -563,7 +572,7 @@ struct hwi_async_pdu_context {
* This is a varying size list! Do not add anything
* after this entry!!
*/
- struct hwi_async_entry async_entry[BE2_MAX_SESSIONS * 2];
+ struct hwi_async_entry *async_entry;
};
#define PDUCQE_CODE_MASK 0x0000003F
@@ -749,6 +758,8 @@ void
free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
void beiscsi_process_all_cqs(struct work_struct *work);
+void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
+ struct iscsi_task *task);
static inline bool beiscsi_error(struct beiscsi_hba *phba)
{
@@ -933,7 +944,7 @@ struct hwi_controller {
struct sgl_handle *psgl_handle_base;
unsigned int wrb_mem_index;
- struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2];
+ struct hwi_wrb_context *wrb_context;
struct mcc_wrb *pmcc_wrb_base;
struct be_ring default_pdu_hdr;
struct be_ring default_pdu_data;
@@ -970,9 +981,7 @@ struct hwi_context_memory {
struct be_queue_info be_def_hdrq;
struct be_queue_info be_def_dataq;
- struct be_queue_info be_wrbq[BE2_MAX_SESSIONS];
- struct be_mcc_wrb_context *pbe_mcc_context;
-
+ struct be_queue_info *be_wrbq;
struct hwi_async_pdu_context *pasync_ctx;
};
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index a6c2fe4..245a959 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -368,6 +368,8 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BM_%d : phba->fw_config.iscsi_features = %d\n",
phba->fw_config.iscsi_features);
+ memcpy(phba->fw_ver_str, resp->params.hba_attribs.
+ firmware_version_string, BEISCSI_VER_STRLEN);
} else
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : Failed in mgmt_check_supported_fw\n");
@@ -1260,6 +1262,45 @@ beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr,
}
/**
+ * beiscsi_fw_ver_disp()- Display Firmware Version
+ * @dev: ptr to device not used.
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text Firmware version
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str);
+}
+
+/**
+ * beiscsi_active_cid_disp()- Display Sessions Active
+ * @dev: ptr to device not used.
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text Session Count
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_active_cid_disp(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (phba->params.cxns_per_ctrl - phba->avlbl_cids));
+}
+
+/**
* beiscsi_adap_family_disp()- Display adapter family.
* @dev: ptr to device to get priv structure
* @attr: device attribute, not used.
@@ -1292,7 +1333,7 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,
break;
default:
return snprintf(buf, PAGE_SIZE,
- "Unkown Adapter Family: 0x%x\n", dev_id);
+ "Unknown Adapter Family: 0x%x\n", dev_id);
break;
}
}
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index 2e4968a..04af7e7 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -156,25 +156,25 @@ union invalidate_commands_params {
} __packed;
struct mgmt_hba_attributes {
- u8 flashrom_version_string[32];
- u8 manufacturer_name[32];
+ u8 flashrom_version_string[BEISCSI_VER_STRLEN];
+ u8 manufacturer_name[BEISCSI_VER_STRLEN];
u32 supported_modes;
u8 seeprom_version_lo;
u8 seeprom_version_hi;
u8 rsvd0[2];
u32 fw_cmd_data_struct_version;
u32 ep_fw_data_struct_version;
- u32 future_reserved[12];
+ u8 ncsi_version_string[12];
u32 default_extended_timeout;
- u8 controller_model_number[32];
+ u8 controller_model_number[BEISCSI_VER_STRLEN];
u8 controller_description[64];
- u8 controller_serial_number[32];
- u8 ip_version_string[32];
- u8 firmware_version_string[32];
- u8 bios_version_string[32];
- u8 redboot_version_string[32];
- u8 driver_version_string[32];
- u8 fw_on_flash_version_string[32];
+ u8 controller_serial_number[BEISCSI_VER_STRLEN];
+ u8 ip_version_string[BEISCSI_VER_STRLEN];
+ u8 firmware_version_string[BEISCSI_VER_STRLEN];
+ u8 bios_version_string[BEISCSI_VER_STRLEN];
+ u8 redboot_version_string[BEISCSI_VER_STRLEN];
+ u8 driver_version_string[BEISCSI_VER_STRLEN];
+ u8 fw_on_flash_version_string[BEISCSI_VER_STRLEN];
u32 functionalities_supported;
u16 max_cdblength;
u8 asic_revision;
@@ -190,7 +190,8 @@ struct mgmt_hba_attributes {
u32 firmware_post_status;
u32 hba_mtu[8];
u8 iscsi_features;
- u8 future_u8[3];
+ u8 asic_generation;
+ u8 future_u8[2];
u32 future_u32[3];
} __packed;
@@ -207,7 +208,7 @@ struct mgmt_controller_attributes {
u64 unique_identifier;
u8 netfilters;
u8 rsvd0[3];
- u8 future_u32[4];
+ u32 future_u32[4];
} __packed;
struct be_mgmt_controller_attributes {
@@ -311,6 +312,12 @@ int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
ssize_t beiscsi_drvr_ver_disp(struct device *dev,
struct device_attribute *attr, char *buf);
+ssize_t beiscsi_fw_ver_disp(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+ssize_t beiscsi_active_cid_disp(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
ssize_t beiscsi_adap_family_disp(struct device *dev,
struct device_attribute *attr, char *buf);
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 342d7d9..520540a 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -1432,6 +1432,7 @@ bfa_iocfc_disable_cbfn(void *bfa_arg)
{
struct bfa_s *bfa = bfa_arg;
+ bfa->queue_process = BFA_FALSE;
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_DISABLED);
}
@@ -1567,7 +1568,6 @@ bfa_iocfc_start(struct bfa_s *bfa)
void
bfa_iocfc_stop(struct bfa_s *bfa)
{
- bfa->queue_process = BFA_FALSE;
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_STOP);
}
@@ -1674,7 +1674,6 @@ bfa_iocfc_disable(struct bfa_s *bfa)
bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
"IOC Disable");
- bfa->queue_process = BFA_FALSE;
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DISABLE);
}
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index 0efdf31..d40a79f 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -45,6 +45,7 @@ enum {
BFA_MFG_TYPE_PROWLER_C = 1710, /* Prowler CNA only cards */
BFA_MFG_TYPE_PROWLER_D = 1860, /* Prowler Dual cards */
BFA_MFG_TYPE_CHINOOK = 1867, /* Chinook cards */
+ BFA_MFG_TYPE_CHINOOK2 = 1869, /*!< Chinook2 cards */
BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */
};
@@ -59,7 +60,8 @@ enum {
(type) == BFA_MFG_TYPE_ASTRA || \
(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
(type) == BFA_MFG_TYPE_LIGHTNING || \
- (type) == BFA_MFG_TYPE_CHINOOK))
+ (type) == BFA_MFG_TYPE_CHINOOK || \
+ (type) == BFA_MFG_TYPE_CHINOOK2))
/*
* Check if the card having old wwn/mac handling
@@ -185,6 +187,8 @@ enum bfa_status {
BFA_STATUS_FAA_DISABLED = 198, /* FAA is already disabled */
BFA_STATUS_FAA_ACQUIRED = 199, /* FAA is already acquired */
BFA_STATUS_FAA_ACQ_ADDR = 200, /* Acquiring addr */
+ BFA_STATUS_BBCR_FC_ONLY = 201, /*!< BBCredit Recovery is supported for *
+ * FC mode only */
BFA_STATUS_ERROR_TRUNK_ENABLED = 203, /* Trunk enabled on adapter */
BFA_STATUS_MAX_ENTRY_REACHED = 212, /* MAX entry reached */
BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */
@@ -197,7 +201,34 @@ enum bfa_status {
BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */
BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */
BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */
+ BFA_STATUS_DPORT_NO_SFP = 243, /* SFP is not present.\n D-port will be
+ * enabled but it will be operational
+ * only after inserting a valid SFP. */
BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */
+ BFA_STATUS_DPORT_ENOSYS = 254, /* Switch has no D_Port functionality */
+ BFA_STATUS_DPORT_CANT_PERF = 255, /* Switch port is not D_Port capable
+ * or D_Port is disabled */
+ BFA_STATUS_DPORT_LOGICALERR = 256, /* Switch D_Port fail */
+ BFA_STATUS_DPORT_SWBUSY = 257, /* Switch port busy */
+ BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is
+ * supported at max port speed alone */
+ BFA_STATUS_ERROR_BBCR_ENABLED = 259, /*!< BB credit recovery
+ * is enabled */
+ BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value.
+ * Valid range is [1-15] */
+ BFA_STATUS_DDPORT_ERR = 261, /* Dynamic D_Port mode is active.\n To
+ * exit dynamic mode, disable D_Port on
+ * the remote port */
+ BFA_STATUS_DPORT_SFPWRAP_ERR = 262, /* Clear e/o_wrap fail, check or
+ * replace SFP */
+ BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational.
+ * Disable BBCR and try this operation again. */
+ BFA_STATUS_DPORT_SW_NOTREADY = 268, /* Remote port is not ready to
+ * start dport test. Check remote
+ * port status. */
+ BFA_STATUS_DPORT_INV_SFP = 271, /* Invalid SFP for D-PORT mode. */
+ BFA_STATUS_DPORT_CMD_NOTSUPP = 273, /* Dport is not supported by
+ * remote port */
BFA_STATUS_MAX_VAL /* Unknown error code */
};
#define bfa_status_t enum bfa_status
@@ -234,6 +265,7 @@ enum {
BFA_ADAPTER_MFG_NAME_LEN = 8, /* manufacturer name length */
BFA_ADAPTER_SYM_NAME_LEN = 64, /* adapter symbolic name length */
BFA_ADAPTER_OS_TYPE_LEN = 64, /* adapter os type length */
+ BFA_ADAPTER_UUID_LEN = 16, /* adapter uuid length */
};
struct bfa_adapter_attr_s {
@@ -267,6 +299,7 @@ struct bfa_adapter_attr_s {
u8 mfg_month; /* manufacturing month */
u16 mfg_year; /* manufacturing year */
u16 rsvd;
+ u8 uuid[BFA_ADAPTER_UUID_LEN];
};
/*
@@ -380,7 +413,8 @@ struct bfa_ioc_attr_s {
u8 port_mode; /* bfa_mode_s */
u8 cap_bm; /* capability */
u8 port_mode_cfg; /* bfa_mode_s */
- u8 rsvd[4]; /* 64bit align */
+ u8 def_fn; /* 1 if default fn */
+ u8 rsvd[3]; /* 64bit align */
};
/*
@@ -517,17 +551,6 @@ struct bfa_ioc_aen_data_s {
};
/*
- * D-port states
- *
-*/
-enum bfa_dport_state {
- BFA_DPORT_ST_DISABLED = 0, /* D-port is Disabled */
- BFA_DPORT_ST_DISABLING = 1, /* D-port is Disabling */
- BFA_DPORT_ST_ENABLING = 2, /* D-port is Enabling */
- BFA_DPORT_ST_ENABLED = 3, /* D-port is Enabled */
-};
-
-/*
* ---------------------- mfg definitions ------------
*/
@@ -614,6 +637,7 @@ enum {
BFA_PCI_DEVICE_ID_CT = 0x14,
BFA_PCI_DEVICE_ID_CT_FC = 0x21,
BFA_PCI_DEVICE_ID_CT2 = 0x22,
+ BFA_PCI_DEVICE_ID_CT2_QUAD = 0x23,
};
#define bfa_asic_id_cb(__d) \
@@ -622,7 +646,9 @@ enum {
#define bfa_asic_id_ct(__d) \
((__d) == BFA_PCI_DEVICE_ID_CT || \
(__d) == BFA_PCI_DEVICE_ID_CT_FC)
-#define bfa_asic_id_ct2(__d) ((__d) == BFA_PCI_DEVICE_ID_CT2)
+#define bfa_asic_id_ct2(__d) \
+ ((__d) == BFA_PCI_DEVICE_ID_CT2 || \
+ (__d) == BFA_PCI_DEVICE_ID_CT2_QUAD)
#define bfa_asic_id_ctc(__d) \
(bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d))
@@ -1126,6 +1152,7 @@ struct bfa_flash_attr_s {
#define LB_PATTERN_DEFAULT 0xB5B5B5B5
#define QTEST_CNT_DEFAULT 10
#define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT
+#define DPORT_ENABLE_LOOPCNT_DEFAULT (1024 * 1024)
struct bfa_diag_memtest_s {
u8 algo;
@@ -1154,6 +1181,54 @@ struct bfa_diag_loopback_result_s {
u8 rsvd[3];
};
+enum bfa_diag_dport_test_status {
+ DPORT_TEST_ST_IDLE = 0, /* the test has not started yet. */
+ DPORT_TEST_ST_FINAL = 1, /* the test done successfully */
+ DPORT_TEST_ST_SKIP = 2, /* the test skipped */
+ DPORT_TEST_ST_FAIL = 3, /* the test failed */
+ DPORT_TEST_ST_INPRG = 4, /* the testing is in progress */
+ DPORT_TEST_ST_RESPONDER = 5, /* test triggered from remote port */
+ DPORT_TEST_ST_STOPPED = 6, /* the test stopped by user. */
+ DPORT_TEST_ST_MAX
+};
+
+enum bfa_diag_dport_test_type {
+ DPORT_TEST_ELOOP = 0,
+ DPORT_TEST_OLOOP = 1,
+ DPORT_TEST_ROLOOP = 2,
+ DPORT_TEST_LINK = 3,
+ DPORT_TEST_MAX
+};
+
+enum bfa_diag_dport_test_opmode {
+ BFA_DPORT_OPMODE_AUTO = 0,
+ BFA_DPORT_OPMODE_MANU = 1,
+};
+
+struct bfa_diag_dport_subtest_result_s {
+ u8 status; /* bfa_diag_dport_test_status */
+ u8 rsvd[7]; /* 64bit align */
+ u64 start_time; /* timestamp */
+};
+
+struct bfa_diag_dport_result_s {
+ wwn_t rp_pwwn; /* switch port wwn */
+ wwn_t rp_nwwn; /* switch node wwn */
+ u64 start_time; /* user/sw start time */
+ u64 end_time; /* timestamp */
+ u8 status; /* bfa_diag_dport_test_status */
+ u8 mode; /* bfa_diag_dport_test_opmode */
+ u8 rsvd; /* 64bit align */
+ u8 speed; /* link speed for buf_reqd */
+ u16 buffer_required;
+ u16 frmsz; /* frame size for buf_reqd */
+ u32 lpcnt; /* Frame count */
+ u32 pat; /* Pattern */
+ u32 roundtrip_latency; /* in nano sec */
+ u32 est_cable_distance; /* in meter */
+ struct bfa_diag_dport_subtest_result_s subtest[DPORT_TEST_MAX];
+};
+
struct bfa_diag_ledtest_s {
u32 cmd; /* bfa_led_op_t */
u32 color; /* bfa_led_color_t */
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index ec03c8c..638f441f 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -105,6 +105,9 @@ struct bfa_fw_ioim_stats_s {
* an error condition*/
u32 wait_for_si; /* FW wait for SI */
u32 rec_rsp_inval; /* REC rsp invalid */
+ u32 rec_rsp_xchg_comp; /* REC rsp xchg complete */
+ u32 rec_rsp_rd_si_ownd; /* REC rsp read si owned */
+
u32 seqr_io_abort; /* target does not know cmd so abort */
u32 seqr_io_retry; /* SEQR failed so retry IO */
@@ -257,8 +260,6 @@ struct bfa_fw_port_lksm_stats_s {
u32 nos_tx; /* No. of times NOS tx started */
u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */
u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */
- u32 bbsc_lr; /* LKSM LR tx for credit recovery */
- u32 rsvd;
};
struct bfa_fw_port_snsm_stats_s {
@@ -409,7 +410,7 @@ struct bfa_fw_trunk_stats_s {
u32 rsvd; /* padding for 64 bit alignment */
};
-struct bfa_fw_advsm_stats_s {
+struct bfa_fw_aport_stats_s {
u32 flogi_sent; /* Flogi sent */
u32 flogi_acc_recvd; /* Flogi Acc received */
u32 flogi_rjt_recvd; /* Flogi rejects received */
@@ -419,6 +420,12 @@ struct bfa_fw_advsm_stats_s {
u32 elp_accepted; /* ELP Accepted */
u32 elp_rejected; /* ELP rejected */
u32 elp_dropped; /* ELP dropped */
+
+ u32 bbcr_lr_count; /*!< BBCR Link Resets */
+ u32 frame_lost_intrs; /*!< BBCR Frame loss intrs */
+ u32 rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */
+
+ u32 rsvd;
};
/*
@@ -479,6 +486,14 @@ struct bfa_fw_ct_mod_stats_s {
};
/*
+ * RDS mod stats
+ */
+struct bfa_fw_rds_stats_s {
+ u32 no_fid_drop_err; /* RDS no fid drop error */
+ u32 rsvd; /* 64bit align */
+};
+
+/*
* IOC firmware stats
*/
struct bfa_fw_stats_s {
@@ -489,10 +504,11 @@ struct bfa_fw_stats_s {
struct bfa_fw_fcxchg_stats_s fcxchg_stats;
struct bfa_fw_lps_stats_s lps_stats;
struct bfa_fw_trunk_stats_s trunk_stats;
- struct bfa_fw_advsm_stats_s advsm_stats;
+ struct bfa_fw_aport_stats_s aport_stats;
struct bfa_fw_mac_mod_stats_s macmod_stats;
struct bfa_fw_ct_mod_stats_s ctmod_stats;
struct bfa_fw_eth_sndrcv_stats_s ethsndrcv_stats;
+ struct bfa_fw_rds_stats_s rds_stats;
};
#define BFA_IOCFC_PATHTOV_MAX 60
@@ -545,6 +561,27 @@ struct bfa_qos_attr_s {
struct bfa_qos_bw_s qos_bw_op; /* QOS bw operational */
};
+enum bfa_bbcr_state {
+ BFA_BBCR_DISABLED, /*!< BBCR is disable */
+ BFA_BBCR_ONLINE, /*!< BBCR is online */
+ BFA_BBCR_OFFLINE, /*!< BBCR is offline */
+};
+
+enum bfa_bbcr_err_reason {
+ BFA_BBCR_ERR_REASON_NONE, /*!< Unknown */
+ BFA_BBCR_ERR_REASON_SPEED_UNSUP, /*!< Port speed < max sup_speed */
+ BFA_BBCR_ERR_REASON_PEER_UNSUP, /*!< BBCR is disable on peer port */
+ BFA_BBCR_ERR_REASON_NON_BRCD_SW, /*!< Connected to non BRCD switch */
+ BFA_BBCR_ERR_REASON_FLOGI_RJT, /*!< Login rejected by the switch */
+};
+
+struct bfa_bbcr_attr_s {
+ u8 state;
+ u8 peer_bb_scn;
+ u8 reason;
+ u8 rsvd;
+};
+
/*
* These fields should be displayed only from the CLI.
* There will be a separate BFAL API (get_qos_vc_attr ?)
@@ -736,6 +773,7 @@ enum bfa_port_states {
BFA_PORT_ST_TOGGLING_QWAIT = 14,
BFA_PORT_ST_FAA_MISCONFIG = 15,
BFA_PORT_ST_DPORT = 16,
+ BFA_PORT_ST_DDPORT = 17,
BFA_PORT_ST_MAX_STATE,
};
@@ -857,6 +895,15 @@ enum bfa_lunmask_state_s {
BFA_LUNMASK_UNINITIALIZED = 0xff,
};
+/**
+ * FEC states
+ */
+enum bfa_fec_state_s {
+ BFA_FEC_ONLINE = 1, /*!< FEC is online */
+ BFA_FEC_OFFLINE = 2, /*!< FEC is offline */
+ BFA_FEC_OFFLINE_NOT_16G = 3, /*!< FEC is offline (speed not 16Gig) */
+};
+
#pragma pack(1)
/*
* LUN mask configuration
@@ -892,6 +939,9 @@ struct bfa_defs_fcpim_throttle_s {
u16 rsvd;
};
+#define BFA_BB_SCN_DEF 3
+#define BFA_BB_SCN_MAX 0x0F
+
/*
* Physical port configuration
*/
@@ -907,8 +957,8 @@ struct bfa_port_cfg_s {
u8 tx_bbcredit; /* transmit buffer credits */
u8 ratelimit; /* ratelimit enabled or not */
u8 trl_def_speed; /* ratelimit default speed */
- u8 bb_scn; /* BB_SCN value from FLOGI Exchg */
- u8 bb_scn_state; /* Config state of BB_SCN */
+ u8 bb_cr_enabled; /*!< Config state of BB_SCN */
+ u8 bb_scn; /*!< BB_SCN value for FLOGI Exchg */
u8 faa_state; /* FAA enabled/disabled */
u8 rsvd1;
u16 path_tov; /* device path timeout */
@@ -950,6 +1000,7 @@ struct bfa_port_attr_s {
bfa_boolean_t link_e2e_beacon; /* link beacon is on */
bfa_boolean_t bbsc_op_status; /* fc credit recovery oper
* state */
+ enum bfa_fec_state_s fec_state; /*!< current FEC state */
/*
* Dynamic field - info from FCS
@@ -961,7 +1012,7 @@ struct bfa_port_attr_s {
/* FCoE specific */
u16 fcoe_vlan;
- u8 rsvd1[6];
+ u8 rsvd1[2];
};
/*
@@ -1048,10 +1099,12 @@ struct bfa_port_link_s {
u8 speed; /* Link speed (1/2/4/8 G) */
u32 linkstate_opt; /* Linkstate optional data (debug) */
u8 trunked; /* Trunked or not (1 or 0) */
- u8 resvd[7];
+ u8 fec_state; /*!< State of FEC */
+ u8 resvd[6];
struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
union {
struct bfa_fcport_loop_info_s loop_info;
+ struct bfa_bbcr_attr_s bbcr_attr;
union {
struct bfa_qos_vc_attr_s qos_vc_attr;
/* VC info from ELP */
@@ -1215,9 +1268,11 @@ struct bfa_port_fc_stats_s {
u64 bad_os_count; /* Invalid ordered sets */
u64 err_enc_out; /* Encoding err nonframe_8b10b */
u64 err_enc; /* Encoding err frame_8b10b */
- u64 bbsc_frames_lost; /* Credit Recovery-Frames Lost */
- u64 bbsc_credits_lost; /* Credit Recovery-Credits Lost */
- u64 bbsc_link_resets; /* Credit Recovery-Link Resets */
+ u64 bbcr_frames_lost; /*!< BBCR Frames Lost */
+ u64 bbcr_rrdys_lost; /*!< BBCR RRDYs Lost */
+ u64 bbcr_link_resets; /*!< BBCR Link Resets */
+ u64 bbcr_frame_lost_intrs; /*!< BBCR Frame loss intrs */
+ u64 bbcr_rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */
u64 loop_timeouts; /* Loop timeouts */
};
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index bea821b..562ef73 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -1531,6 +1531,12 @@ enum fdmi_hba_attribute_type {
FDMI_HBA_ATTRIB_FW_VERSION, /* 0x0009 */
FDMI_HBA_ATTRIB_OS_NAME, /* 0x000A */
FDMI_HBA_ATTRIB_MAX_CT, /* 0x000B */
+ FDMI_HBA_ATTRIB_NODE_SYM_NAME, /* 0x000C */
+ FDMI_HBA_ATTRIB_VENDOR_INFO, /* 0x000D */
+ FDMI_HBA_ATTRIB_NUM_PORTS, /* 0x000E */
+ FDMI_HBA_ATTRIB_FABRIC_NAME, /* 0x000F */
+ FDMI_HBA_ATTRIB_BIOS_VER, /* 0x0010 */
+ FDMI_HBA_ATTRIB_VENDOR_ID = 0x00E0,
FDMI_HBA_ATTRIB_MAX_TYPE
};
@@ -1545,6 +1551,15 @@ enum fdmi_port_attribute_type {
FDMI_PORT_ATTRIB_FRAME_SIZE, /* 0x0004 */
FDMI_PORT_ATTRIB_DEV_NAME, /* 0x0005 */
FDMI_PORT_ATTRIB_HOST_NAME, /* 0x0006 */
+ FDMI_PORT_ATTRIB_NODE_NAME, /* 0x0007 */
+ FDMI_PORT_ATTRIB_PORT_NAME, /* 0x0008 */
+ FDMI_PORT_ATTRIB_PORT_SYM_NAME, /* 0x0009 */
+ FDMI_PORT_ATTRIB_PORT_TYPE, /* 0x000A */
+ FDMI_PORT_ATTRIB_SUPP_COS, /* 0x000B */
+ FDMI_PORT_ATTRIB_PORT_FAB_NAME, /* 0x000C */
+ FDMI_PORT_ATTRIB_PORT_FC4_TYPE, /* 0x000D */
+ FDMI_PORT_ATTRIB_PORT_STATE = 0x101, /* 0x0101 */
+ FDMI_PORT_ATTRIB_PORT_NUM_RPRT = 0x102, /* 0x0102 */
FDMI_PORT_ATTR_MAX_TYPE
};
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 27b5609..d7385d1 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -2882,7 +2882,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
iotag = be16_to_cpu(rsp->io_tag);
ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
- WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag);
+ WARN_ON(ioim->iotag != iotag);
bfa_ioim_cb_profile_comp(fcpim, ioim);
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index d428808..a3ab5cc 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -240,9 +240,6 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
u32 rsp_len,
u32 resid_len,
struct fchs_s *rspfchs);
-static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
-static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
- struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
@@ -404,8 +401,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_CONT_OP:
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit,
- bfa_fcs_fabric_oper_bbscn(fabric));
+ fabric->bb_credit);
fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
if (fabric->auth_reqd && fabric->is_auth) {
@@ -433,8 +429,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_NO_FABRIC:
fabric->fab_type = BFA_FCS_FABRIC_N2N;
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit,
- bfa_fcs_fabric_oper_bbscn(fabric));
+ fabric->bb_credit);
bfa_fcs_fabric_notify_online(fabric);
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
break;
@@ -602,8 +597,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_NO_FABRIC:
bfa_trc(fabric->fcs, fabric->bb_credit);
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit,
- bfa_fcs_fabric_oper_bbscn(fabric));
+ fabric->bb_credit);
break;
case BFA_FCS_FABRIC_SM_RETRY_OP:
@@ -965,10 +959,6 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
case BFA_STATUS_FABRIC_RJT:
fabric->stats.flogi_rejects++;
- if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
- fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
- fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
-
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
return;
@@ -1014,14 +1004,11 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
{
struct bfa_s *bfa = fabric->fcs->bfa;
struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
- u8 alpa = 0, bb_scn = 0;
+ u8 alpa = 0;
- if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
- (!fabric->fcs->bbscn_flogi_rjt))
- bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
- pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
+ pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
fabric->stats.flogi_sent++;
}
@@ -1102,40 +1089,6 @@ bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)
}
/*
- * Computes operating BB_SCN value
- */
-static u8
-bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
-{
- u8 pr_bbscn = fabric->lps->pr_bbscn;
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
-
- if (!(fcport->cfg.bb_scn_state && pr_bbscn))
- return 0;
-
- /* return max of local/remote bb_scn values */
- return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
- pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
-}
-
-/*
- * Check if BB_SCN can be enabled.
- */
-static bfa_boolean_t
-bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
-
- if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
- fcport->cfg.bb_scn_state &&
- !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
- !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
- return BFA_TRUE;
- else
- return BFA_FALSE;
-}
-
-/*
* Delete all vports and wait for vport delete completions.
*/
static void
@@ -1273,7 +1226,6 @@ void
bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
{
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
}
@@ -1480,7 +1432,6 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
}
fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
- fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
@@ -1513,8 +1464,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
n2n_port->reply_oxid, pcfg->pwwn,
pcfg->nwwn,
bfa_fcport_get_maxfrsize(bfa),
- bfa_fcport_get_rx_bbcredit(bfa),
- bfa_fcs_fabric_oper_bbscn(fabric));
+ bfa_fcport_get_rx_bbcredit(bfa), 0);
bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,
BFA_FALSE, FC_CLASS_3,
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index a449706..94d5d01 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -243,24 +243,21 @@ struct bfa_fcs_fabric_s;
* Symbolic Name.
*
* Physical Port's symbolic name Format : (Total 128 bytes)
- * Adapter Model number/name : 12 bytes
+ * Adapter Model number/name : 16 bytes
* Driver Version : 10 bytes
* Host Machine Name : 30 bytes
- * Host OS Info : 48 bytes
+ * Host OS Info : 44 bytes
* Host OS PATCH Info : 16 bytes
* ( remaining 12 bytes reserved to be used for separator)
*/
#define BFA_FCS_PORT_SYMBNAME_SEPARATOR " | "
-#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 12
+#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 16
#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10
#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30
-#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48
+#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 44
#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
-/* bb_scn value in 2^bb_scn */
-#define BFA_FCS_PORT_DEF_BB_SCN 3
-
/*
* Get FC port ID for a logical port.
*/
@@ -630,6 +627,9 @@ void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
#define BFA_FCS_FDMI_SUPP_SPEEDS_10G FDMI_TRANS_SPEED_10G
+#define BFA_FCS_FDMI_VENDOR_INFO_LEN 8
+#define BFA_FCS_FDMI_FC4_TYPE_LEN 32
+
/*
* HBA Attribute Block : BFA internal representation. Note : Some variable
* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
@@ -640,25 +640,39 @@ struct bfa_fcs_fdmi_hba_attr_s {
u8 manufacturer[64];
u8 serial_num[64];
u8 model[16];
- u8 model_desc[256];
+ u8 model_desc[128];
u8 hw_version[8];
u8 driver_version[BFA_VERSION_LEN];
u8 option_rom_ver[BFA_VERSION_LEN];
u8 fw_version[BFA_VERSION_LEN];
u8 os_name[256];
__be32 max_ct_pyld;
+ struct bfa_lport_symname_s node_sym_name;
+ u8 vendor_info[BFA_FCS_FDMI_VENDOR_INFO_LEN];
+ __be32 num_ports;
+ wwn_t fabric_name;
+ u8 bios_ver[BFA_VERSION_LEN];
};
/*
* Port Attribute Block
*/
struct bfa_fcs_fdmi_port_attr_s {
- u8 supp_fc4_types[32]; /* supported FC4 types */
+ u8 supp_fc4_types[BFA_FCS_FDMI_FC4_TYPE_LEN];
__be32 supp_speed; /* supported speed */
__be32 curr_speed; /* current Speed */
__be32 max_frm_size; /* max frame size */
u8 os_device_name[256]; /* OS device Name */
u8 host_name[256]; /* host name */
+ wwn_t port_name;
+ wwn_t node_name;
+ struct bfa_lport_symname_s port_sym_name;
+ __be32 port_type;
+ enum fc_cos scos;
+ wwn_t port_fabric_name;
+ u8 port_act_fc4_type[BFA_FCS_FDMI_FC4_TYPE_LEN];
+ __be32 port_state;
+ __be32 num_ports;
};
struct bfa_fcs_stats_s {
@@ -683,8 +697,6 @@ struct bfa_fcs_s {
struct bfa_trc_mod_s *trcmod; /* tracing module */
bfa_boolean_t vf_enabled; /* VF mode is enabled */
bfa_boolean_t fdmi_enabled; /* FDMI is enabled */
- bfa_boolean_t bbscn_enabled; /* Driver Config Parameter */
- bfa_boolean_t bbscn_flogi_rjt;/* FLOGI reject due to BB_SCN */
bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
u16 port_vfid; /* port default VF ID */
struct bfa_fcs_driver_info_s driver_info;
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 1224d04..2f61a5a 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -2048,10 +2048,71 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
templen = sizeof(fcs_hba_attr->max_ct_pyld);
memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
len += templen;
count++;
attr->len = cpu_to_be16(templen + sizeof(attr->type) +
sizeof(templen));
+ /*
+ * Send extended attributes ( FOS 7.1 support )
+ */
+ if (fdmi->retry_cnt == 0) {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME);
+ templen = sizeof(fcs_hba_attr->node_sym_name);
+ memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID);
+ templen = sizeof(fcs_hba_attr->vendor_info);
+ memcpy(attr->value, &fcs_hba_attr->vendor_info, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS);
+ templen = sizeof(fcs_hba_attr->num_ports);
+ memcpy(attr->value, &fcs_hba_attr->num_ports, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME);
+ templen = sizeof(fcs_hba_attr->fabric_name);
+ memcpy(attr->value, &fcs_hba_attr->fabric_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER);
+ templen = sizeof(fcs_hba_attr->bios_ver);
+ memcpy(attr->value, &fcs_hba_attr->bios_ver, templen);
+ templen = fc_roundup(attr->len, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+ }
/*
* Update size of payload
@@ -2252,6 +2313,113 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
sizeof(templen));
}
+ if (fdmi->retry_cnt == 0) {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME);
+ templen = sizeof(fcs_port_attr.node_name);
+ memcpy(attr->value, &fcs_port_attr.node_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME);
+ templen = sizeof(fcs_port_attr.port_name);
+ memcpy(attr->value, &fcs_port_attr.port_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ if (fcs_port_attr.port_sym_name.symname[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type =
+ cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME);
+ templen = sizeof(fcs_port_attr.port_sym_name);
+ memcpy(attr->value,
+ &fcs_port_attr.port_sym_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) +
+ sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen +
+ sizeof(attr->type) + sizeof(templen));
+ }
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE);
+ templen = sizeof(fcs_port_attr.port_type);
+ memcpy(attr->value, &fcs_port_attr.port_type, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS);
+ templen = sizeof(fcs_port_attr.scos);
+ memcpy(attr->value, &fcs_port_attr.scos, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME);
+ templen = sizeof(fcs_port_attr.port_fabric_name);
+ memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE);
+ templen = sizeof(fcs_port_attr.port_act_fc4_type);
+ memcpy(attr->value, fcs_port_attr.port_act_fc4_type,
+ templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE);
+ templen = sizeof(fcs_port_attr.port_state);
+ memcpy(attr->value, &fcs_port_attr.port_state, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT);
+ templen = sizeof(fcs_port_attr.num_ports);
+ memcpy(attr->value, &fcs_port_attr.num_ports, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+ }
+
/*
* Update size of payload
*/
@@ -2458,6 +2626,15 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
/* Retrieve the max frame size from the port attr */
bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
+
+ strncpy(hba_attr->node_sym_name.symname,
+ port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN);
+ strcpy(hba_attr->vendor_info, "BROCADE");
+ hba_attr->num_ports =
+ cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc));
+ hba_attr->fabric_name = port->fabric->lps->pr_nwwn;
+ strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
+
}
static void
@@ -2467,6 +2644,7 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
struct bfa_fcs_lport_s *port = fdmi->ms->port;
struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
struct bfa_port_attr_s pport_attr;
+ struct bfa_lport_attr_s lport_attr;
memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
@@ -2531,6 +2709,18 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
sizeof(port_attr->host_name));
+ port_attr->node_name = bfa_fcs_lport_get_nwwn(port);
+ port_attr->port_name = bfa_fcs_lport_get_pwwn(port);
+
+ strncpy(port_attr->port_sym_name.symname,
+ (char *)&bfa_fcs_lport_get_psym_name(port), BFA_SYMNAME_MAXLEN);
+ bfa_fcs_lport_get_attr(port, &lport_attr);
+ port_attr->port_type = cpu_to_be32(lport_attr.port_type);
+ port_attr->scos = pport_attr.cos_supported;
+ port_attr->port_fabric_name = port->fabric->lps->pr_nwwn;
+ fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type);
+ port_attr->port_state = cpu_to_be32(pport_attr.port_state);
+ port_attr->num_ports = cpu_to_be32(port->num_rports);
}
/*
@@ -5798,6 +5988,7 @@ enum bfa_fcs_vport_event {
BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
+ BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */
};
static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
@@ -5983,6 +6174,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
break;
case BFA_FCS_VPORT_SM_RSP_FAILED:
+ case BFA_FCS_VPORT_SM_FABRIC_MAX:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
break;
@@ -6053,6 +6245,7 @@ bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
case BFA_FCS_VPORT_SM_OFFLINE:
case BFA_FCS_VPORT_SM_RSP_ERROR:
case BFA_FCS_VPORT_SM_RSP_FAILED:
+ case BFA_FCS_VPORT_SM_FABRIC_MAX:
case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
@@ -6338,7 +6531,7 @@ bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
else {
bfa_fcs_vport_aen_post(&vport->lport,
BFA_LPORT_AEN_NPIV_FABRIC_MAX);
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX);
}
break;
@@ -6724,7 +6917,19 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
break;
}
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ else
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+
+ break;
+
+ case BFA_STATUS_ETIMER:
+ vport->vport_stats.fdisc_timeouts++;
+ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ else
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
break;
case BFA_STATUS_FABRIC_RJT:
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index 58ac643..2035b0d 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -189,8 +189,8 @@ bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
break;
case RPSM_EVENT_PLOGI_RCVD:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
- bfa_fcs_rport_fcs_online_action(rport);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+ bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
case RPSM_EVENT_PLOGI_COMP:
@@ -2577,7 +2577,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
- port->fabric->bb_credit, 0);
+ port->fabric->bb_credit);
}
}
@@ -3430,9 +3430,10 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
num_ents = be16_to_cpu(rpsc2_acc->num_pids);
bfa_trc(rport->fcs, num_ents);
if (num_ents > 0) {
- WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid);
+ WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=
+ bfa_ntoh3b(rport->pid));
bfa_trc(rport->fcs,
- be16_to_cpu(rpsc2_acc->port_info[0].pid));
+ be32_to_cpu(rpsc2_acc->port_info[0].pid));
bfa_trc(rport->fcs,
be16_to_cpu(rpsc2_acc->port_info[0].speed));
bfa_trc(rport->fcs,
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 0116c10..f78bcb6 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -67,6 +67,14 @@ BFA_TRC_FILE(CNA, IOC);
((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
#define bfa_ioc_sync_complete(__ioc) \
((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
+#define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate) \
+ ((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate))
+#define bfa_ioc_get_cur_ioc_fwstate(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc))
+#define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate) \
+ ((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate))
+#define bfa_ioc_get_alt_ioc_fwstate(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_get_alt_fwstate(__ioc))
#define bfa_ioc_mbox_cmd_pending(__ioc) \
(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
@@ -698,7 +706,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
}
/* h/w sem init */
- fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
+ fwstate = bfa_ioc_get_cur_ioc_fwstate(iocpf->ioc);
if (fwstate == BFI_IOC_UNINIT) {
writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
goto sem_get;
@@ -725,8 +733,8 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
bfa_trc(iocpf->ioc, fwstate);
bfa_trc(iocpf->ioc, swab32(fwhdr.exec));
- writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT);
+ bfa_ioc_set_alt_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT);
/*
* Unlock the hw semaphore. Should be here only once per boot.
@@ -1037,7 +1045,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
*/
case IOCPF_E_TIMEOUT:
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
@@ -1138,7 +1146,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
case IOCPF_E_SEMLOCKED:
bfa_ioc_notify_fail(ioc);
bfa_ioc_sync_leave(ioc);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
break;
@@ -1227,7 +1235,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
bfa_ioc_notify_fail(ioc);
if (!iocpf->auto_recover) {
bfa_ioc_sync_leave(ioc);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
} else {
@@ -1519,7 +1527,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
u32 boot_type;
u32 boot_env;
- ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
if (force)
ioc_fwstate = BFI_IOC_UNINIT;
@@ -1850,7 +1858,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
bfa_trc(ioc, len);
for (i = 0; i < len; i++) {
r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
- buf[i] = be32_to_cpu(r32);
+ buf[i] = swab32(r32);
loff += sizeof(u32);
/*
@@ -2006,11 +2014,11 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
* Initialize IOC state of all functions on a chip reset.
*/
if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
- writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST);
+ bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST);
} else {
- writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING);
+ bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING);
}
bfa_ioc_msgflush(ioc);
@@ -2038,7 +2046,7 @@ bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
bfa_boolean_t
bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
{
- u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 r32 = bfa_ioc_get_cur_ioc_fwstate(ioc);
return ((r32 != BFI_IOC_UNINIT) &&
(r32 != BFI_IOC_INITING) &&
@@ -2188,6 +2196,7 @@ bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
break;
case BFA_PCI_DEVICE_ID_CT2:
+ case BFA_PCI_DEVICE_ID_CT2_QUAD:
ioc->asic_gen = BFI_ASIC_GEN_CT2;
if (clscode == BFI_PCIFN_CLASS_FC &&
pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
@@ -2430,12 +2439,12 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
return BFA_FALSE;
- ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
+ ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
- ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
+ ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
}
@@ -2449,8 +2458,8 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
void
bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
{
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT);
+ bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT);
}
#define BFA_MFG_NAME "Brocade"
@@ -2500,6 +2509,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
ad_attr->mfg_day = ioc_attr->mfg_day;
ad_attr->mfg_month = ioc_attr->mfg_month;
ad_attr->mfg_year = ioc_attr->mfg_year;
+ memcpy(ad_attr->uuid, ioc_attr->uuid, BFA_ADAPTER_UUID_LEN);
}
enum bfa_ioc_type_e
@@ -2564,13 +2574,19 @@ void
bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
{
struct bfi_ioc_attr_s *ioc_attr;
+ u8 nports = bfa_ioc_get_nports(ioc);
WARN_ON(!model);
memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
ioc_attr = ioc->attr;
- snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+ if (bfa_asic_id_ct2(ioc->pcidev.device_id) &&
+ (!bfa_mfg_is_mezz(ioc_attr->card_type)))
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u-%u%s",
+ BFA_MFG_NAME, ioc_attr->card_type, nports, "p");
+ else
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
BFA_MFG_NAME, ioc_attr->card_type);
}
@@ -2620,7 +2636,7 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
ioc_attr->state = bfa_ioc_get_state(ioc);
- ioc_attr->port_id = ioc->port_id;
+ ioc_attr->port_id = bfa_ioc_portid(ioc);
ioc_attr->port_mode = ioc->port_mode;
ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
ioc_attr->cap_bm = ioc->ad_cap_bm;
@@ -2629,8 +2645,9 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
- ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
- ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+ ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc);
+ ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc);
+ ioc_attr->def_fn = (bfa_ioc_pcifn(ioc) == bfa_ioc_portid(ioc));
bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
}
@@ -2917,7 +2934,7 @@ bfa_iocpf_sem_timeout(void *ioc_arg)
static void
bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
{
- u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
bfa_trc(ioc, fwstate);
@@ -6010,6 +6027,7 @@ bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
*/
msg->last = (len == fru->residue) ? 1 : 0;
+ msg->trfr_cmpl = (len == fru->residue) ? fru->trfr_cmpl : 0;
bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
@@ -6124,13 +6142,14 @@ bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,
*/
bfa_status_t
bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
- bfa_cb_fru_t cbfn, void *cbarg)
+ bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl)
{
bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);
bfa_trc(fru, len);
bfa_trc(fru, offset);
- if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+ if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2 &&
+ fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2)
return BFA_STATUS_FRU_NOT_PRESENT;
if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
@@ -6152,6 +6171,7 @@ bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
fru->offset = 0;
fru->addr_off = offset;
fru->ubuf = buf;
+ fru->trfr_cmpl = trfr_cmpl;
bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);
@@ -6181,7 +6201,8 @@ bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
return BFA_STATUS_FRU_NOT_PRESENT;
- if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
+ if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK &&
+ fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2)
return BFA_STATUS_CMD_NOTSUPP;
if (!bfa_ioc_is_operational(fru->ioc))
@@ -6222,7 +6243,8 @@ bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)
if (!bfa_ioc_is_operational(fru->ioc))
return BFA_STATUS_IOC_NON_OP;
- if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK)
+ if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK ||
+ fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK2)
*max_size = BFA_FRU_CHINOOK_MAX_SIZE;
else
return BFA_STATUS_CMD_NOTSUPP;
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 23a90e7..90814fe 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -346,6 +346,12 @@ struct bfa_ioc_hwif_s {
void (*ioc_sync_ack) (struct bfa_ioc_s *ioc);
bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc);
bfa_boolean_t (*ioc_lpu_read_stat) (struct bfa_ioc_s *ioc);
+ void (*ioc_set_fwstate) (struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate);
+ enum bfi_ioc_state (*ioc_get_fwstate) (struct bfa_ioc_s *ioc);
+ void (*ioc_set_alt_fwstate) (struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate);
+ enum bfi_ioc_state (*ioc_get_alt_fwstate) (struct bfa_ioc_s *ioc);
};
/*
@@ -725,6 +731,7 @@ struct bfa_fru_s {
struct bfa_mbox_cmd_s mb; /* mailbox */
struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
struct bfa_mem_dma_s fru_dma;
+ u8 trfr_cmpl;
};
#define BFA_FRU(__bfa) (&(__bfa)->modules.fru)
@@ -732,7 +739,7 @@ struct bfa_fru_s {
bfa_status_t bfa_fruvpd_update(struct bfa_fru_s *fru,
void *buf, u32 len, u32 offset,
- bfa_cb_fru_t cbfn, void *cbarg);
+ bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl);
bfa_status_t bfa_fruvpd_read(struct bfa_fru_s *fru,
void *buf, u32 len, u32 offset,
bfa_cb_fru_t cbfn, void *cbarg);
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 30df8a2..e3b9287 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -22,6 +22,8 @@
BFA_TRC_FILE(CNA, IOC_CB);
+#define bfa_ioc_cb_join_pos(__ioc) ((u32) (1 << BFA_IOC_CB_JOIN_SH))
+
/*
* forward declarations
*/
@@ -37,6 +39,12 @@ static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_set_cur_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_set_alt_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc);
static struct bfa_ioc_hwif_s hwif_cb;
@@ -59,6 +67,10 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave;
hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack;
hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete;
+ hwif_cb.ioc_set_fwstate = bfa_ioc_cb_set_cur_ioc_fwstate;
+ hwif_cb.ioc_get_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate;
+ hwif_cb.ioc_set_alt_fwstate = bfa_ioc_cb_set_alt_ioc_fwstate;
+ hwif_cb.ioc_get_alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate;
ioc->ioc_hwif = &hwif_cb;
}
@@ -187,6 +199,20 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
static bfa_boolean_t
bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc)
{
+ u32 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ /**
+ * Driver load time. If the join bit is set,
+ * it is due to an unclean exit by the driver for this
+ * PCI fn in the previous incarnation. Whoever comes here first
+ * should clean it up, no matter which PCI fn.
+ */
+ if (ioc_fwstate & BFA_IOC_CB_JOIN_MASK) {
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+ return BFA_TRUE;
+ }
+
return bfa_ioc_cb_sync_complete(ioc);
}
@@ -212,24 +238,66 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
static void
bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc)
{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 join_pos = bfa_ioc_cb_join_pos(ioc);
+
+ writel((r32 | join_pos), ioc->ioc_regs.ioc_fwstate);
}
static void
bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc)
{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 join_pos = bfa_ioc_cb_join_pos(ioc);
+
+ writel((r32 & ~join_pos), ioc->ioc_regs.ioc_fwstate);
+}
+
+static void
+bfa_ioc_cb_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+
+ writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)),
+ ioc->ioc_regs.ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state)(readl(ioc->ioc_regs.ioc_fwstate) &
+ BFA_IOC_CB_FWSTATE_MASK);
+}
+
+static void
+bfa_ioc_cb_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ u32 r32 = readl(ioc->ioc_regs.alt_ioc_fwstate);
+
+ writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)),
+ ioc->ioc_regs.alt_ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state)(readl(ioc->ioc_regs.alt_ioc_fwstate) &
+ BFA_IOC_CB_FWSTATE_MASK);
}
static void
bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc)
{
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_cb_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
}
static bfa_boolean_t
bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
{
- uint32_t fwstate, alt_fwstate;
- fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 fwstate, alt_fwstate;
+ fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc);
/*
* At this point, this IOC is hoding the hw sem in the
@@ -257,7 +325,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
fwstate == BFI_IOC_OP)
return BFA_TRUE;
else {
- alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate);
+ alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc);
if (alt_fwstate == BFI_IOC_FAIL ||
alt_fwstate == BFI_IOC_DISABLED ||
alt_fwstate == BFI_IOC_UNINIT ||
@@ -272,7 +340,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
bfa_status_t
bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
{
- u32 pll_sclk, pll_fclk;
+ u32 pll_sclk, pll_fclk, join_bits;
pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN |
__APP_PLL_SCLK_P0_1(3U) |
@@ -282,8 +350,12 @@ bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
__APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
__APP_PLL_LCLK_JITLMT0_1(3U) |
__APP_PLL_LCLK_CNTLMT0_1(3U);
- writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
- writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
+ join_bits = readl(rb + BFA_IOC0_STATE_REG) &
+ BFA_IOC_CB_JOIN_MASK;
+ writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC0_STATE_REG));
+ join_bits = readl(rb + BFA_IOC1_STATE_REG) &
+ BFA_IOC_CB_JOIN_MASK;
+ writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC1_STATE_REG));
writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index de4e726..bd53150 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -43,6 +43,12 @@ static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_set_cur_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_set_alt_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc);
static struct bfa_ioc_hwif_s hwif_ct;
static struct bfa_ioc_hwif_s hwif_ct2;
@@ -512,6 +518,10 @@ bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif)
hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
+ hwif->ioc_set_fwstate = bfa_ioc_ct_set_cur_ioc_fwstate;
+ hwif->ioc_get_fwstate = bfa_ioc_ct_get_cur_ioc_fwstate;
+ hwif->ioc_set_alt_fwstate = bfa_ioc_ct_set_alt_ioc_fwstate;
+ hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate;
}
/**
@@ -918,6 +928,16 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
}
}
+ /*
+ * The very first PCIe DMA Read done by LPU fails with a fatal error,
+ * when Address Translation Cache (ATC) has been enabled by system BIOS.
+ *
+ * Workaround:
+ * Disable Invalidated Tag Match Enable capability by setting the bit 26
+ * of CHIP_MISC_PRG to 0, by default it is set to 1.
+ */
+ r32 = readl(rb + CT2_CHIP_MISC_PRG);
+ writel((r32 & 0xfbffffff), (rb + CT2_CHIP_MISC_PRG));
/*
* Mask the interrupts and clear any
@@ -949,3 +969,29 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
return BFA_STATUS_OK;
}
+
+static void
+bfa_ioc_ct_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ writel(fwstate, ioc->ioc_regs.ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state)readl(ioc->ioc_regs.ioc_fwstate);
+}
+
+static void
+bfa_ioc_ct_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ writel(fwstate, ioc->ioc_regs.alt_ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state) readl(ioc->ioc_regs.alt_ioc_fwstate);
+}
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 299c1c8..6c41e57 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -70,6 +70,8 @@ enum bfa_fcport_sm_event {
BFA_FCPORT_SM_DPORTENABLE = 10, /* enable dport */
BFA_FCPORT_SM_DPORTDISABLE = 11,/* disable dport */
BFA_FCPORT_SM_FAA_MISCONFIG = 12, /* FAA misconfiguratin */
+ BFA_FCPORT_SM_DDPORTENABLE = 13, /* enable ddport */
+ BFA_FCPORT_SM_DDPORTDISABLE = 14, /* disable ddport */
};
/*
@@ -202,6 +204,8 @@ static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event);
static void bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
static void bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event);
@@ -234,6 +238,7 @@ static struct bfa_sm_table_s hal_port_sm_table[] = {
{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
+ {BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
{BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
};
@@ -1276,7 +1281,6 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
switch (event) {
case BFA_LPS_SM_FWRSP:
- case BFA_LPS_SM_OFFLINE:
if (lps->status == BFA_STATUS_OK) {
bfa_sm_set_state(lps, bfa_lps_sm_online);
if (lps->fdisc)
@@ -1305,6 +1309,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
bfa_lps_login_comp(lps);
break;
+ case BFA_LPS_SM_OFFLINE:
case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
@@ -1614,7 +1619,6 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
lps->lp_mac = rsp->lp_mac;
lps->brcd_switch = rsp->brcd_switch;
lps->fcf_mac = rsp->fcf_mac;
- lps->pr_bbscn = rsp->bb_scn;
break;
@@ -1744,7 +1748,6 @@ bfa_lps_send_login(struct bfa_lps_s *lps)
m->nwwn = lps->nwwn;
m->fdisc = lps->fdisc;
m->auth_en = lps->auth_en;
- m->bb_scn = lps->bb_scn;
bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
list_del(&lps->qe);
@@ -1940,7 +1943,7 @@ bfa_lps_delete(struct bfa_lps_s *lps)
*/
void
bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
- wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn)
+ wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
{
lps->uarg = uarg;
lps->alpa = alpa;
@@ -1949,7 +1952,6 @@ bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
lps->nwwn = nwwn;
lps->fdisc = BFA_FALSE;
lps->auth_en = auth_en;
- lps->bb_scn = bb_scn;
bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
}
@@ -2649,6 +2651,10 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
break;
+ case BFA_FCPORT_SM_DDPORTENABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2762,6 +2768,40 @@ bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
}
static void
+bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_DISABLE:
+ case BFA_FCPORT_SM_DDPORTDISABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ break;
+
+ case BFA_FCPORT_SM_DPORTENABLE:
+ case BFA_FCPORT_SM_DPORTDISABLE:
+ case BFA_FCPORT_SM_ENABLE:
+ case BFA_FCPORT_SM_START:
+ /**
+ * Ignore event for a port that is ddport
+ */
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event)
{
@@ -3082,6 +3122,8 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
port_cfg->qos_bw.med = BFA_QOS_BW_MED;
port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
+ fcport->fec_state = BFA_FEC_OFFLINE;
+
INIT_LIST_HEAD(&fcport->stats_pending_q);
INIT_LIST_HEAD(&fcport->statsclr_pending_q);
@@ -3158,6 +3200,11 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
fcport->qos_attr = pevent->link_state.qos_attr;
fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
+ if (fcport->cfg.bb_cr_enabled)
+ fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
+
+ fcport->fec_state = pevent->link_state.fec_state;
+
/*
* update trunk state if applicable
*/
@@ -3177,7 +3224,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
{
fcport->speed = BFA_PORT_SPEED_UNKNOWN;
fcport->topology = BFA_PORT_TOPOLOGY_NONE;
- fcport->bbsc_op_state = BFA_FALSE;
+ fcport->fec_state = BFA_FEC_OFFLINE;
}
/*
@@ -3629,6 +3676,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
fcport->qos_attr.qos_bw_op =
i2hmsg.penable_rsp->port_cfg.qos_bw;
+ if (fcport->cfg.bb_cr_enabled)
+ fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
+ else
+ fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
+
bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
}
break;
@@ -3639,6 +3691,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
break;
case BFI_FCPORT_I2H_EVENT:
+ if (fcport->cfg.bb_cr_enabled)
+ fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
+ else
+ fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
+
if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
else {
@@ -3846,6 +3903,8 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
return BFA_STATUS_LOOP_UNSUPP_MEZZ;
if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
return BFA_STATUS_DPORT_ERR;
+ if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
+ return BFA_STATUS_DPORT_ERR;
break;
case BFA_PORT_TOPOLOGY_AUTO:
@@ -3964,14 +4023,11 @@ bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
}
void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn)
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
- fcport->cfg.bb_scn = bb_scn;
- if (bb_scn)
- fcport->bbsc_op_state = BFA_TRUE;
}
/*
@@ -4021,7 +4077,8 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
- attr->bbsc_op_status = fcport->bbsc_op_state;
+
+ attr->fec_state = fcport->fec_state;
/* PBC Disabled State */
if (bfa_fcport_is_pbcdisabled(bfa))
@@ -4115,6 +4172,15 @@ bfa_fcport_is_dport(struct bfa_s *bfa)
BFA_PORT_ST_DPORT);
}
+bfa_boolean_t
+bfa_fcport_is_ddport(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+ BFA_PORT_ST_DDPORT);
+}
+
bfa_status_t
bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
{
@@ -4217,6 +4283,77 @@ bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
return fcport->cfg.trunked;
}
+bfa_status_t
+bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, on_off);
+
+ if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
+ return BFA_STATUS_BBCR_FC_ONLY;
+
+ if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
+ (bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
+ return BFA_STATUS_CMD_NOTSUPP_MEZZ;
+
+ if (on_off) {
+ if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
+ return BFA_STATUS_TOPOLOGY_LOOP;
+
+ if (fcport->cfg.qos_enabled)
+ return BFA_STATUS_ERROR_QOS_ENABLED;
+
+ if (fcport->cfg.trunked)
+ return BFA_STATUS_TRUNK_ENABLED;
+
+ if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
+ (fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
+ return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
+
+ if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
+ return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+
+ if (fcport->cfg.bb_cr_enabled) {
+ if (bb_scn != fcport->cfg.bb_scn)
+ return BFA_STATUS_BBCR_CFG_NO_CHANGE;
+ else
+ return BFA_STATUS_NO_CHANGE;
+ }
+
+ if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
+ bb_scn = BFA_BB_SCN_DEF;
+
+ fcport->cfg.bb_cr_enabled = on_off;
+ fcport->cfg.bb_scn = bb_scn;
+ } else {
+ if (!fcport->cfg.bb_cr_enabled)
+ return BFA_STATUS_NO_CHANGE;
+
+ fcport->cfg.bb_cr_enabled = on_off;
+ fcport->cfg.bb_scn = 0;
+ }
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
+ struct bfa_bbcr_attr_s *bbcr_attr)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
+ return BFA_STATUS_BBCR_FC_ONLY;
+
+ if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
+ return BFA_STATUS_TOPOLOGY_LOOP;
+
+ *bbcr_attr = fcport->bbcr_attr;
+
+ return BFA_STATUS_OK;
+}
+
void
bfa_fcport_dportenable(struct bfa_s *bfa)
{
@@ -4237,6 +4374,24 @@ bfa_fcport_dportdisable(struct bfa_s *bfa)
bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
}
+void
+bfa_fcport_ddportenable(struct bfa_s *bfa)
+{
+ /*
+ * Assume caller check for port is in disable state
+ */
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
+}
+
+void
+bfa_fcport_ddportdisable(struct bfa_s *bfa)
+{
+ /*
+ * Assume caller check for port is in disable state
+ */
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
+}
+
/*
* Rport State machine functions
*/
@@ -5622,6 +5777,14 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
* Dport forward declaration
*/
+enum bfa_dport_test_state_e {
+ BFA_DPORT_ST_DISABLED = 0, /*!< dport is disabled */
+ BFA_DPORT_ST_INP = 1, /*!< test in progress */
+ BFA_DPORT_ST_COMP = 2, /*!< test complete successfully */
+ BFA_DPORT_ST_NO_SFP = 3, /*!< sfp is not present */
+ BFA_DPORT_ST_NOTSTART = 4, /*!< test not start dport is enabled */
+};
+
/*
* BFA DPORT state machine events
*/
@@ -5631,6 +5794,9 @@ enum bfa_dport_sm_event {
BFA_DPORT_SM_FWRSP = 3, /* fw enable/disable rsp */
BFA_DPORT_SM_QRESUME = 4, /* CQ space available */
BFA_DPORT_SM_HWFAIL = 5, /* IOC h/w failure */
+ BFA_DPORT_SM_START = 6, /* re-start dport test */
+ BFA_DPORT_SM_REQFAIL = 7, /* request failure */
+ BFA_DPORT_SM_SCN = 8, /* state change notify frm fw */
};
static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
@@ -5645,9 +5811,19 @@ static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event);
static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
enum bfa_dport_sm_event event);
+static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
static void bfa_dport_qresume(void *cbarg);
static void bfa_dport_req_comp(struct bfa_dport_s *dport,
- bfi_diag_dport_rsp_t *msg);
+ struct bfi_diag_dport_rsp_s *msg);
+static void bfa_dport_scn(struct bfa_dport_s *dport,
+ struct bfi_diag_dport_scn_s *msg);
/*
* BFA fcdiag module
@@ -5689,6 +5865,8 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
dport->cbfn = NULL;
dport->cbarg = NULL;
+ dport->test_state = BFA_DPORT_ST_DISABLED;
+ memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
}
static void
@@ -5891,7 +6069,12 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
break;
case BFI_DIAG_I2H_DPORT:
- bfa_dport_req_comp(&fcdiag->dport, (bfi_diag_dport_rsp_t *)msg);
+ bfa_dport_req_comp(&fcdiag->dport,
+ (struct bfi_diag_dport_rsp_s *)msg);
+ break;
+ case BFI_DIAG_I2H_DPORT_SCN:
+ bfa_dport_scn(&fcdiag->dport,
+ (struct bfi_diag_dport_scn_s *)msg);
break;
default:
bfa_trc(fcdiag, msg->mhdr.msg_id);
@@ -5986,7 +6169,11 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
return BFA_STATUS_UNSUPP_SPEED;
}
}
-
+ /* check to see if fcport is dport */
+ if (bfa_fcport_is_dport(bfa)) {
+ bfa_trc(fcdiag, fcdiag->lb.lock);
+ return BFA_STATUS_DPORT_ENABLED;
+ }
/* check to see if there is another destructive diag cmd running */
if (fcdiag->lb.lock) {
bfa_trc(fcdiag, fcdiag->lb.lock);
@@ -6090,6 +6277,15 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
/*
* D-port
*/
+#define bfa_dport_result_start(__dport, __mode) do { \
+ (__dport)->result.start_time = bfa_get_log_time(); \
+ (__dport)->result.status = DPORT_TEST_ST_INPRG; \
+ (__dport)->result.mode = (__mode); \
+ (__dport)->result.rp_pwwn = (__dport)->rp_pwwn; \
+ (__dport)->result.rp_nwwn = (__dport)->rp_nwwn; \
+ (__dport)->result.lpcnt = (__dport)->lpcnt; \
+} while (0)
+
static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
enum bfi_dport_req req);
static void
@@ -6124,6 +6320,18 @@ bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
/* ignore */
break;
+ case BFA_DPORT_SM_SCN:
+ if (dport->i2hmsg.scn.state == BFI_DPORT_SCN_DDPORT_ENABLE) {
+ bfa_fcport_ddportenable(dport->bfa);
+ dport->dynamic = BFA_TRUE;
+ dport->test_state = BFA_DPORT_ST_NOTSTART;
+ bfa_sm_set_state(dport, bfa_dport_sm_enabled);
+ } else {
+ bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
+ WARN_ON(1);
+ }
+ break;
+
default:
bfa_sm_fault(dport->bfa, event);
}
@@ -6159,9 +6367,23 @@ bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
switch (event) {
case BFA_DPORT_SM_FWRSP:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
+ dport->test_state = BFA_DPORT_ST_NO_SFP;
+ } else {
+ dport->test_state = BFA_DPORT_ST_INP;
+ bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
+ }
bfa_sm_set_state(dport, bfa_dport_sm_enabled);
break;
+ case BFA_DPORT_SM_REQFAIL:
+ dport->test_state = BFA_DPORT_ST_DISABLED;
+ bfa_fcport_dportdisable(dport->bfa);
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ break;
+
case BFA_DPORT_SM_HWFAIL:
bfa_sm_set_state(dport, bfa_dport_sm_disabled);
bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
@@ -6178,8 +6400,11 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
bfa_trc(dport->bfa, event);
switch (event) {
- case BFA_DPORT_SM_ENABLE:
- /* Already enabled */
+ case BFA_DPORT_SM_START:
+ if (bfa_dport_send_req(dport, BFI_DPORT_START))
+ bfa_sm_set_state(dport, bfa_dport_sm_starting);
+ else
+ bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
break;
case BFA_DPORT_SM_DISABLE:
@@ -6194,6 +6419,48 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
bfa_sm_set_state(dport, bfa_dport_sm_disabled);
break;
+ case BFA_DPORT_SM_SCN:
+ switch (dport->i2hmsg.scn.state) {
+ case BFI_DPORT_SCN_TESTCOMP:
+ dport->test_state = BFA_DPORT_ST_COMP;
+ break;
+
+ case BFI_DPORT_SCN_TESTSTART:
+ dport->test_state = BFA_DPORT_ST_INP;
+ break;
+
+ case BFI_DPORT_SCN_TESTSKIP:
+ case BFI_DPORT_SCN_SUBTESTSTART:
+ /* no state change */
+ break;
+
+ case BFI_DPORT_SCN_SFP_REMOVED:
+ dport->test_state = BFA_DPORT_ST_NO_SFP;
+ break;
+
+ case BFI_DPORT_SCN_DDPORT_DISABLE:
+ bfa_fcport_ddportdisable(dport->bfa);
+
+ if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
+ bfa_sm_set_state(dport,
+ bfa_dport_sm_dynamic_disabling);
+ else
+ bfa_sm_set_state(dport,
+ bfa_dport_sm_dynamic_disabling_qwait);
+ break;
+
+ case BFI_DPORT_SCN_FCPORT_DISABLE:
+ bfa_fcport_ddportdisable(dport->bfa);
+
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ dport->dynamic = BFA_FALSE;
+ break;
+
+ default:
+ bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
+ bfa_sm_fault(dport->bfa, event);
+ }
+ break;
default:
bfa_sm_fault(dport->bfa, event);
}
@@ -6217,6 +6484,10 @@ bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
break;
+ case BFA_DPORT_SM_SCN:
+ /* ignore */
+ break;
+
default:
bfa_sm_fault(dport->bfa, event);
}
@@ -6229,7 +6500,98 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
switch (event) {
case BFA_DPORT_SM_FWRSP:
+ dport->test_state = BFA_DPORT_ST_DISABLED;
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ /* no state change */
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_QRESUME:
+ bfa_sm_set_state(dport, bfa_dport_sm_starting);
+ bfa_dport_send_req(dport, BFI_DPORT_START);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_reqq_wcancel(&dport->reqq_wait);
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_FWRSP:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
+ dport->test_state = BFA_DPORT_ST_NO_SFP;
+ } else {
+ dport->test_state = BFA_DPORT_ST_INP;
+ bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
+ }
+ /* fall thru */
+
+ case BFA_DPORT_SM_REQFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_enabled);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_SCN:
+ switch (dport->i2hmsg.scn.state) {
+ case BFI_DPORT_SCN_DDPORT_DISABLED:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ dport->dynamic = BFA_FALSE;
+ bfa_fcport_enable(dport->bfa);
+ break;
+
+ default:
+ bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
+ bfa_sm_fault(dport->bfa, event);
+
+ }
break;
case BFA_DPORT_SM_HWFAIL:
@@ -6242,6 +6604,32 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
}
}
+static void
+bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_QRESUME:
+ bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
+ bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_reqq_wcancel(&dport->reqq_wait);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ /* ignore */
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
static bfa_boolean_t
bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
@@ -6249,12 +6637,6 @@ bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
struct bfi_diag_dport_req_s *m;
/*
- * Increment message tag before queue check, so that responses to old
- * requests are discarded.
- */
- dport->msgtag++;
-
- /*
* check for room in queue to send request now
*/
m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
@@ -6266,7 +6648,10 @@ bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
bfa_fn_lpu(dport->bfa));
m->req = req;
- m->msgtag = dport->msgtag;
+ if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
+ m->lpcnt = cpu_to_be32(dport->lpcnt);
+ m->payload = cpu_to_be32(dport->payload);
+ }
/*
* queue I/O message to firmware
@@ -6285,19 +6670,131 @@ bfa_dport_qresume(void *cbarg)
}
static void
-bfa_dport_req_comp(struct bfa_dport_s *dport, bfi_diag_dport_rsp_t *msg)
+bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
{
- bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
+ msg->status = cpu_to_be32(msg->status);
+ dport->i2hmsg.rsp.status = msg->status;
+ dport->rp_pwwn = msg->pwwn;
+ dport->rp_nwwn = msg->nwwn;
+
+ if ((msg->status == BFA_STATUS_OK) ||
+ (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
+ bfa_trc(dport->bfa, msg->status);
+ bfa_trc(dport->bfa, dport->rp_pwwn);
+ bfa_trc(dport->bfa, dport->rp_nwwn);
+ bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
+
+ } else {
+ bfa_trc(dport->bfa, msg->status);
+ bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
+ }
bfa_cb_fcdiag_dport(dport, msg->status);
}
+static bfa_boolean_t
+bfa_dport_is_sending_req(struct bfa_dport_s *dport)
+{
+ if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_starting) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
+ return BFA_TRUE;
+ } else {
+ return BFA_FALSE;
+ }
+}
+
+static void
+bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
+{
+ int i;
+ uint8_t subtesttype;
+
+ bfa_trc(dport->bfa, msg->state);
+ dport->i2hmsg.scn.state = msg->state;
+
+ switch (dport->i2hmsg.scn.state) {
+ case BFI_DPORT_SCN_TESTCOMP:
+ dport->result.end_time = bfa_get_log_time();
+ bfa_trc(dport->bfa, dport->result.end_time);
+
+ dport->result.status = msg->info.testcomp.status;
+ bfa_trc(dport->bfa, dport->result.status);
+
+ dport->result.roundtrip_latency =
+ cpu_to_be32(msg->info.testcomp.latency);
+ dport->result.est_cable_distance =
+ cpu_to_be32(msg->info.testcomp.distance);
+ dport->result.buffer_required =
+ be16_to_cpu(msg->info.testcomp.numbuffer);
+
+ dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
+ dport->result.speed = msg->info.testcomp.speed;
+
+ bfa_trc(dport->bfa, dport->result.roundtrip_latency);
+ bfa_trc(dport->bfa, dport->result.est_cable_distance);
+ bfa_trc(dport->bfa, dport->result.buffer_required);
+ bfa_trc(dport->bfa, dport->result.frmsz);
+ bfa_trc(dport->bfa, dport->result.speed);
+
+ for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
+ dport->result.subtest[i].status =
+ msg->info.testcomp.subtest_status[i];
+ bfa_trc(dport->bfa, dport->result.subtest[i].status);
+ }
+ break;
+
+ case BFI_DPORT_SCN_TESTSKIP:
+ case BFI_DPORT_SCN_DDPORT_ENABLE:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ break;
+
+ case BFI_DPORT_SCN_TESTSTART:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ dport->rp_pwwn = msg->info.teststart.pwwn;
+ dport->rp_nwwn = msg->info.teststart.nwwn;
+ dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
+ bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
+ break;
+
+ case BFI_DPORT_SCN_SUBTESTSTART:
+ subtesttype = msg->info.teststart.type;
+ dport->result.subtest[subtesttype].start_time =
+ bfa_get_log_time();
+ dport->result.subtest[subtesttype].status =
+ DPORT_TEST_ST_INPRG;
+
+ bfa_trc(dport->bfa, subtesttype);
+ bfa_trc(dport->bfa,
+ dport->result.subtest[subtesttype].start_time);
+ break;
+
+ case BFI_DPORT_SCN_SFP_REMOVED:
+ case BFI_DPORT_SCN_DDPORT_DISABLED:
+ case BFI_DPORT_SCN_DDPORT_DISABLE:
+ case BFI_DPORT_SCN_FCPORT_DISABLE:
+ dport->result.status = DPORT_TEST_ST_IDLE;
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, msg->state);
+ }
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
+}
+
/*
* Dport enable
*
* @param[in] *bfa - bfa data struct
*/
bfa_status_t
-bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
+bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg)
{
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
struct bfa_dport_s *dport = &fcdiag->dport;
@@ -6311,6 +6808,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
}
/*
+ * Dport is supported in CT2 or above
+ */
+ if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
+ bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
+ return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+ }
+
+ /*
* Check to see if IOC is down
*/
if (!bfa_iocfc_is_operational(bfa))
@@ -6348,6 +6853,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
}
/*
+ * Check if diag loopback is running
+ */
+ if (bfa_fcdiag_lb_is_running(bfa)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DIAG_BUSY;
+ }
+
+ /*
* Check to see if port is disable or in dport state
*/
if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
@@ -6357,14 +6870,16 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
}
/*
+ * Check if dport is in dynamic mode
+ */
+ if (dport->dynamic)
+ return BFA_STATUS_DDPORT_ERR;
+
+ /*
* Check if dport is busy
*/
- if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait)) {
+ if (bfa_dport_is_sending_req(dport))
return BFA_STATUS_DEVBUSY;
- }
/*
* Check if dport is already enabled
@@ -6374,6 +6889,10 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
return BFA_STATUS_DPORT_ENABLED;
}
+ bfa_trc(dport->bfa, lpcnt);
+ bfa_trc(dport->bfa, pat);
+ dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
+ dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
dport->cbfn = cbfn;
dport->cbarg = cbarg;
@@ -6402,6 +6921,13 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
}
/*
+ * Check if dport is in dynamic mode
+ */
+ if (dport->dynamic) {
+ return BFA_STATUS_DDPORT_ERR;
+ }
+
+ /*
* Check to see if port is disable or in dport state
*/
if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
@@ -6413,10 +6939,7 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
/*
* Check if dport is busy
*/
- if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
+ if (bfa_dport_is_sending_req(dport))
return BFA_STATUS_DEVBUSY;
/*
@@ -6435,30 +6958,105 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
}
/*
- * Get D-port state
+ * Dport start -- restart dport test
*
- * @param[in] *bfa - bfa data struct
+ * @param[in] *bfa - bfa data struct
*/
+bfa_status_t
+bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
+ /*
+ * Check to see if IOC is down
+ */
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /*
+ * Check if dport is in dynamic mode
+ */
+ if (dport->dynamic)
+ return BFA_STATUS_DDPORT_ERR;
+
+ /*
+ * Check if dport is busy
+ */
+ if (bfa_dport_is_sending_req(dport))
+ return BFA_STATUS_DEVBUSY;
+ /*
+ * Check if dport is in enabled state.
+ * Test can only be restart when previous test has completed
+ */
+ if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DPORT_DISABLED;
+
+ } else {
+ if (dport->test_state == BFA_DPORT_ST_NO_SFP)
+ return BFA_STATUS_DPORT_INV_SFP;
+
+ if (dport->test_state == BFA_DPORT_ST_INP)
+ return BFA_STATUS_DEVBUSY;
+
+ WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
+ }
+
+ bfa_trc(dport->bfa, lpcnt);
+ bfa_trc(dport->bfa, pat);
+
+ dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
+ dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
+
+ dport->cbfn = cbfn;
+ dport->cbarg = cbarg;
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_START);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Dport show -- return dport test result
+ *
+ * @param[in] *bfa - bfa data struct
+ */
bfa_status_t
-bfa_dport_get_state(struct bfa_s *bfa, enum bfa_dport_state *state)
+bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
{
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
struct bfa_dport_s *dport = &fcdiag->dport;
- if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled))
- *state = BFA_DPORT_ST_ENABLED;
- else if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait))
- *state = BFA_DPORT_ST_ENABLING;
- else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled))
- *state = BFA_DPORT_ST_DISABLED;
- else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
- bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
- *state = BFA_DPORT_ST_DISABLING;
- else {
- bfa_trc(dport->bfa, BFA_STATUS_EINVAL);
- return BFA_STATUS_EINVAL;
+ /*
+ * Check to see if IOC is down
+ */
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /*
+ * Check if dport is busy
+ */
+ if (bfa_dport_is_sending_req(dport))
+ return BFA_STATUS_DEVBUSY;
+
+ /*
+ * Check if dport is in enabled state.
+ */
+ if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DPORT_DISABLED;
+
}
+
+ /*
+ * Check if there is SFP
+ */
+ if (dport->test_state == BFA_DPORT_ST_NO_SFP)
+ return BFA_STATUS_DPORT_INV_SFP;
+
+ memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
+
return BFA_STATUS_OK;
}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index 8d7fbec..ef07365 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -405,8 +405,6 @@ struct bfa_lps_s {
bfa_status_t status; /* login status */
u16 pdusz; /* max receive PDU size */
u16 pr_bbcred; /* BB_CREDIT from peer */
- u8 pr_bbscn; /* BB_SCN from peer */
- u8 bb_scn; /* local BB_SCN */
u8 lsrjt_rsn; /* LSRJT reason */
u8 lsrjt_expl; /* LSRJT explanation */
u8 lun_mask; /* LUN mask flag */
@@ -510,11 +508,12 @@ struct bfa_fcport_s {
bfa_boolean_t diag_busy; /* diag busy status */
bfa_boolean_t beacon; /* port beacon status */
bfa_boolean_t link_e2e_beacon; /* link beacon status */
- bfa_boolean_t bbsc_op_state; /* Cred recov Oper State */
struct bfa_fcport_trunk_s trunk;
u16 fcoe_vlan;
struct bfa_mem_dma_s fcport_dma;
bfa_boolean_t stats_dma_ready;
+ struct bfa_bbcr_attr_s bbcr_attr;
+ enum bfa_fec_state_s fec_state;
};
#define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport)
@@ -552,11 +551,12 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
enum bfa_port_linkstate event), void *event_cbarg);
bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_ddport(struct bfa_s *bfa);
bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa,
struct bfa_qos_bw_s *qos_bw);
enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
bfa_boolean_t link_e2e_beacon);
@@ -571,6 +571,10 @@ void bfa_fcport_dportenable(struct bfa_s *bfa);
void bfa_fcport_dportdisable(struct bfa_s *bfa);
bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state);
+bfa_status_t bfa_fcport_cfg_bbcr(struct bfa_s *bfa,
+ bfa_boolean_t on_off, u8 bb_scn);
+bfa_status_t bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
+ struct bfa_bbcr_attr_s *bbcr_attr);
/*
* bfa rport API functions
@@ -667,7 +671,7 @@ struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
void bfa_lps_delete(struct bfa_lps_s *lps);
void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
u16 pdusz, wwn_t pwwn, wwn_t nwwn,
- bfa_boolean_t auth_en, u8 bb_scn);
+ bfa_boolean_t auth_en);
void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
wwn_t pwwn, wwn_t nwwn);
void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
@@ -712,10 +716,18 @@ struct bfa_fcdiag_lb_s {
struct bfa_dport_s {
struct bfa_s *bfa; /* Back pointer to BFA */
bfa_sm_t sm; /* finite state machine */
- u32 msgtag; /* firmware msg tag for reply */
struct bfa_reqq_wait_s reqq_wait;
bfa_cb_diag_t cbfn;
void *cbarg;
+ union bfi_diag_dport_msg_u i2hmsg;
+ u8 test_state; /* enum dport_test_state */
+ u8 dynamic; /* boolean_t */
+ u8 rsvd[2];
+ u32 lpcnt;
+ u32 payload; /* user defined payload pattern */
+ wwn_t rp_pwwn;
+ wwn_t rp_nwwn;
+ struct bfa_diag_dport_result_s result;
};
struct bfa_fcdiag_s {
@@ -739,11 +751,13 @@ bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
u32 queue, struct bfa_diag_qtest_result_s *result,
bfa_cb_diag_t cbfn, void *cbarg);
bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
-bfa_status_t bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn,
- void *cbarg);
+bfa_status_t bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg);
bfa_status_t bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn,
void *cbarg);
-bfa_status_t bfa_dport_get_state(struct bfa_s *bfa,
- enum bfa_dport_state *state);
+bfa_status_t bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_dport_show(struct bfa_s *bfa,
+ struct bfa_diag_dport_result_s *result);
#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 895b0e5..9611195 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -63,9 +63,9 @@ int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
u32 *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
-#define BFAD_FW_FILE_CB "cbfw-3.1.0.0.bin"
-#define BFAD_FW_FILE_CT "ctfw-3.1.0.0.bin"
-#define BFAD_FW_FILE_CT2 "ct2fw-3.1.0.0.bin"
+#define BFAD_FW_FILE_CB "cbfw-3.2.1.0.bin"
+#define BFAD_FW_FILE_CT "ctfw-3.2.1.0.bin"
+#define BFAD_FW_FILE_CT2 "ct2fw-3.2.1.0.bin"
static u32 *bfad_load_fwimg(struct pci_dev *pdev);
static void bfad_free_fwimg(void);
@@ -1034,7 +1034,7 @@ bfad_start_ops(struct bfad_s *bfad) {
sizeof(driver_info.host_os_patch) - 1);
strncpy(driver_info.os_device_name, bfad->pci_name,
- sizeof(driver_info.os_device_name - 1));
+ sizeof(driver_info.os_device_name) - 1);
/* FCS driver info init */
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -1720,6 +1720,14 @@ struct pci_device_id bfad_id_table[] = {
.class_mask = ~0,
},
+ {
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_CT2_QUAD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_SERIAL_FIBER << 8),
+ .class_mask = ~0,
+ },
{0, 0},
};
@@ -1739,7 +1747,7 @@ static struct pci_driver bfad_pci_driver = {
.name = BFAD_DRIVER_NAME,
.id_table = bfad_id_table,
.probe = bfad_pci_probe,
- .remove = __devexit_p(bfad_pci_remove),
+ .remove = bfad_pci_remove,
.err_handler = &bfad_err_handler,
};
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 72f5dc3..e9a681d 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -335,23 +335,10 @@ bfad_im_reset_stats(struct Scsi_Host *shost)
}
/*
- * FC transport template entry, get rport loss timeout.
- */
-static void
-bfad_im_get_rport_loss_tmo(struct fc_rport *rport)
-{
- struct bfad_itnim_data_s *itnim_data = rport->dd_data;
- struct bfad_itnim_s *itnim = itnim_data->itnim;
- struct bfad_s *bfad = itnim->im->bfad;
- unsigned long flags;
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-}
-
-/*
* FC transport template entry, set rport loss timeout.
+ * Update dev_loss_tmo based on the value pushed down by the stack
+ * In case it is lesser than path_tov of driver, set it to path_tov + 1
+ * to ensure that the driver times out before the application
*/
static void
bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
@@ -359,15 +346,11 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
struct bfad_itnim_data_s *itnim_data = rport->dd_data;
struct bfad_itnim_s *itnim = itnim_data->itnim;
struct bfad_s *bfad = itnim->im->bfad;
- unsigned long flags;
-
- if (timeout > 0) {
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcpim_path_tov_set(&bfad->bfa, timeout);
- rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- }
+ uint16_t path_tov = bfa_fcpim_path_tov_get(&bfad->bfa);
+ rport->dev_loss_tmo = timeout;
+ if (timeout < path_tov)
+ rport->dev_loss_tmo = path_tov + 1;
}
static int
@@ -665,7 +648,6 @@ struct fc_function_template bfad_im_fc_function_template = {
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_rport_dev_loss_tmo = 1,
- .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
.issue_fc_host_lip = bfad_im_issue_fc_host_lip,
.vport_create = bfad_im_vport_create,
@@ -723,7 +705,6 @@ struct fc_function_template bfad_im_vport_fc_function_template = {
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_rport_dev_loss_tmo = 1,
- .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
};
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 555e7db..0467c34 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -402,25 +402,43 @@ bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd)
}
int
-bfad_iocmd_port_cfg_bbsc(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
- struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
- unsigned long flags;
+ struct bfa_bsg_bbcr_enable_s *iocmd =
+ (struct bfa_bsg_bbcr_enable_s *)pcmd;
+ unsigned long flags;
+ int rc;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
- if (v_cmd == IOCMD_PORT_BBSC_ENABLE)
- fcport->cfg.bb_scn_state = BFA_TRUE;
- else if (v_cmd == IOCMD_PORT_BBSC_DISABLE)
- fcport->cfg.bb_scn_state = BFA_FALSE;
+ if (cmd == IOCMD_PORT_BBCR_ENABLE)
+ rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_TRUE, iocmd->bb_scn);
+ else if (cmd == IOCMD_PORT_BBCR_DISABLE)
+ rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_FALSE, 0);
+ else {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return -EINVAL;
}
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
+ iocmd->status = rc;
+ return 0;
+}
+
+int
+bfad_iocmd_port_get_bbcr_attr(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_bbcr_attr_s *iocmd = (struct bfa_bsg_bbcr_attr_s *) pcmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status =
+ bfa_fcport_get_bbcr_attr(&bfad->bfa, &iocmd->attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
return 0;
}
+
static int
bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
{
@@ -1767,51 +1785,87 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
}
int
-bfad_iocmd_diag_cfg_dport(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd)
{
- struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+ struct bfa_bsg_dport_enable_s *iocmd =
+ (struct bfa_bsg_dport_enable_s *)pcmd;
unsigned long flags;
struct bfad_hal_comp fcomp;
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (cmd == IOCMD_DIAG_DPORT_ENABLE)
- iocmd->status = bfa_dport_enable(&bfad->bfa,
- bfad_hcb_comp, &fcomp);
- else if (cmd == IOCMD_DIAG_DPORT_DISABLE)
- iocmd->status = bfa_dport_disable(&bfad->bfa,
- bfad_hcb_comp, &fcomp);
+ iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->lpcnt,
+ iocmd->pat, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ bfa_trc(bfad, iocmd->status);
else {
- bfa_trc(bfad, 0);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- return -EINVAL;
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
}
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+int
+bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK)
bfa_trc(bfad, iocmd->status);
else {
wait_for_completion(&fcomp.comp);
iocmd->status = fcomp.status;
}
+ return 0;
+}
+
+int
+bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_dport_enable_s *iocmd =
+ (struct bfa_bsg_dport_enable_s *)pcmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_start(&bfad->bfa, iocmd->lpcnt,
+ iocmd->pat, bfad_hcb_comp,
+ &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK) {
+ bfa_trc(bfad, iocmd->status);
+ } else {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
return 0;
}
int
-bfad_iocmd_diag_dport_get_state(struct bfad_s *bfad, void *pcmd)
+bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd)
{
- struct bfa_bsg_diag_dport_get_state_s *iocmd =
- (struct bfa_bsg_diag_dport_get_state_s *)pcmd;
- unsigned long flags;
+ struct bfa_bsg_diag_dport_show_s *iocmd =
+ (struct bfa_bsg_diag_dport_show_s *)pcmd;
+ unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- iocmd->status = bfa_dport_get_state(&bfad->bfa, &iocmd->state);
+ iocmd->status = bfa_dport_show(&bfad->bfa, &iocmd->result);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return 0;
}
+
int
bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
{
@@ -2662,7 +2716,7 @@ bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_fruvpd_update(BFA_FRU(&bfad->bfa),
&iocmd->data, iocmd->len, iocmd->offset,
- bfad_hcb_comp, &fcomp);
+ bfad_hcb_comp, &fcomp, iocmd->trfr_cmpl);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status == BFA_STATUS_OK) {
wait_for_completion(&fcomp.comp);
@@ -2750,9 +2804,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_PORT_CFG_MAXFRSZ:
rc = bfad_iocmd_port_cfg_maxfrsize(bfad, iocmd);
break;
- case IOCMD_PORT_BBSC_ENABLE:
- case IOCMD_PORT_BBSC_DISABLE:
- rc = bfad_iocmd_port_cfg_bbsc(bfad, iocmd, cmd);
+ case IOCMD_PORT_BBCR_ENABLE:
+ case IOCMD_PORT_BBCR_DISABLE:
+ rc = bfad_iocmd_port_cfg_bbcr(bfad, cmd, iocmd);
+ break;
+ case IOCMD_PORT_BBCR_GET_ATTR:
+ rc = bfad_iocmd_port_get_bbcr_attr(bfad, iocmd);
break;
case IOCMD_LPORT_GET_ATTR:
rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
@@ -2913,11 +2970,16 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
break;
case IOCMD_DIAG_DPORT_ENABLE:
+ rc = bfad_iocmd_diag_dport_enable(bfad, iocmd);
+ break;
case IOCMD_DIAG_DPORT_DISABLE:
- rc = bfad_iocmd_diag_cfg_dport(bfad, cmd, iocmd);
+ rc = bfad_iocmd_diag_dport_disable(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_DPORT_SHOW:
+ rc = bfad_iocmd_diag_dport_show(bfad, iocmd);
break;
- case IOCMD_DIAG_DPORT_GET_STATE:
- rc = bfad_iocmd_diag_dport_get_state(bfad, iocmd);
+ case IOCMD_DIAG_DPORT_START:
+ rc = bfad_iocmd_diag_dport_start(bfad, iocmd);
break;
case IOCMD_PHY_GET_ATTR:
rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
@@ -3309,7 +3371,8 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
goto out;
}
- if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload,
+ if (copy_from_user((uint8_t *)bsg_fcpt,
+ (void *)(unsigned long)bsg_data->payload,
bsg_data->payload_len)) {
kfree(bsg_fcpt);
rc = -EIO;
@@ -3463,8 +3526,8 @@ out_free_mem:
kfree(rsp_kbuf);
/* Need a copy to user op */
- if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt,
- bsg_data->payload_len))
+ if (copy_to_user((void *)(unsigned long)bsg_data->payload,
+ (void *)bsg_fcpt, bsg_data->payload_len))
rc = -EIO;
kfree(bsg_fcpt);
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 15e1fc8..05f0fc9 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -46,8 +46,9 @@ enum {
IOCMD_PORT_CFG_ALPA,
IOCMD_PORT_CFG_MAXFRSZ,
IOCMD_PORT_CLR_ALPA,
- IOCMD_PORT_BBSC_ENABLE,
- IOCMD_PORT_BBSC_DISABLE,
+ IOCMD_PORT_BBCR_ENABLE,
+ IOCMD_PORT_BBCR_DISABLE,
+ IOCMD_PORT_BBCR_GET_ATTR,
IOCMD_LPORT_GET_ATTR,
IOCMD_LPORT_GET_RPORTS,
IOCMD_LPORT_GET_STATS,
@@ -143,7 +144,6 @@ enum {
IOCMD_FCPIM_LUNMASK_DELETE,
IOCMD_DIAG_DPORT_ENABLE,
IOCMD_DIAG_DPORT_DISABLE,
- IOCMD_DIAG_DPORT_GET_STATE,
IOCMD_QOS_SET_BW,
IOCMD_FCPIM_THROTTLE_QUERY,
IOCMD_FCPIM_THROTTLE_SET,
@@ -152,6 +152,8 @@ enum {
IOCMD_FRUVPD_READ,
IOCMD_FRUVPD_UPDATE,
IOCMD_FRUVPD_GET_MAX_SIZE,
+ IOCMD_DIAG_DPORT_SHOW,
+ IOCMD_DIAG_DPORT_START,
};
struct bfa_bsg_gen_s {
@@ -495,6 +497,20 @@ struct bfa_bsg_port_cfg_mode_s {
struct bfa_port_cfg_mode_s cfg;
};
+struct bfa_bsg_bbcr_enable_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u8 bb_scn;
+ u8 rsvd;
+};
+
+struct bfa_bsg_bbcr_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_bbcr_attr_s attr;
+};
+
struct bfa_bsg_faa_attr_s {
bfa_status_t status;
u16 bfad_num;
@@ -578,6 +594,21 @@ struct bfa_bsg_diag_loopback_s {
struct bfa_diag_loopback_result_s result;
};
+struct bfa_bsg_diag_dport_show_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_diag_dport_result_s result;
+};
+
+struct bfa_bsg_dport_enable_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u16 lpcnt;
+ u16 pat;
+};
+
struct bfa_bsg_diag_fwping_s {
bfa_status_t status;
u16 bfad_num;
@@ -625,13 +656,6 @@ struct bfa_bsg_diag_lb_stat_s {
u16 rsvd;
};
-struct bfa_bsg_diag_dport_get_state_s {
- bfa_status_t status;
- u16 bfad_num;
- u16 rsvd;
- enum bfa_dport_state state;
-};
-
struct bfa_bsg_phy_attr_s {
bfa_status_t status;
u16 bfad_num;
@@ -770,10 +794,12 @@ struct bfa_bsg_tfru_s {
struct bfa_bsg_fruvpd_s {
bfa_status_t status;
u16 bfad_num;
- u16 rsvd;
+ u16 rsvd1;
u32 offset;
u32 len;
u8 data[BFA_MAX_FRUVPD_TRANSFER_SIZE];
+ u8 trfr_cmpl;
+ u8 rsvd2[3];
};
struct bfa_bsg_fruvpd_max_size_s {
@@ -795,10 +821,12 @@ struct bfa_bsg_fcpt_s {
};
#define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s
+#pragma pack(1)
struct bfa_bsg_data {
int payload_len;
- void *payload;
+ u64 payload;
};
+#pragma pack()
#define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz) \
(((__payload_len) != ((__hdrsz) + (__bufsz))) ? \
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 439c012..8e83d04 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -173,31 +173,9 @@ bfad_debugfs_open_reg(struct inode *inode, struct file *file)
static loff_t
bfad_debugfs_lseek(struct file *file, loff_t offset, int orig)
{
- struct bfad_debug_info *debug;
- loff_t pos = file->f_pos;
-
- debug = file->private_data;
-
- switch (orig) {
- case 0:
- file->f_pos = offset;
- break;
- case 1:
- file->f_pos += offset;
- break;
- case 2:
- file->f_pos = debug->buffer_len - offset;
- break;
- default:
- return -EINVAL;
- }
-
- if (file->f_pos < 0 || file->f_pos > debug->buffer_len) {
- file->f_pos = pos;
- return -EINVAL;
- }
-
- return file->f_pos;
+ struct bfad_debug_info *debug = file->private_data;
+ return fixed_size_llseek(file, offset, orig,
+ debug->buffer_len);
}
static ssize_t
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 0c64a04..78d3401 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -57,7 +57,7 @@
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
-#define BFAD_DRIVER_VERSION "3.1.2.1"
+#define BFAD_DRIVER_VERSION "3.2.21.1"
#endif
#define BFAD_PROTO_NAME FCPI_NAME
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 8f92732..9796284 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -523,20 +523,13 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
int error = 1;
mutex_lock(&bfad_mutex);
- if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) {
+ error = idr_alloc(&bfad_im_port_index, im_port, 0, 0, GFP_KERNEL);
+ if (error < 0) {
mutex_unlock(&bfad_mutex);
- printk(KERN_WARNING "idr_pre_get failure\n");
+ printk(KERN_WARNING "idr_alloc failure\n");
goto out;
}
-
- error = idr_get_new(&bfad_im_port_index, im_port,
- &im_port->idr_id);
- if (error) {
- mutex_unlock(&bfad_mutex);
- printk(KERN_WARNING "idr_get_new failure\n");
- goto out;
- }
-
+ im_port->idr_id = error;
mutex_unlock(&bfad_mutex);
im_port->shost = bfad_scsi_host_alloc(im_port, bfad);
@@ -951,13 +944,15 @@ static int
bfad_im_slave_alloc(struct scsi_device *sdev)
{
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
- struct bfad_itnim_data_s *itnim_data =
- (struct bfad_itnim_data_s *) rport->dd_data;
- struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
+ struct bfad_itnim_data_s *itnim_data;
+ struct bfa_s *bfa;
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
+ itnim_data = (struct bfad_itnim_data_s *) rport->dd_data;
+ bfa = itnim_data->itnim->bfa_itnim->bfa;
+
if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) {
/*
* We should not mask LUN 0 - since this will translate
@@ -1042,7 +1037,7 @@ bfad_fc_host_init(struct bfad_im_port_s *im_port)
/* For fibre channel services type 0x20 */
fc_host_supported_fc4s(host)[7] = 1;
- strncpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
+ strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
BFA_SYMNAME_MAXLEN);
sprintf(fc_host_symbolic_name(host), "%s", symname);
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 57b146b..37bd256 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -264,6 +264,7 @@ struct bfi_ioc_getattr_req_s {
union bfi_addr_u attr_addr;
};
+#define BFI_IOC_ATTR_UUID_SZ 16
struct bfi_ioc_attr_s {
wwn_t mfg_pwwn; /* Mfg port wwn */
wwn_t mfg_nwwn; /* Mfg node wwn */
@@ -292,6 +293,7 @@ struct bfi_ioc_attr_s {
u8 mfg_day; /* manufacturing day */
u8 mfg_month; /* manufacturing month */
u16 mfg_year; /* manufacturing year */
+ u8 uuid[BFI_IOC_ATTR_UUID_SZ]; /*!< chinook uuid */
};
/*
@@ -374,6 +376,10 @@ enum bfi_ioc_state {
BFI_IOC_MEMTEST = 9, /* IOC is doing memtest */
};
+#define BFA_IOC_CB_JOIN_SH 16
+#define BFA_IOC_CB_FWSTATE_MASK 0x0000ffff
+#define BFA_IOC_CB_JOIN_MASK 0xffff0000
+
#define BFI_IOC_ENDIAN_SIG 0x12345678
enum {
@@ -973,6 +979,7 @@ enum bfi_diag_i2h {
BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST),
BFI_DIAG_I2H_DPORT = BFA_I2HM(BFI_DIAG_H2I_DPORT),
+ BFI_DIAG_I2H_DPORT_SCN = BFA_I2HM(8),
};
#define BFI_DIAG_MAX_SGES 2
@@ -1064,16 +1071,73 @@ struct bfi_diag_qtest_req_s {
enum bfi_dport_req {
BFI_DPORT_DISABLE = 0, /* disable dport request */
BFI_DPORT_ENABLE = 1, /* enable dport request */
+ BFI_DPORT_START = 2, /* start dport request */
+ BFI_DPORT_SHOW = 3, /* show dport request */
+ BFI_DPORT_DYN_DISABLE = 4, /* disable dynamic dport request */
+};
+
+enum bfi_dport_scn {
+ BFI_DPORT_SCN_TESTSTART = 1,
+ BFI_DPORT_SCN_TESTCOMP = 2,
+ BFI_DPORT_SCN_SFP_REMOVED = 3,
+ BFI_DPORT_SCN_DDPORT_ENABLE = 4,
+ BFI_DPORT_SCN_DDPORT_DISABLE = 5,
+ BFI_DPORT_SCN_FCPORT_DISABLE = 6,
+ BFI_DPORT_SCN_SUBTESTSTART = 7,
+ BFI_DPORT_SCN_TESTSKIP = 8,
+ BFI_DPORT_SCN_DDPORT_DISABLED = 9,
};
struct bfi_diag_dport_req_s {
struct bfi_mhdr_s mh; /* 4 bytes */
- u8 req; /* request 1: enable 0: disable */
- u8 status; /* reply status */
- u8 rsvd[2];
- u32 msgtag; /* msgtag for reply */
+ u8 req; /* request 1: enable 0: disable */
+ u8 rsvd[3];
+ u32 lpcnt;
+ u32 payload;
+};
+
+struct bfi_diag_dport_rsp_s {
+ struct bfi_mhdr_s mh; /* header 4 bytes */
+ bfa_status_t status; /* reply status */
+ wwn_t pwwn; /* switch port wwn. 8 bytes */
+ wwn_t nwwn; /* switch node wwn. 8 bytes */
+};
+
+struct bfi_diag_dport_scn_teststart_s {
+ wwn_t pwwn; /* switch port wwn. 8 bytes */
+ wwn_t nwwn; /* switch node wwn. 8 bytes */
+ u8 type; /* bfa_diag_dport_test_type_e */
+ u8 rsvd[3];
+ u32 numfrm; /* from switch uint in 1M */
+};
+
+struct bfi_diag_dport_scn_testcomp_s {
+ u8 status; /* bfa_diag_dport_test_status_e */
+ u8 speed; /* bfa_port_speed_t */
+ u16 numbuffer; /* from switch */
+ u8 subtest_status[DPORT_TEST_MAX]; /* 4 bytes */
+ u32 latency; /* from switch */
+ u32 distance; /* from swtich unit in meters */
+ /* Buffers required to saturate the link */
+ u16 frm_sz; /* from switch for buf_reqd */
+ u8 rsvd[2];
+};
+
+struct bfi_diag_dport_scn_s { /* max size == RDS_RMESZ */
+ struct bfi_mhdr_s mh; /* header 4 bytes */
+ u8 state; /* new state */
+ u8 rsvd[3];
+ union {
+ struct bfi_diag_dport_scn_teststart_s teststart;
+ struct bfi_diag_dport_scn_testcomp_s testcomp;
+ } info;
+};
+
+union bfi_diag_dport_msg_u {
+ struct bfi_diag_dport_req_s req;
+ struct bfi_diag_dport_rsp_s rsp;
+ struct bfi_diag_dport_scn_s scn;
};
-#define bfi_diag_dport_rsp_t struct bfi_diag_dport_req_s
/*
* PHY module specific
@@ -1191,7 +1255,9 @@ enum bfi_fru_i2h_msgs {
struct bfi_fru_write_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
u8 last;
- u8 rsv[3];
+ u8 rsv_1[3];
+ u8 trfr_cmpl;
+ u8 rsv_2[3];
u32 offset;
u32 length;
struct bfi_alen_s alen;
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index 5ae2c16..1a3fe5a 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -276,8 +276,7 @@ struct bfi_fcport_enable_req_s {
struct bfi_fcport_set_svc_params_req_s {
struct bfi_mhdr_s mh; /* msg header */
__be16 tx_bbcredit; /* Tx credits */
- u8 bb_scn; /* BB_SC FC credit recovery */
- u8 rsvd;
+ u8 rsvd[2];
};
/*
@@ -446,8 +445,8 @@ struct bfi_lps_login_rsp_s {
mac_t fcf_mac;
u8 ext_status;
u8 brcd_switch; /* attached peer is brcd switch */
- u8 bb_scn; /* atatched port's bb_scn */
u8 bfa_tag;
+ u8 rsvd;
};
struct bfi_lps_logout_req_s {
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 3486845..08b22a90 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -2,7 +2,7 @@
#define _BNX2FC_H_
/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
*
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -64,10 +64,12 @@
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "1.0.12"
+#define BNX2FC_VERSION "1.0.14"
#define PFX "bnx2fc: "
+#define BCM_CHIP_LEN 16
+
#define BNX2X_DOORBELL_PCI_BAR 2
#define BNX2FC_MAX_BD_LEN 0xffff
@@ -88,9 +90,6 @@
#define BNX2FC_MAX_NPIV 256
-#define BNX2FC_MAX_OUTSTANDING_CMNDS 2048
-#define BNX2FC_CAN_QUEUE BNX2FC_MAX_OUTSTANDING_CMNDS
-#define BNX2FC_ELSTM_XIDS BNX2FC_CAN_QUEUE
#define BNX2FC_MIN_PAYLOAD 256
#define BNX2FC_MAX_PAYLOAD 2048
#define BNX2FC_MFS \
@@ -108,11 +107,8 @@
#define BNX2FC_CONFQ_WQE_SIZE (sizeof(struct fcoe_confqe))
#define BNX2FC_5771X_DB_PAGE_SIZE 128
-#define BNX2FC_MAX_TASKS \
- (BNX2FC_MAX_OUTSTANDING_CMNDS + BNX2FC_ELSTM_XIDS)
#define BNX2FC_TASK_SIZE 128
#define BNX2FC_TASKS_PER_PAGE (PAGE_SIZE/BNX2FC_TASK_SIZE)
-#define BNX2FC_TASK_CTX_ARR_SZ (BNX2FC_MAX_TASKS/BNX2FC_TASKS_PER_PAGE)
#define BNX2FC_MAX_ROWS_IN_HASH_TBL 8
#define BNX2FC_HASH_TBL_CHUNK_SIZE (16 * 1024)
@@ -125,12 +121,9 @@
#define BNX2FC_WRITE (1 << 0)
#define BNX2FC_MIN_XID 0
-#define BNX2FC_MAX_XID \
- (BNX2FC_MAX_OUTSTANDING_CMNDS + BNX2FC_ELSTM_XIDS - 1)
#define FCOE_MAX_NUM_XIDS 0x2000
-#define FCOE_MIN_XID (BNX2FC_MAX_XID + 1)
-#define FCOE_MAX_XID (FCOE_MIN_XID + FCOE_MAX_NUM_XIDS - 1)
-#define FCOE_XIDS_PER_CPU (FCOE_MIN_XID + (512 * nr_cpu_ids) - 1)
+#define FCOE_MAX_XID_OFFSET (FCOE_MAX_NUM_XIDS - 1)
+#define FCOE_XIDS_PER_CPU_OFFSET ((512 * nr_cpu_ids) - 1)
#define BNX2FC_MAX_LUN 0xFFFF
#define BNX2FC_MAX_FCP_TGT 256
#define BNX2FC_MAX_CMD_LEN 16
@@ -156,6 +149,18 @@
#define BNX2FC_RELOGIN_WAIT_TIME 200
#define BNX2FC_RELOGIN_WAIT_CNT 10
+#define BNX2FC_STATS(hba, stat, cnt) \
+ do { \
+ u32 val; \
+ \
+ val = fw_stats->stat.cnt; \
+ if (hba->prev_stats.stat.cnt <= val) \
+ val -= hba->prev_stats.stat.cnt; \
+ else \
+ val += (0xfffffff - hba->prev_stats.stat.cnt); \
+ hba->bfw_stats.cnt += val; \
+ } while (0)
+
/* bnx2fc driver uses only one instance of fcoe_percpu_s */
extern struct fcoe_percpu_s bnx2fc_global;
@@ -167,6 +172,14 @@ struct bnx2fc_percpu_s {
spinlock_t fp_work_lock;
};
+struct bnx2fc_fw_stats {
+ u64 fc_crc_cnt;
+ u64 fcoe_tx_pkt_cnt;
+ u64 fcoe_rx_pkt_cnt;
+ u64 fcoe_tx_byte_cnt;
+ u64 fcoe_rx_byte_cnt;
+};
+
struct bnx2fc_hba {
struct list_head list;
struct cnic_dev *cnic;
@@ -186,6 +199,13 @@ struct bnx2fc_hba {
#define BNX2FC_FLAG_FW_INIT_DONE 0
#define BNX2FC_FLAG_DESTROY_CMPL 1
u32 next_conn_id;
+
+ /* xid resources */
+ u16 max_xid;
+ u32 max_tasks;
+ u32 max_outstanding_cmds;
+ u32 elstm_xids;
+
struct fcoe_task_ctx_entry **task_ctx;
dma_addr_t *task_ctx_dma;
struct regpair *task_ctx_bd_tbl;
@@ -207,6 +227,8 @@ struct bnx2fc_hba {
struct bnx2fc_rport **tgt_ofld_list;
/* statistics */
+ struct bnx2fc_fw_stats bfw_stats;
+ struct fcoe_statistics_params prev_stats;
struct fcoe_statistics_params *stats_buffer;
dma_addr_t stats_buf_dma;
struct completion stat_req_done;
@@ -221,6 +243,8 @@ struct bnx2fc_hba {
int wait_for_link_down;
int num_ofld_sess;
struct list_head vports;
+
+ char chip_num[BCM_CHIP_LEN];
};
struct bnx2fc_interface {
@@ -280,6 +304,7 @@ struct bnx2fc_rport {
#define BNX2FC_FLAG_UPLD_REQ_COMPL 0x7
#define BNX2FC_FLAG_EXPL_LOGO 0x8
#define BNX2FC_FLAG_DISABLE_FAILED 0x9
+#define BNX2FC_FLAG_ENABLED 0xa
u8 src_addr[ETH_ALEN];
u32 max_sqes;
@@ -468,6 +493,8 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba);
int bnx2fc_send_fw_fcoe_destroy_msg(struct bnx2fc_hba *hba);
int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
struct bnx2fc_rport *tgt);
+int bnx2fc_send_session_enable_req(struct fcoe_port *port,
+ struct bnx2fc_rport *tgt);
int bnx2fc_send_session_disable_req(struct fcoe_port *port,
struct bnx2fc_rport *tgt);
int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
@@ -479,8 +506,7 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba);
void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba);
int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba);
void bnx2fc_free_fw_resc(struct bnx2fc_hba *hba);
-struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
- u16 min_xid, u16 max_xid);
+struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba);
void bnx2fc_cmd_mgr_free(struct bnx2fc_cmd_mgr *cmgr);
void bnx2fc_get_link_state(struct bnx2fc_hba *hba);
char *bnx2fc_get_next_rqe(struct bnx2fc_rport *tgt, u8 num_items);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index bdbbb13..b1c9a4f 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -3,7 +3,7 @@
* This file contains helper routines that handle ELS requests
* and responses.
*
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index e055865..69ac554 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -3,7 +3,7 @@
* cnic modules to create FCoE instances, send/receive non-offloaded
* FIP/FCoE packets, listen to link events etc.
*
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,10 +22,10 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
#define DRV_MODULE_NAME "bnx2fc"
#define DRV_MODULE_VERSION BNX2FC_VERSION
-#define DRV_MODULE_RELDATE "Jun 04, 2012"
+#define DRV_MODULE_RELDATE "Mar 08, 2013"
-static char version[] __devinitdata =
+static char version[] =
"Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -62,12 +62,16 @@ static int bnx2fc_destroy(struct net_device *net_device);
static int bnx2fc_enable(struct net_device *netdev);
static int bnx2fc_disable(struct net_device *netdev);
+/* fcoe_syfs control interface handlers */
+static int bnx2fc_ctlr_alloc(struct net_device *netdev);
+static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev);
+
static void bnx2fc_recv_frame(struct sk_buff *skb);
static void bnx2fc_start_disc(struct bnx2fc_interface *interface);
static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
static int bnx2fc_lport_config(struct fc_lport *lport);
-static int bnx2fc_em_config(struct fc_lport *lport);
+static int bnx2fc_em_config(struct fc_lport *lport, struct bnx2fc_hba *hba);
static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba);
static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba);
@@ -89,7 +93,6 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport);
static void bnx2fc_stop(struct bnx2fc_interface *interface);
static int __init bnx2fc_mod_init(void);
static void __exit bnx2fc_mod_exit(void);
-static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev);
unsigned int bnx2fc_debug_level;
module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
@@ -107,44 +110,6 @@ static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport)
((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
}
-/**
- * bnx2fc_get_lesb() - Fill the FCoE Link Error Status Block
- * @lport: the local port
- * @fc_lesb: the link error status block
- */
-static void bnx2fc_get_lesb(struct fc_lport *lport,
- struct fc_els_lesb *fc_lesb)
-{
- struct net_device *netdev = bnx2fc_netdev(lport);
-
- __fcoe_get_lesb(lport, fc_lesb, netdev);
-}
-
-static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
-{
- struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
- struct net_device *netdev = bnx2fc_netdev(fip->lp);
- struct fcoe_fc_els_lesb *fcoe_lesb;
- struct fc_els_lesb fc_lesb;
-
- __fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
- fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
-
- ctlr_dev->lesb.lesb_link_fail =
- ntohl(fcoe_lesb->lesb_link_fail);
- ctlr_dev->lesb.lesb_vlink_fail =
- ntohl(fcoe_lesb->lesb_vlink_fail);
- ctlr_dev->lesb.lesb_miss_fka =
- ntohl(fcoe_lesb->lesb_miss_fka);
- ctlr_dev->lesb.lesb_symb_err =
- ntohl(fcoe_lesb->lesb_symb_err);
- ctlr_dev->lesb.lesb_err_block =
- ntohl(fcoe_lesb->lesb_err_block);
- ctlr_dev->lesb.lesb_fcs_error =
- ntohl(fcoe_lesb->lesb_fcs_error);
-}
-EXPORT_SYMBOL(bnx2fc_ctlr_get_lesb);
-
static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
{
struct fcoe_ctlr_device *ctlr_dev =
@@ -687,11 +652,16 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
return bnx2fc_stats;
}
- bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat2.fc_crc_cnt;
- bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
- bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
- bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
- bnx2fc_stats->rx_words += (fw_stats->rx_stat0.fcoe_rx_byte_cnt) / 4;
+ BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt);
+ bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt;
+ BNX2FC_STATS(hba, tx_stat, fcoe_tx_pkt_cnt);
+ bnx2fc_stats->tx_frames += hba->bfw_stats.fcoe_tx_pkt_cnt;
+ BNX2FC_STATS(hba, tx_stat, fcoe_tx_byte_cnt);
+ bnx2fc_stats->tx_words += ((hba->bfw_stats.fcoe_tx_byte_cnt) / 4);
+ BNX2FC_STATS(hba, rx_stat0, fcoe_rx_pkt_cnt);
+ bnx2fc_stats->rx_frames += hba->bfw_stats.fcoe_rx_pkt_cnt;
+ BNX2FC_STATS(hba, rx_stat0, fcoe_rx_byte_cnt);
+ bnx2fc_stats->rx_words += ((hba->bfw_stats.fcoe_rx_byte_cnt) / 4);
bnx2fc_stats->dumped_frames = 0;
bnx2fc_stats->lip_count = 0;
@@ -700,6 +670,8 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
bnx2fc_stats->loss_of_signal_count = 0;
bnx2fc_stats->prim_seq_protocol_err_count = 0;
+ memcpy(&hba->prev_stats, hba->stats_buffer,
+ sizeof(struct fcoe_statistics_params));
return bnx2fc_stats;
}
@@ -707,6 +679,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
{
struct fcoe_port *port = lport_priv(lport);
struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct Scsi_Host *shost = lport->host;
int rc = 0;
@@ -727,42 +700,14 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
}
if (!lport->vport)
fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
- sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s",
- BNX2FC_NAME, BNX2FC_VERSION,
+ snprintf(fc_host_symbolic_name(lport->host), 256,
+ "%s (Broadcom %s) v%s over %s",
+ BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION,
interface->netdev->name);
return 0;
}
-static void bnx2fc_link_speed_update(struct fc_lport *lport)
-{
- struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_interface *interface = port->priv;
- struct net_device *netdev = interface->netdev;
- struct ethtool_cmd ecmd;
-
- if (!__ethtool_get_settings(netdev, &ecmd)) {
- lport->link_supported_speeds &=
- ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
- if (ecmd.supported & (SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full))
- lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
- if (ecmd.supported & SUPPORTED_10000baseT_Full)
- lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
-
- switch (ethtool_cmd_speed(&ecmd)) {
- case SPEED_1000:
- lport->link_speed = FC_PORTSPEED_1GBIT;
- break;
- case SPEED_2500:
- lport->link_speed = FC_PORTSPEED_2GBIT;
- break;
- case SPEED_10000:
- lport->link_speed = FC_PORTSPEED_10GBIT;
- break;
- }
- }
-}
static int bnx2fc_link_ok(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
@@ -820,7 +765,7 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev)
port->fcoe_pending_queue_active = 0;
setup_timer(&port->timer, fcoe_queue_timer, (unsigned long) lport);
- bnx2fc_link_speed_update(lport);
+ fcoe_link_speed_update(lport);
if (!lport->vport) {
if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
@@ -864,6 +809,7 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
u16 vlan_id)
{
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
+ struct fcoe_ctlr_device *cdev;
struct fc_lport *lport;
struct fc_lport *vport;
struct bnx2fc_interface *interface, *tmp;
@@ -923,30 +869,47 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n",
interface->netdev->name, event);
- bnx2fc_link_speed_update(lport);
+ fcoe_link_speed_update(lport);
+
+ cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
if (link_possible && !bnx2fc_link_ok(lport)) {
- /* Reset max recv frame size to default */
- fc_set_mfs(lport, BNX2FC_MFS);
- /*
- * ctlr link up will only be handled during
- * enable to avoid sending discovery solicitation
- * on a stale vlan
- */
- if (interface->enabled)
- fcoe_ctlr_link_up(ctlr);
+ switch (cdev->enabled) {
+ case FCOE_CTLR_DISABLED:
+ pr_info("Link up while interface is disabled.\n");
+ break;
+ case FCOE_CTLR_ENABLED:
+ case FCOE_CTLR_UNUSED:
+ /* Reset max recv frame size to default */
+ fc_set_mfs(lport, BNX2FC_MFS);
+ /*
+ * ctlr link up will only be handled during
+ * enable to avoid sending discovery
+ * solicitation on a stale vlan
+ */
+ if (interface->enabled)
+ fcoe_ctlr_link_up(ctlr);
+ };
} else if (fcoe_ctlr_link_down(ctlr)) {
- mutex_lock(&lport->lp_mutex);
- list_for_each_entry(vport, &lport->vports, list)
- fc_host_port_type(vport->host) =
- FC_PORTTYPE_UNKNOWN;
- mutex_unlock(&lport->lp_mutex);
- fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
- per_cpu_ptr(lport->stats,
- get_cpu())->LinkFailureCount++;
- put_cpu();
- fcoe_clean_pending_queue(lport);
- wait_for_upload = 1;
+ switch (cdev->enabled) {
+ case FCOE_CTLR_DISABLED:
+ pr_info("Link down while interface is disabled.\n");
+ break;
+ case FCOE_CTLR_ENABLED:
+ case FCOE_CTLR_UNUSED:
+ mutex_lock(&lport->lp_mutex);
+ list_for_each_entry(vport, &lport->vports, list)
+ fc_host_port_type(vport->host) =
+ FC_PORTTYPE_UNKNOWN;
+ mutex_unlock(&lport->lp_mutex);
+ fc_host_port_type(lport->host) =
+ FC_PORTTYPE_UNKNOWN;
+ per_cpu_ptr(lport->stats,
+ get_cpu())->LinkFailureCount++;
+ put_cpu();
+ fcoe_clean_pending_queue(lport);
+ wait_for_upload = 1;
+ };
}
}
mutex_unlock(&bnx2fc_dev_lock);
@@ -979,19 +942,21 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
fc_exch_init(lport);
fc_rport_init(lport);
fc_disc_init(lport);
+ fc_disc_config(lport, lport);
return 0;
}
-static int bnx2fc_em_config(struct fc_lport *lport)
+static int bnx2fc_em_config(struct fc_lport *lport, struct bnx2fc_hba *hba)
{
- int max_xid;
+ int fcoe_min_xid, fcoe_max_xid;
+ fcoe_min_xid = hba->max_xid + 1;
if (nr_cpu_ids <= 2)
- max_xid = FCOE_XIDS_PER_CPU;
+ fcoe_max_xid = hba->max_xid + FCOE_XIDS_PER_CPU_OFFSET;
else
- max_xid = FCOE_MAX_XID;
- if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, FCOE_MIN_XID,
- max_xid, NULL)) {
+ fcoe_max_xid = hba->max_xid + FCOE_MAX_XID_OFFSET;
+ if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, fcoe_min_xid,
+ fcoe_max_xid, NULL)) {
printk(KERN_ERR PFX "em_config:fc_exch_mgr_alloc failed\n");
return -ENOMEM;
}
@@ -1338,6 +1303,12 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
mutex_init(&hba->hba_mutex);
hba->cnic = cnic;
+
+ hba->max_tasks = cnic->max_fcoe_exchanges;
+ hba->elstm_xids = (hba->max_tasks / 2);
+ hba->max_outstanding_cmds = hba->elstm_xids;
+ hba->max_xid = (hba->max_tasks - 1);
+
rc = bnx2fc_bind_pcidev(hba);
if (rc) {
printk(KERN_ERR PFX "create_adapter: bind error\n");
@@ -1356,8 +1327,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
hba->num_ofld_sess = 0;
- hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
- BNX2FC_MAX_XID);
+ hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba);
if (!hba->cmd_mgr) {
printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
goto cmgr_err;
@@ -1368,13 +1338,13 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
FCOE_IOS_PER_CONNECTION_SHIFT;
fcoe_cap->capability1 |= BNX2FC_NUM_MAX_SESS <<
FCOE_LOGINS_PER_PORT_SHIFT;
- fcoe_cap->capability2 = BNX2FC_MAX_OUTSTANDING_CMNDS <<
+ fcoe_cap->capability2 = hba->max_outstanding_cmds <<
FCOE_NUMBER_OF_EXCHANGES_SHIFT;
fcoe_cap->capability2 |= BNX2FC_MAX_NPIV <<
FCOE_NPIV_WWN_PER_PORT_SHIFT;
fcoe_cap->capability3 = BNX2FC_NUM_MAX_SESS <<
FCOE_TARGETS_SUPPORTED_SHIFT;
- fcoe_cap->capability3 |= BNX2FC_MAX_OUTSTANDING_CMNDS <<
+ fcoe_cap->capability3 |= hba->max_outstanding_cmds <<
FCOE_OUTSTANDING_COMMANDS_SHIFT;
fcoe_cap->capability4 = FCOE_CAPABILITY4_STATEFUL;
@@ -1454,7 +1424,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
struct Scsi_Host *shost;
struct fc_vport *vport = dev_to_vport(parent);
struct bnx2fc_lport *blport;
- struct bnx2fc_hba *hba;
+ struct bnx2fc_hba *hba = interface->hba;
int rc = 0;
blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL);
@@ -1464,6 +1434,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
}
/* Allocate Scsi_Host structure */
+ bnx2fc_shost_template.can_queue = hba->max_outstanding_cmds;
if (!npiv)
lport = libfc_host_alloc(&bnx2fc_shost_template, sizeof(*port));
else
@@ -1477,6 +1448,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
port = lport_priv(lport);
port->lport = lport;
port->priv = interface;
+ port->get_netdev = bnx2fc_netdev;
INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
/* Configure fcoe_port */
@@ -1514,7 +1486,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
/* Allocate exchange manager */
if (!npiv)
- rc = bnx2fc_em_config(lport);
+ rc = bnx2fc_em_config(lport, hba);
else {
shost = vport_to_shost(vport);
n_port = shost_priv(shost);
@@ -1528,7 +1500,6 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
bnx2fc_interface_get(interface);
- hba = interface->hba;
spin_lock_bh(&hba->hba_lock);
blport->lport = lport;
list_add_tail(&blport->list, &hba->vports);
@@ -1687,23 +1658,60 @@ mem_err:
static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
{
struct cnic_dev *cnic;
+ struct pci_dev *pdev;
if (!hba->cnic) {
printk(KERN_ERR PFX "cnic is NULL\n");
return -ENODEV;
}
cnic = hba->cnic;
- hba->pcidev = cnic->pcidev;
- if (hba->pcidev)
- pci_dev_get(hba->pcidev);
+ pdev = hba->pcidev = cnic->pcidev;
+ if (!hba->pcidev)
+ return -ENODEV;
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_NX2_57710:
+ strncpy(hba->chip_num, "BCM57710", BCM_CHIP_LEN);
+ break;
+ case PCI_DEVICE_ID_NX2_57711:
+ strncpy(hba->chip_num, "BCM57711", BCM_CHIP_LEN);
+ break;
+ case PCI_DEVICE_ID_NX2_57712:
+ case PCI_DEVICE_ID_NX2_57712_MF:
+ case PCI_DEVICE_ID_NX2_57712_VF:
+ strncpy(hba->chip_num, "BCM57712", BCM_CHIP_LEN);
+ break;
+ case PCI_DEVICE_ID_NX2_57800:
+ case PCI_DEVICE_ID_NX2_57800_MF:
+ case PCI_DEVICE_ID_NX2_57800_VF:
+ strncpy(hba->chip_num, "BCM57800", BCM_CHIP_LEN);
+ break;
+ case PCI_DEVICE_ID_NX2_57810:
+ case PCI_DEVICE_ID_NX2_57810_MF:
+ case PCI_DEVICE_ID_NX2_57810_VF:
+ strncpy(hba->chip_num, "BCM57810", BCM_CHIP_LEN);
+ break;
+ case PCI_DEVICE_ID_NX2_57840:
+ case PCI_DEVICE_ID_NX2_57840_MF:
+ case PCI_DEVICE_ID_NX2_57840_VF:
+ case PCI_DEVICE_ID_NX2_57840_2_20:
+ case PCI_DEVICE_ID_NX2_57840_4_10:
+ strncpy(hba->chip_num, "BCM57840", BCM_CHIP_LEN);
+ break;
+ default:
+ pr_err(PFX "Unknown device id 0x%x\n", pdev->device);
+ break;
+ }
+ pci_dev_get(hba->pcidev);
return 0;
}
static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
{
- if (hba->pcidev)
+ if (hba->pcidev) {
+ hba->chip_num[0] = '\0';
pci_dev_put(hba->pcidev);
+ }
hba->pcidev = NULL;
}
@@ -1996,7 +2004,9 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
}
-
+/**
+ * Deperecated: Use bnx2fc_enabled()
+ */
static int bnx2fc_disable(struct net_device *netdev)
{
struct bnx2fc_interface *interface;
@@ -2022,7 +2032,9 @@ static int bnx2fc_disable(struct net_device *netdev)
return rc;
}
-
+/**
+ * Deprecated: Use bnx2fc_enabled()
+ */
static int bnx2fc_enable(struct net_device *netdev)
{
struct bnx2fc_interface *interface;
@@ -2048,17 +2060,57 @@ static int bnx2fc_enable(struct net_device *netdev)
}
/**
- * bnx2fc_create - Create bnx2fc FCoE interface
+ * bnx2fc_ctlr_enabled() - Enable or disable an FCoE Controller
+ * @cdev: The FCoE Controller that is being enabled or disabled
*
- * @buffer: The name of Ethernet interface to create on
- * @kp: The associated kernel param
+ * fcoe_sysfs will ensure that the state of 'enabled' has
+ * changed, so no checking is necessary here. This routine simply
+ * calls fcoe_enable or fcoe_disable, both of which are deprecated.
+ * When those routines are removed the functionality can be merged
+ * here.
+ */
+static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev)
+{
+ struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev);
+ struct fc_lport *lport = ctlr->lp;
+ struct net_device *netdev = bnx2fc_netdev(lport);
+
+ switch (cdev->enabled) {
+ case FCOE_CTLR_ENABLED:
+ return bnx2fc_enable(netdev);
+ case FCOE_CTLR_DISABLED:
+ return bnx2fc_disable(netdev);
+ case FCOE_CTLR_UNUSED:
+ default:
+ return -ENOTSUPP;
+ };
+}
+
+enum bnx2fc_create_link_state {
+ BNX2FC_CREATE_LINK_DOWN,
+ BNX2FC_CREATE_LINK_UP,
+};
+
+/**
+ * _bnx2fc_create() - Create bnx2fc FCoE interface
+ * @netdev : The net_device object the Ethernet interface to create on
+ * @fip_mode: The FIP mode for this creation
+ * @link_state: The ctlr link state on creation
*
- * Called from sysfs.
+ * Called from either the libfcoe 'create' module parameter
+ * via fcoe_create or from fcoe_syfs's ctlr_create file.
+ *
+ * libfcoe's 'create' module parameter is deprecated so some
+ * consolidation of code can be done when that interface is
+ * removed.
*
* Returns: 0 for success
*/
-static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
+static int _bnx2fc_create(struct net_device *netdev,
+ enum fip_state fip_mode,
+ enum bnx2fc_create_link_state link_state)
{
+ struct fcoe_ctlr_device *cdev;
struct fcoe_ctlr *ctlr;
struct bnx2fc_interface *interface;
struct bnx2fc_hba *hba;
@@ -2127,6 +2179,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
}
ctlr = bnx2fc_to_ctlr(interface);
+ cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
interface->vlan_id = vlan_id;
interface->timer_work_queue =
@@ -2137,7 +2190,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
goto ifput_err;
}
- lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
+ lport = bnx2fc_if_create(interface, &cdev->dev, 0);
if (!lport) {
printk(KERN_ERR PFX "Failed to create interface (%s)\n",
netdev->name);
@@ -2153,7 +2206,13 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
/* Make this master N_port */
ctlr->lp = lport;
- if (!bnx2fc_link_ok(lport)) {
+ if (link_state == BNX2FC_CREATE_LINK_UP)
+ cdev->enabled = FCOE_CTLR_ENABLED;
+ else
+ cdev->enabled = FCOE_CTLR_DISABLED;
+
+ if (link_state == BNX2FC_CREATE_LINK_UP &&
+ !bnx2fc_link_ok(lport)) {
fcoe_ctlr_link_up(ctlr);
fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state);
@@ -2161,7 +2220,10 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
BNX2FC_HBA_DBG(lport, "create: START DISC\n");
bnx2fc_start_disc(interface);
- interface->enabled = true;
+
+ if (link_state == BNX2FC_CREATE_LINK_UP)
+ interface->enabled = true;
+
/*
* Release from kref_init in bnx2fc_interface_setup, on success
* lport should be holding a reference taken in bnx2fc_if_create
@@ -2187,6 +2249,37 @@ mod_err:
}
/**
+ * bnx2fc_create() - Create a bnx2fc interface
+ * @netdev : The net_device object the Ethernet interface to create on
+ * @fip_mode: The FIP mode for this creation
+ *
+ * Called from fcoe transport
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
+{
+ return _bnx2fc_create(netdev, fip_mode, BNX2FC_CREATE_LINK_UP);
+}
+
+/**
+ * bnx2fc_ctlr_alloc() - Allocate a bnx2fc interface from fcoe_sysfs
+ * @netdev: The net_device to be used by the allocated FCoE Controller
+ *
+ * This routine is called from fcoe_sysfs. It will start the fcoe_ctlr
+ * in a link_down state. The allows the user an opportunity to configure
+ * the FCoE Controller from sysfs before enabling the FCoE Controller.
+ *
+ * Creating in with this routine starts the FCoE Controller in Fabric
+ * mode. The user can change to VN2VN or another mode before enabling.
+ */
+static int bnx2fc_ctlr_alloc(struct net_device *netdev)
+{
+ return _bnx2fc_create(netdev, FIP_MODE_FABRIC,
+ BNX2FC_CREATE_LINK_DOWN);
+}
+
+/**
* bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance
*
* @cnic: Pointer to cnic device instance
@@ -2311,6 +2404,7 @@ static struct fcoe_transport bnx2fc_transport = {
.name = {"bnx2fc"},
.attached = false,
.list = LIST_HEAD_INIT(bnx2fc_transport.list),
+ .alloc = bnx2fc_ctlr_alloc,
.match = bnx2fc_match,
.create = bnx2fc_create,
.destroy = bnx2fc_destroy,
@@ -2555,13 +2649,13 @@ module_init(bnx2fc_mod_init);
module_exit(bnx2fc_mod_exit);
static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = {
- .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode,
- .get_fcoe_ctlr_link_fail = bnx2fc_ctlr_get_lesb,
- .get_fcoe_ctlr_vlink_fail = bnx2fc_ctlr_get_lesb,
- .get_fcoe_ctlr_miss_fka = bnx2fc_ctlr_get_lesb,
- .get_fcoe_ctlr_symb_err = bnx2fc_ctlr_get_lesb,
- .get_fcoe_ctlr_err_block = bnx2fc_ctlr_get_lesb,
- .get_fcoe_ctlr_fcs_error = bnx2fc_ctlr_get_lesb,
+ .set_fcoe_ctlr_enabled = bnx2fc_ctlr_enabled,
+ .get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb,
+ .get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb,
+ .get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb,
+ .get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb,
+ .get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb,
+ .get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb,
.get_fcoe_fcf_selected = fcoe_fcf_get_selected,
.get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id,
@@ -2657,10 +2751,9 @@ static struct scsi_host_template bnx2fc_shost_template = {
.change_queue_type = fc_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
- .can_queue = BNX2FC_CAN_QUEUE,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = BNX2FC_MAX_BDS_PER_CMD,
- .max_sectors = 512,
+ .max_sectors = 1024,
};
static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
@@ -2668,7 +2761,7 @@ static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
.elsct_send = bnx2fc_elsct_send,
.fcp_abort_io = bnx2fc_abort_io,
.fcp_cleanup = bnx2fc_cleanup,
- .get_lesb = bnx2fc_get_lesb,
+ .get_lesb = fcoe_get_lesb,
.rport_event_callback = bnx2fc_rport_event_handler,
};
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index ef60afa..c0d035a 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -2,7 +2,7 @@
* This file contains the code that low level functions that interact
* with 57712 FCoE firmware.
*
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -77,7 +77,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
fcoe_init1.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
- fcoe_init1.num_tasks = BNX2FC_MAX_TASKS;
+ fcoe_init1.num_tasks = hba->max_tasks;
fcoe_init1.sq_num_wqes = BNX2FC_SQ_WQES_MAX;
fcoe_init1.rq_num_wqes = BNX2FC_RQ_WQES_MAX;
fcoe_init1.rq_buffer_log_size = BNX2FC_RQ_BUF_LOG_SZ;
@@ -126,7 +126,11 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
fcoe_init3.error_bit_map_lo = 0xffffffff;
fcoe_init3.error_bit_map_hi = 0xffffffff;
- fcoe_init3.perf_config = 1;
+ /*
+ * enable both cached connection and cached tasks
+ * 0 = none, 1 = cached connection, 2 = cached tasks, 3 = both
+ */
+ fcoe_init3.perf_config = 3;
kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
@@ -347,7 +351,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
* @port: port structure pointer
* @tgt: bnx2fc_rport structure pointer
*/
-static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
+int bnx2fc_send_session_enable_req(struct fcoe_port *port,
struct bnx2fc_rport *tgt)
{
struct kwqe *kwqe_arr[2];
@@ -697,7 +701,7 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
- if (xid > BNX2FC_MAX_XID) {
+ if (xid > hba->max_xid) {
BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n",
xid);
goto ret_err_rqe;
@@ -759,8 +763,6 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
case FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET:
BNX2FC_TGT_DBG(tgt, "REC TOV popped for xid - 0x%x\n",
xid);
- memset(&io_req->err_entry, 0,
- sizeof(struct fcoe_err_report_entry));
memcpy(&io_req->err_entry, err_entry,
sizeof(struct fcoe_err_report_entry));
if (!test_bit(BNX2FC_FLAG_SRR_SENT,
@@ -817,7 +819,7 @@ ret_err_rqe:
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
- if (xid > BNX2FC_MAX_XID) {
+ if (xid > hba->max_xid) {
BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n", xid);
goto ret_warn_rqe;
}
@@ -847,8 +849,6 @@ ret_err_rqe:
goto ret_warn_rqe;
}
- memset(&io_req->err_entry, 0,
- sizeof(struct fcoe_err_report_entry));
memcpy(&io_req->err_entry, err_entry,
sizeof(struct fcoe_err_report_entry));
@@ -884,7 +884,7 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
spin_lock_bh(&tgt->tgt_lock);
xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
- if (xid >= BNX2FC_MAX_TASKS) {
+ if (xid >= hba->max_tasks) {
printk(KERN_ERR PFX "ERROR:xid out of range\n");
spin_unlock_bh(&tgt->tgt_lock);
return;
@@ -1124,7 +1124,6 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
struct bnx2fc_interface *interface;
u32 conn_id;
u32 context_id;
- int rc;
conn_id = ofld_kcqe->fcoe_conn_id;
context_id = ofld_kcqe->fcoe_conn_context_id;
@@ -1153,17 +1152,10 @@ static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
"resources\n");
set_bit(BNX2FC_FLAG_CTX_ALLOC_FAILURE, &tgt->flags);
}
- goto ofld_cmpl_err;
} else {
-
- /* now enable the session */
- rc = bnx2fc_send_session_enable_req(port, tgt);
- if (rc) {
- printk(KERN_ERR PFX "enable session failed\n");
- goto ofld_cmpl_err;
- }
+ /* FW offload request successfully completed */
+ set_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
}
- return;
ofld_cmpl_err:
set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
wake_up_interruptible(&tgt->ofld_wait);
@@ -1210,15 +1202,9 @@ static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
printk(KERN_ERR PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
goto enbl_cmpl_err;
}
- if (ofld_kcqe->completion_status)
- goto enbl_cmpl_err;
- else {
+ if (!ofld_kcqe->completion_status)
/* enable successful - rport ready for issuing IOs */
- set_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
- set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
- wake_up_interruptible(&tgt->ofld_wait);
- }
- return;
+ set_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
enbl_cmpl_err:
set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
@@ -1251,6 +1237,7 @@ static void bnx2fc_process_conn_disable_cmpl(struct bnx2fc_hba *hba,
/* disable successful */
BNX2FC_TGT_DBG(tgt, "disable successful\n");
clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+ clear_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
set_bit(BNX2FC_FLAG_DISABLED, &tgt->flags);
set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
wake_up_interruptible(&tgt->upld_wait);
@@ -1859,6 +1846,7 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
int rc = 0;
struct regpair *task_ctx_bdt;
dma_addr_t addr;
+ int task_ctx_arr_sz;
int i;
/*
@@ -1882,7 +1870,8 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
* Allocate task_ctx which is an array of pointers pointing to
* a page containing 32 task contexts
*/
- hba->task_ctx = kzalloc((BNX2FC_TASK_CTX_ARR_SZ * sizeof(void *)),
+ task_ctx_arr_sz = (hba->max_tasks / BNX2FC_TASKS_PER_PAGE);
+ hba->task_ctx = kzalloc((task_ctx_arr_sz * sizeof(void *)),
GFP_KERNEL);
if (!hba->task_ctx) {
printk(KERN_ERR PFX "unable to allocate task context array\n");
@@ -1893,7 +1882,7 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
/*
* Allocate task_ctx_dma which is an array of dma addresses
*/
- hba->task_ctx_dma = kmalloc((BNX2FC_TASK_CTX_ARR_SZ *
+ hba->task_ctx_dma = kmalloc((task_ctx_arr_sz *
sizeof(dma_addr_t)), GFP_KERNEL);
if (!hba->task_ctx_dma) {
printk(KERN_ERR PFX "unable to alloc context mapping array\n");
@@ -1902,7 +1891,7 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
}
task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl;
- for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+ for (i = 0; i < task_ctx_arr_sz; i++) {
hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev,
PAGE_SIZE,
@@ -1922,7 +1911,7 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
return 0;
out3:
- for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+ for (i = 0; i < task_ctx_arr_sz; i++) {
if (hba->task_ctx[i]) {
dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
@@ -1946,6 +1935,7 @@ out:
void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba)
{
+ int task_ctx_arr_sz;
int i;
if (hba->task_ctx_bd_tbl) {
@@ -1955,8 +1945,9 @@ void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba)
hba->task_ctx_bd_tbl = NULL;
}
+ task_ctx_arr_sz = (hba->max_tasks / BNX2FC_TASKS_PER_PAGE);
if (hba->task_ctx) {
- for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+ for (i = 0; i < task_ctx_arr_sz; i++) {
if (hba->task_ctx[i]) {
dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
hba->task_ctx[i],
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 8d4626c..575142e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1,7 +1,7 @@
/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
* IO manager and SCSI IO processing.
*
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -239,8 +239,7 @@ static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code)
sc_cmd->scsi_done(sc_cmd);
}
-struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
- u16 min_xid, u16 max_xid)
+struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
{
struct bnx2fc_cmd_mgr *cmgr;
struct io_bdt *bdt_info;
@@ -252,6 +251,8 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
int num_ios, num_pri_ios;
size_t bd_tbl_sz;
int arr_sz = num_possible_cpus() + 1;
+ u16 min_xid = BNX2FC_MIN_XID;
+ u16 max_xid = hba->max_xid;
if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
printk(KERN_ERR PFX "cmd_mgr_alloc: Invalid min_xid 0x%x \
@@ -298,7 +299,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
* of slow path requests.
*/
xid = BNX2FC_MIN_XID;
- num_pri_ios = num_ios - BNX2FC_ELSTM_XIDS;
+ num_pri_ios = num_ios - hba->elstm_xids;
for (i = 0; i < num_ios; i++) {
io_req = kzalloc(sizeof(*io_req), GFP_KERNEL);
@@ -367,7 +368,7 @@ void bnx2fc_cmd_mgr_free(struct bnx2fc_cmd_mgr *cmgr)
struct bnx2fc_hba *hba = cmgr->hba;
size_t bd_tbl_sz;
u16 min_xid = BNX2FC_MIN_XID;
- u16 max_xid = BNX2FC_MAX_XID;
+ u16 max_xid = hba->max_xid;
int num_ios;
int i;
@@ -654,7 +655,7 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
mp_req->mp_resp_bd = dma_alloc_coherent(&hba->pcidev->dev, sz,
&mp_req->mp_resp_bd_dma,
GFP_ATOMIC);
- if (!mp_req->mp_req_bd) {
+ if (!mp_req->mp_resp_bd) {
printk(KERN_ERR PFX "unable to alloc MP resp bd\n");
bnx2fc_free_mp_resc(io_req);
return FAILED;
@@ -685,8 +686,8 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
{
struct fc_lport *lport;
- struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
- struct fc_rport_libfc_priv *rp = rport->dd_data;
+ struct fc_rport *rport;
+ struct fc_rport_libfc_priv *rp;
struct fcoe_port *port;
struct bnx2fc_interface *interface;
struct bnx2fc_rport *tgt;
@@ -704,6 +705,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
unsigned long start = jiffies;
lport = shost_priv(host);
+ rport = starget_to_rport(scsi_target(sc_cmd->device));
port = lport_priv(lport);
interface = port->priv;
@@ -712,6 +714,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
rc = FAILED;
goto tmf_err;
}
+ rp = rport->dd_data;
rc = fc_block_scsi_eh(sc_cmd);
if (rc)
@@ -1267,8 +1270,11 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
spin_lock_bh(&tgt->tgt_lock);
io_req->wait_for_comp = 0;
- if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
- &io_req->req_flags))) {
+ if (test_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags)) {
+ BNX2FC_IO_DBG(io_req, "IO completed in a different context\n");
+ rc = SUCCESS;
+ } else if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+ &io_req->req_flags))) {
/* Let the scsi-ml try to recover this command */
printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
io_req->xid);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index b9d0d9c..4d93177 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -2,7 +2,7 @@
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@ static void bnx2fc_upld_timer(unsigned long data)
BNX2FC_TGT_DBG(tgt, "upld_timer - Upload compl not received!!\n");
/* fake upload completion */
clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+ clear_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
wake_up_interruptible(&tgt->upld_wait);
}
@@ -55,10 +56,25 @@ static void bnx2fc_ofld_timer(unsigned long data)
* resources are freed up in bnx2fc_offload_session
*/
clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+ clear_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
wake_up_interruptible(&tgt->ofld_wait);
}
+static void bnx2fc_ofld_wait(struct bnx2fc_rport *tgt)
+{
+ setup_timer(&tgt->ofld_timer, bnx2fc_ofld_timer, (unsigned long)tgt);
+ mod_timer(&tgt->ofld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+ wait_event_interruptible(tgt->ofld_wait,
+ (test_bit(
+ BNX2FC_FLAG_OFLD_REQ_CMPL,
+ &tgt->flags)));
+ if (signal_pending(current))
+ flush_signals(current);
+ del_timer_sync(&tgt->ofld_timer);
+}
+
static void bnx2fc_offload_session(struct fcoe_port *port,
struct bnx2fc_rport *tgt,
struct fc_rport_priv *rdata)
@@ -103,17 +119,7 @@ retry_ofld:
* wait for the session is offloaded and enabled. 3 Secs
* should be ample time for this process to complete.
*/
- setup_timer(&tgt->ofld_timer, bnx2fc_ofld_timer, (unsigned long)tgt);
- mod_timer(&tgt->ofld_timer, jiffies + BNX2FC_FW_TIMEOUT);
-
- wait_event_interruptible(tgt->ofld_wait,
- (test_bit(
- BNX2FC_FLAG_OFLD_REQ_CMPL,
- &tgt->flags)));
- if (signal_pending(current))
- flush_signals(current);
-
- del_timer_sync(&tgt->ofld_timer);
+ bnx2fc_ofld_wait(tgt);
if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) {
if (test_and_clear_bit(BNX2FC_FLAG_CTX_ALLOC_FAILURE,
@@ -131,14 +137,23 @@ retry_ofld:
}
if (bnx2fc_map_doorbell(tgt)) {
printk(KERN_ERR PFX "map doorbell failed - no mem\n");
- /* upload will take care of cleaning up sess resc */
- lport->tt.rport_logoff(rdata);
+ goto ofld_err;
}
+ clear_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+ rval = bnx2fc_send_session_enable_req(port, tgt);
+ if (rval) {
+ pr_err(PFX "enable session failed\n");
+ goto ofld_err;
+ }
+ bnx2fc_ofld_wait(tgt);
+ if (!(test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)))
+ goto ofld_err;
return;
ofld_err:
/* couldn't offload the session. log off from this rport */
BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n");
+ clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
/* Free session resources */
bnx2fc_free_session_resc(hba, tgt);
tgt_init_err:
@@ -259,6 +274,19 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
spin_unlock_bh(&tgt->tgt_lock);
}
+static void bnx2fc_upld_wait(struct bnx2fc_rport *tgt)
+{
+ setup_timer(&tgt->upld_timer, bnx2fc_upld_timer, (unsigned long)tgt);
+ mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+ wait_event_interruptible(tgt->upld_wait,
+ (test_bit(
+ BNX2FC_FLAG_UPLD_REQ_COMPL,
+ &tgt->flags)));
+ if (signal_pending(current))
+ flush_signals(current);
+ del_timer_sync(&tgt->upld_timer);
+}
+
static void bnx2fc_upload_session(struct fcoe_port *port,
struct bnx2fc_rport *tgt)
{
@@ -279,19 +307,8 @@ static void bnx2fc_upload_session(struct fcoe_port *port,
* wait for upload to complete. 3 Secs
* should be sufficient time for this process to complete.
*/
- setup_timer(&tgt->upld_timer, bnx2fc_upld_timer, (unsigned long)tgt);
- mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
-
BNX2FC_TGT_DBG(tgt, "waiting for disable compl\n");
- wait_event_interruptible(tgt->upld_wait,
- (test_bit(
- BNX2FC_FLAG_UPLD_REQ_COMPL,
- &tgt->flags)));
-
- if (signal_pending(current))
- flush_signals(current);
-
- del_timer_sync(&tgt->upld_timer);
+ bnx2fc_upld_wait(tgt);
/*
* traverse thru the active_q and tmf_q and cleanup
@@ -308,24 +325,13 @@ static void bnx2fc_upload_session(struct fcoe_port *port,
bnx2fc_send_session_destroy_req(hba, tgt);
/* wait for destroy to complete */
- setup_timer(&tgt->upld_timer,
- bnx2fc_upld_timer, (unsigned long)tgt);
- mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
-
- wait_event_interruptible(tgt->upld_wait,
- (test_bit(
- BNX2FC_FLAG_UPLD_REQ_COMPL,
- &tgt->flags)));
+ bnx2fc_upld_wait(tgt);
if (!(test_bit(BNX2FC_FLAG_DESTROYED, &tgt->flags)))
printk(KERN_ERR PFX "ERROR!! destroy timed out\n");
BNX2FC_TGT_DBG(tgt, "destroy wait complete flags = 0x%lx\n",
tgt->flags);
- if (signal_pending(current))
- flush_signals(current);
-
- del_timer_sync(&tgt->upld_timer);
} else if (test_bit(BNX2FC_FLAG_DISABLE_FAILED, &tgt->flags)) {
printk(KERN_ERR PFX "ERROR!! DISABLE req failed, destroy"
@@ -381,7 +387,9 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
tgt->rq_cons_idx = 0;
atomic_set(&tgt->num_active_ios, 0);
- if (rdata->flags & FC_RP_FLAGS_RETRY) {
+ if (rdata->flags & FC_RP_FLAGS_RETRY &&
+ rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET &&
+ !(rdata->ids.roles & FC_RPORT_ROLE_FCP_INITIATOR)) {
tgt->dev_type = TYPE_TAPE;
tgt->io_timeout = 0; /* use default ULP timeout */
} else {
@@ -479,7 +487,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
tgt = (struct bnx2fc_rport *)&rp[1];
/* This can happen when ADISC finds the same target */
- if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) {
+ if (test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)) {
BNX2FC_TGT_DBG(tgt, "already offloaded\n");
mutex_unlock(&hba->hba_mutex);
return;
@@ -494,11 +502,8 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
BNX2FC_TGT_DBG(tgt, "OFFLOAD num_ofld_sess = %d\n",
hba->num_ofld_sess);
- if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) {
- /*
- * Session is offloaded and enabled. Map
- * doorbell register for this target
- */
+ if (test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)) {
+ /* Session is offloaded and enabled. */
BNX2FC_TGT_DBG(tgt, "sess offloaded\n");
/* This counter is protected with hba mutex */
hba->num_ofld_sess++;
@@ -535,7 +540,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
*/
tgt = (struct bnx2fc_rport *)&rp[1];
- if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) {
+ if (!(test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags))) {
mutex_unlock(&hba->hba_mutex);
break;
}
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index b44d04e..f109e3b 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -580,8 +580,8 @@ struct bnx2i_5771x_dbell {
* @sq_mem_size: SQ size
* @sq_prod_qe: SQ producer entry pointer
* @sq_cons_qe: SQ consumer entry pointer
- * @sq_first_qe: virtaul address of first entry in SQ
- * @sq_last_qe: virtaul address of last entry in SQ
+ * @sq_first_qe: virtual address of first entry in SQ
+ * @sq_last_qe: virtual address of last entry in SQ
* @sq_prod_idx: SQ producer index
* @sq_cons_idx: SQ consumer index
* @sqe_left: number sq entry left
@@ -593,8 +593,8 @@ struct bnx2i_5771x_dbell {
* @cq_mem_size: CQ size
* @cq_prod_qe: CQ producer entry pointer
* @cq_cons_qe: CQ consumer entry pointer
- * @cq_first_qe: virtaul address of first entry in CQ
- * @cq_last_qe: virtaul address of last entry in CQ
+ * @cq_first_qe: virtual address of first entry in CQ
+ * @cq_last_qe: virtual address of last entry in CQ
* @cq_prod_idx: CQ producer index
* @cq_cons_idx: CQ consumer index
* @cqe_left: number cq entry left
@@ -608,8 +608,8 @@ struct bnx2i_5771x_dbell {
* @rq_mem_size: RQ size
* @rq_prod_qe: RQ producer entry pointer
* @rq_cons_qe: RQ consumer entry pointer
- * @rq_first_qe: virtaul address of first entry in RQ
- * @rq_last_qe: virtaul address of last entry in RQ
+ * @rq_first_qe: virtual address of first entry in RQ
+ * @rq_last_qe: virtual address of last entry in RQ
* @rq_prod_idx: RQ producer index
* @rq_cons_idx: RQ consumer index
* @rqe_left: number rq entry left
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 91eec60..a28b03e 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1317,7 +1317,7 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
(1ULL << ISCSI_KCQE_COMPLETION_STATUS_PROTOCOL_ERR_LUN));
if (error_mask1) {
iscsi_init2.error_bit_map[0] = error_mask1;
- mask64 &= (u32)(~mask64);
+ mask64 ^= (u32)(mask64);
mask64 |= error_mask1;
} else
iscsi_init2.error_bit_map[0] = (u32) mask64;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index ee009e4ad..50fef69 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -21,7 +21,7 @@ static u32 adapter_count;
#define DRV_MODULE_VERSION "2.7.2.2"
#define DRV_MODULE_RELDATE "Apr 25, 2012"
-static char version[] __devinitdata =
+static char version[] =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c
index d40ea2f..1e3f96a 100644
--- a/drivers/scsi/bvme6000_scsi.c
+++ b/drivers/scsi/bvme6000_scsi.c
@@ -34,7 +34,7 @@ static struct scsi_host_template bvme6000_scsi_driver_template = {
static struct platform_device *bvme6000_scsi_device;
-static __devinit int
+static int
bvme6000_probe(struct platform_device *dev)
{
struct Scsi_Host *host;
@@ -88,7 +88,7 @@ bvme6000_probe(struct platform_device *dev)
return -ENODEV;
}
-static __devexit int
+static int
bvme6000_device_remove(struct platform_device *dev)
{
struct Scsi_Host *host = platform_get_drvdata(dev);
@@ -108,7 +108,7 @@ static struct platform_driver bvme6000_scsi_driver = {
.owner = THIS_MODULE,
},
.probe = bvme6000_probe,
- .remove = __devexit_p(bvme6000_device_remove),
+ .remove = bvme6000_device_remove,
};
static int __init bvme6000_scsi_init(void)
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index a15474e..2a32374 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -895,7 +895,7 @@ static int ch_probe(struct device *dev)
{
struct scsi_device *sd = to_scsi_device(dev);
struct device *class_dev;
- int minor, ret = -ENOMEM;
+ int ret;
scsi_changer *ch;
if (sd->type != TYPE_MEDIUM_CHANGER)
@@ -905,22 +905,19 @@ static int ch_probe(struct device *dev)
if (NULL == ch)
return -ENOMEM;
- if (!idr_pre_get(&ch_index_idr, GFP_KERNEL))
- goto free_ch;
-
+ idr_preload(GFP_KERNEL);
spin_lock(&ch_index_lock);
- ret = idr_get_new(&ch_index_idr, ch, &minor);
+ ret = idr_alloc(&ch_index_idr, ch, 0, CH_MAX_DEVS + 1, GFP_NOWAIT);
spin_unlock(&ch_index_lock);
+ idr_preload_end();
- if (ret)
+ if (ret < 0) {
+ if (ret == -ENOSPC)
+ ret = -ENODEV;
goto free_ch;
-
- if (minor > CH_MAX_DEVS) {
- ret = -ENODEV;
- goto remove_idr;
}
- ch->minor = minor;
+ ch->minor = ret;
sprintf(ch->name,"ch%d",ch->minor);
class_dev = device_create(ch_sysfs_class, dev,
@@ -944,7 +941,7 @@ static int ch_probe(struct device *dev)
return 0;
remove_idr:
- idr_remove(&ch_index_idr, minor);
+ idr_remove(&ch_index_idr, ch->minor);
free_ch:
kfree(ch);
return ret;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 76e4c03..d35a5d6 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1,10 +1,10 @@
-/*
+/*
* ASCII values for a number of symbolic constants, printing functions,
* etc.
* Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422)
* Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
* by D. Gilbert and aeb (20020609)
- * Update to SPC-4 T10/1713-D Rev 20, 22 May 2009, D. Gilbert 20090624
+ * Updated to SPC-4 T10/1713-D Rev 36g, D. Gilbert 20130701
*/
#include <linux/blkdev.h>
@@ -21,12 +21,13 @@
/* Commands with service actions that change the command name */
-#define MAINTENANCE_IN 0xa3
-#define MAINTENANCE_OUT 0xa4
#define SERVICE_ACTION_IN_12 0xab
#define SERVICE_ACTION_OUT_12 0xa9
+#define SERVICE_ACTION_BIDIRECTIONAL 0x9d
#define SERVICE_ACTION_IN_16 0x9e
#define SERVICE_ACTION_OUT_16 0x9f
+#define THIRD_PARTY_COPY_OUT 0x83
+#define THIRD_PARTY_COPY_IN 0x84
@@ -36,11 +37,11 @@ static const char * cdb_byte0_names[] = {
/* 04-07 */ "Format Unit/Medium", "Read Block Limits", NULL,
"Reassign Blocks",
/* 08-0d */ "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
-/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
+/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
/* 13-16 */ "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
"Reserve(6)",
/* 17-1a */ "Release(6)", "Copy", "Erase", "Mode Sense(6)",
-/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
+/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
/* 1e-1f */ "Prevent/Allow Medium Removal", NULL,
/* 20-22 */ NULL, NULL, NULL,
/* 23-28 */ "Read Format Capacities", "Set Window",
@@ -48,16 +49,16 @@ static const char * cdb_byte0_names[] = {
/* 29-2d */ "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
"Read updated block",
/* 2e-31 */ "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
-/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position",
+/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position",
/* 35-37 */ "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
- "Read Defect Data(10)",
-/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
- "Read Buffer",
+ "Read Defect Data(10)",
+/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
+ "Read Buffer",
/* 3d-3f */ "Update Block", "Read Long(10)", "Write Long(10)",
/* 40-41 */ "Change Definition", "Write Same(10)",
/* 42-48 */ "Unmap/Read sub-channel", "Read TOC/PMA/ATIP",
"Read density support", "Play audio(10)", "Get configuration",
- "Play audio msf", "Play audio track/index",
+ "Play audio msf", "Sanitize/Play audio track/index",
/* 49-4f */ "Play track relative(10)", "Get event status notification",
"Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
NULL,
@@ -72,17 +73,17 @@ static const char * cdb_byte0_names[] = {
/* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, "Extended CDB",
"Variable length",
-/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", "Extended copy",
- "Receive copy results",
+/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)",
+ "Third party copy out", "Third party copy in",
/* 85-89 */ "ATA command pass through(16)", "Access control in",
- "Access control out", "Read(16)", "Memory Export Out(16)",
+ "Access control out", "Read(16)", "Compare and Write",
/* 8a-8f */ "Write(16)", "ORWrite", "Read attributes", "Write attributes",
"Write and verify(16)", "Verify(16)",
/* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)",
"Lock/unlock cache(16)", "Write same(16)", NULL,
/* 95-99 */ NULL, NULL, NULL, NULL, NULL,
-/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in(16)",
- "Service action out(16)",
+/* 9a-9f */ NULL, NULL, NULL, "Service action bidirectional",
+ "Service action in(16)", "Service action out(16)",
/* a0-a5 */ "Report luns", "ATA command pass through(12)/Blank",
"Security protocol in", "Maintenance in", "Maintenance out",
"Move medium/play audio(12)",
@@ -122,6 +123,7 @@ static const struct value_name_pair maint_out_arr[] = {
{0x6, "Set identifying information"},
{0xa, "Set target port groups"},
{0xb, "Change aliases"},
+ {0xc, "Remove I_T nexus"},
{0xe, "Set priority"},
{0xf, "Set timestamp"},
{0x10, "Management protocol out"},
@@ -138,10 +140,16 @@ static const struct value_name_pair serv_out12_arr[] = {
};
#define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr)
+static const struct value_name_pair serv_bidi_arr[] = {
+ {-1, "dummy entry"},
+};
+#define SERV_BIDI_SZ ARRAY_SIZE(serv_bidi_arr)
+
static const struct value_name_pair serv_in16_arr[] = {
{0x10, "Read capacity(16)"},
{0x11, "Read long(16)"},
{0x12, "Get LBA status"},
+ {0x13, "Report referrals"},
};
#define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
@@ -151,6 +159,51 @@ static const struct value_name_pair serv_out16_arr[] = {
};
#define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr)
+static const struct value_name_pair pr_in_arr[] = {
+ {0x0, "Persistent reserve in, read keys"},
+ {0x1, "Persistent reserve in, read reservation"},
+ {0x2, "Persistent reserve in, report capabilities"},
+ {0x3, "Persistent reserve in, read full status"},
+};
+#define PR_IN_SZ ARRAY_SIZE(pr_in_arr)
+
+static const struct value_name_pair pr_out_arr[] = {
+ {0x0, "Persistent reserve out, register"},
+ {0x1, "Persistent reserve out, reserve"},
+ {0x2, "Persistent reserve out, release"},
+ {0x3, "Persistent reserve out, clear"},
+ {0x4, "Persistent reserve out, preempt"},
+ {0x5, "Persistent reserve out, preempt and abort"},
+ {0x6, "Persistent reserve out, register and ignore existing key"},
+ {0x7, "Persistent reserve out, register and move"},
+};
+#define PR_OUT_SZ ARRAY_SIZE(pr_out_arr)
+
+/* SPC-4 rev 34 renamed the Extended Copy opcode to Third Party Copy Out.
+ LID1 (List Identifier length: 1 byte) is the Extended Copy found in SPC-2
+ and SPC-3 */
+static const struct value_name_pair tpc_out_arr[] = {
+ {0x0, "Extended copy(LID1)"},
+ {0x1, "Extended copy(LID4)"},
+ {0x10, "Populate token"},
+ {0x11, "Write using token"},
+ {0x1c, "Copy operation abort"},
+};
+#define TPC_OUT_SZ ARRAY_SIZE(tpc_out_arr)
+
+static const struct value_name_pair tpc_in_arr[] = {
+ {0x0, "Receive copy status(LID1)"},
+ {0x1, "Receive copy data(LID1)"},
+ {0x3, "Receive copy operating parameters"},
+ {0x4, "Receive copy failure details(LID1)"},
+ {0x5, "Receive copy status(LID4)"},
+ {0x6, "Receive copy data(LID4)"},
+ {0x7, "Receive ROD token information"},
+ {0x8, "Report all ROD tokens"},
+};
+#define TPC_IN_SZ ARRAY_SIZE(tpc_in_arr)
+
+
static const struct value_name_pair variable_length_arr[] = {
{0x1, "Rebuild(32)"},
{0x2, "Regenerate(32)"},
@@ -207,6 +260,7 @@ static const char * get_sa_name(const struct value_name_pair * arr,
static void print_opcode_name(unsigned char * cdbp, int cdb_len)
{
int sa, len, cdb0;
+ int fin_name = 0;
const char * name;
cdb0 = cdbp[0];
@@ -219,7 +273,8 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
break;
}
sa = (cdbp[8] << 8) + cdbp[9];
- name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ, sa);
+ name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ,
+ sa);
if (name)
printk("%s", name);
else
@@ -232,50 +287,57 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
case MAINTENANCE_IN:
sa = cdbp[1] & 0x1f;
name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
- if (name)
- printk("%s", name);
- else
- printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ fin_name = 1;
break;
case MAINTENANCE_OUT:
sa = cdbp[1] & 0x1f;
name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa);
- if (name)
- printk("%s", name);
- else
- printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ fin_name = 1;
+ break;
+ case PERSISTENT_RESERVE_IN:
+ sa = cdbp[1] & 0x1f;
+ name = get_sa_name(pr_in_arr, PR_IN_SZ, sa);
+ fin_name = 1;
+ break;
+ case PERSISTENT_RESERVE_OUT:
+ sa = cdbp[1] & 0x1f;
+ name = get_sa_name(pr_out_arr, PR_OUT_SZ, sa);
+ fin_name = 1;
break;
case SERVICE_ACTION_IN_12:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa);
- if (name)
- printk("%s", name);
- else
- printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ fin_name = 1;
break;
case SERVICE_ACTION_OUT_12:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa);
- if (name)
- printk("%s", name);
- else
- printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ fin_name = 1;
+ break;
+ case SERVICE_ACTION_BIDIRECTIONAL:
+ sa = cdbp[1] & 0x1f;
+ name = get_sa_name(serv_bidi_arr, SERV_BIDI_SZ, sa);
+ fin_name = 1;
break;
case SERVICE_ACTION_IN_16:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa);
- if (name)
- printk("%s", name);
- else
- printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ fin_name = 1;
break;
case SERVICE_ACTION_OUT_16:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa);
- if (name)
- printk("%s", name);
- else
- printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ fin_name = 1;
+ break;
+ case THIRD_PARTY_COPY_IN:
+ sa = cdbp[1] & 0x1f;
+ name = get_sa_name(tpc_in_arr, TPC_IN_SZ, sa);
+ fin_name = 1;
+ break;
+ case THIRD_PARTY_COPY_OUT:
+ sa = cdbp[1] & 0x1f;
+ name = get_sa_name(tpc_out_arr, TPC_OUT_SZ, sa);
+ fin_name = 1;
break;
default:
if (cdb0 < 0xc0) {
@@ -288,6 +350,12 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
printk("cdb[0]=0x%x (vendor)", cdb0);
break;
}
+ if (fin_name) {
+ if (name)
+ printk("%s", name);
+ else
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+ }
}
#else /* ifndef CONFIG_SCSI_CONSTANTS */
@@ -312,10 +380,15 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
break;
case MAINTENANCE_IN:
case MAINTENANCE_OUT:
+ case PERSISTENT_RESERVE_IN:
+ case PERSISTENT_RESERVE_OUT:
case SERVICE_ACTION_IN_12:
case SERVICE_ACTION_OUT_12:
+ case SERVICE_ACTION_BIDIRECTIONAL:
case SERVICE_ACTION_IN_16:
case SERVICE_ACTION_OUT_16:
+ case THIRD_PARTY_COPY_IN:
+ case THIRD_PARTY_COPY_OUT:
sa = cdbp[1] & 0x1f;
printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
@@ -327,7 +400,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
break;
}
}
-#endif
+#endif
void __scsi_print_command(unsigned char *cdb)
{
@@ -336,7 +409,7 @@ void __scsi_print_command(unsigned char *cdb)
print_opcode_name(cdb, 0);
len = scsi_command_size(cdb);
/* print out all bytes in cdb */
- for (k = 0; k < len; ++k)
+ for (k = 0; k < len; ++k)
printk(" %02x", cdb[k]);
printk("\n");
}
@@ -404,8 +477,9 @@ struct error_info {
/*
* The canonical list of T10 Additional Sense Codes is available at:
- * http://www.t10.org/lists/asc-num.txt
+ * http://www.t10.org/lists/asc-num.txt [most recent: 20130605]
*/
+
static const struct error_info additional[] =
{
{0x0000, "No additional sense information"},
@@ -430,6 +504,8 @@ static const struct error_info additional[] =
{0x001C, "Verify operation in progress"},
{0x001D, "ATA pass through information available"},
{0x001E, "Conflicting SA creation request"},
+ {0x001F, "Logical unit transitioning to another power condition"},
+ {0x0020, "Extended copy information available"},
{0x0100, "No index/sector signal"},
@@ -460,6 +536,17 @@ static const struct error_info additional[] =
{0x0412, "Logical unit not ready, offline"},
{0x0413, "Logical unit not ready, SA creation in progress"},
{0x0414, "Logical unit not ready, space allocation in progress"},
+ {0x0415, "Logical unit not ready, robotics disabled"},
+ {0x0416, "Logical unit not ready, configuration required"},
+ {0x0417, "Logical unit not ready, calibration required"},
+ {0x0418, "Logical unit not ready, a door is open"},
+ {0x0419, "Logical unit not ready, operating in sequential mode"},
+ {0x041A, "Logical unit not ready, start stop unit command in "
+ "progress"},
+ {0x041B, "Logical unit not ready, sanitize in progress"},
+ {0x041C, "Logical unit not ready, additional power use not yet "
+ "granted"},
+ {0x041D, "Logical unit not ready, configuration in progress"},
{0x0500, "Logical unit does not respond to selection"},
@@ -490,6 +577,7 @@ static const struct error_info additional[] =
{0x0B06, "Warning - non-volatile cache now volatile"},
{0x0B07, "Warning - degraded power to non-volatile cache"},
{0x0B08, "Warning - power loss expected"},
+ {0x0B09, "Warning - device statistics notification active"},
{0x0C00, "Write error"},
{0x0C01, "Write error - recovered with auto reallocation"},
@@ -505,6 +593,7 @@ static const struct error_info additional[] =
{0x0C0B, "Auxiliary memory write error"},
{0x0C0C, "Write error - unexpected unsolicited data"},
{0x0C0D, "Write error - not enough unsolicited data"},
+ {0x0C0E, "Multiple write errors"},
{0x0C0F, "Defects in error window"},
{0x0D00, "Error detected by third party temporary initiator"},
@@ -523,6 +612,8 @@ static const struct error_info additional[] =
{0x1001, "Logical block guard check failed"},
{0x1002, "Logical block application tag check failed"},
{0x1003, "Logical block reference tag check failed"},
+ {0x1004, "Logical block protection error on recover buffered data"},
+ {0x1005, "Logical block protection method error"},
{0x1100, "Unrecovered read error"},
{0x1101, "Read retries exhausted"},
@@ -545,6 +636,7 @@ static const struct error_info additional[] =
{0x1112, "Auxiliary memory read error"},
{0x1113, "Read error - failed retransmission request"},
{0x1114, "Read error - lba marked bad by application client"},
+ {0x1115, "Write after sanitize required"},
{0x1200, "Address mark not found for id field"},
@@ -622,6 +714,7 @@ static const struct error_info additional[] =
{0x2009, "Access denied - invalid LU identifier"},
{0x200A, "Access denied - invalid proxy token"},
{0x200B, "Access denied - ACL LUN conflict"},
+ {0x200C, "Illegal command when not in append-only mode"},
{0x2100, "Logical block address out of range"},
{0x2101, "Invalid element address"},
@@ -630,6 +723,19 @@ static const struct error_info additional[] =
{0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"},
+ {0x2300, "Invalid token operation, cause not reportable"},
+ {0x2301, "Invalid token operation, unsupported token type"},
+ {0x2302, "Invalid token operation, remote token usage not supported"},
+ {0x2303, "Invalid token operation, remote rod token creation not "
+ "supported"},
+ {0x2304, "Invalid token operation, token unknown"},
+ {0x2305, "Invalid token operation, token corrupt"},
+ {0x2306, "Invalid token operation, token revoked"},
+ {0x2307, "Invalid token operation, token expired"},
+ {0x2308, "Invalid token operation, token cancelled"},
+ {0x2309, "Invalid token operation, token deleted"},
+ {0x230A, "Invalid token operation, invalid token length"},
+
{0x2400, "Invalid field in cdb"},
{0x2401, "CDB decryption error"},
{0x2402, "Obsolete"},
@@ -705,6 +811,7 @@ static const struct error_info additional[] =
"event"},
{0x2A13, "Data encryption key instance counter has changed"},
{0x2A14, "SA creation capabilities data has changed"},
+ {0x2A15, "Medium removal prevention preempted"},
{0x2B00, "Copy cannot execute since host cannot disconnect"},
@@ -720,6 +827,7 @@ static const struct error_info additional[] =
{0x2C09, "Previous reservation conflict status"},
{0x2C0A, "Partition or collection contains user objects"},
{0x2C0B, "Not reserved"},
+ {0x2C0C, "Orwrite generation does not match"},
{0x2D00, "Overwrite error on update in place"},
@@ -728,6 +836,7 @@ static const struct error_info additional[] =
{0x2F00, "Commands cleared by another initiator"},
{0x2F01, "Commands cleared by power loss notification"},
{0x2F02, "Commands cleared by device server"},
+ {0x2F03, "Some commands cleared by queuing layer event"},
{0x3000, "Incompatible medium installed"},
{0x3001, "Cannot read medium - unknown format"},
@@ -745,10 +854,12 @@ static const struct error_info additional[] =
{0x3010, "Medium not formatted"},
{0x3011, "Incompatible volume type"},
{0x3012, "Incompatible volume qualifier"},
+ {0x3013, "Cleaning volume expired"},
{0x3100, "Medium format corrupted"},
{0x3101, "Format command failed"},
{0x3102, "Zoned formatting failed due to spare linking"},
+ {0x3103, "Sanitize command failed"},
{0x3200, "No defect spare location available"},
{0x3201, "Defect list update failure"},
@@ -809,6 +920,8 @@ static const struct error_info additional[] =
{0x3B19, "Element enabled"},
{0x3B1A, "Data transfer device removed"},
{0x3B1B, "Data transfer device inserted"},
+ {0x3B1C, "Too many logical objects on partition to support "
+ "operation"},
{0x3D00, "Invalid bits in identify message"},
@@ -839,6 +952,7 @@ static const struct error_info additional[] =
{0x3F12, "iSCSI IP address added"},
{0x3F13, "iSCSI IP address removed"},
{0x3F14, "iSCSI IP address changed"},
+ {0x3F15, "Inspect referrals sense descriptors"},
/*
* {0x40NN, "Ram failure"},
* {0x40NN, "Diagnostic failure on component nn"},
@@ -848,6 +962,7 @@ static const struct error_info additional[] =
{0x4300, "Message error"},
{0x4400, "Internal target failure"},
+ {0x4401, "Persistent reservation information lost"},
{0x4471, "ATA device failed set features"},
{0x4500, "Select or reselect failure"},
@@ -876,6 +991,21 @@ static const struct error_info additional[] =
{0x4B04, "Nak received"},
{0x4B05, "Data offset error"},
{0x4B06, "Initiator response timeout"},
+ {0x4B07, "Connection lost"},
+ {0x4B08, "Data-in buffer overflow - data buffer size"},
+ {0x4B09, "Data-in buffer overflow - data buffer descriptor area"},
+ {0x4B0A, "Data-in buffer error"},
+ {0x4B0B, "Data-out buffer overflow - data buffer size"},
+ {0x4B0C, "Data-out buffer overflow - data buffer descriptor area"},
+ {0x4B0D, "Data-out buffer error"},
+ {0x4B0E, "PCIe fabric error"},
+ {0x4B0F, "PCIe completion timeout"},
+ {0x4B10, "PCIe completer abort"},
+ {0x4B11, "PCIe poisoned tlp received"},
+ {0x4B12, "PCIe eCRC check failed"},
+ {0x4B13, "PCIe unsupported request"},
+ {0x4B14, "PCIe acs violation"},
+ {0x4B15, "PCIe tlp prefix blocked"},
{0x4C00, "Logical unit failed self-configuration"},
/*
@@ -897,6 +1027,10 @@ static const struct error_info additional[] =
{0x5302, "Medium removal prevented"},
{0x5303, "Medium removal prevented by data transfer element"},
{0x5304, "Medium thread or unthread failure"},
+ {0x5305, "Volume identifier invalid"},
+ {0x5306, "Volume identifier missing"},
+ {0x5307, "Duplicate volume identifier"},
+ {0x5308, "Element status unknown"},
{0x5400, "Scsi to host system interface failure"},
@@ -911,6 +1045,9 @@ static const struct error_info additional[] =
{0x5508, "Maximum number of supplemental decryption keys exceeded"},
{0x5509, "Medium auxiliary memory not accessible"},
{0x550A, "Data currently unavailable"},
+ {0x550B, "Insufficient power for operation"},
+ {0x550C, "Insufficient resources to create rod"},
+ {0x550D, "Insufficient resources to create rod token"},
{0x5700, "Unable to recover table-of-contents"},
@@ -1069,6 +1206,7 @@ static const struct error_info additional[] =
{0x670B, "ATA device feature not enabled"},
{0x6800, "Logical unit not configured"},
+ {0x6801, "Subsidiary logical unit not configured"},
{0x6900, "Data loss on logical unit"},
{0x6901, "Multiple logical unit failures"},
@@ -1185,10 +1323,13 @@ static const char * const snstext[] = {
"Vendor Specific(9)",
"Copy Aborted", /* A: COPY or COMPARE was aborted */
"Aborted Command", /* B: The target aborted the command */
- "Equal", /* C: A SEARCH DATA command found data equal */
+ "Equal", /* C: A SEARCH DATA command found data equal,
+ reserved in SPC-4 rev 36 */
"Volume Overflow", /* D: Medium full with still data to be written */
"Miscompare", /* E: Source data and data on the medium
do not agree */
+ "Completed", /* F: command completed sense data reported,
+ may occur for successful command */
};
#endif
@@ -1306,7 +1447,7 @@ scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
struct scsi_sense_hdr *sshdr)
{
int k, num, res;
-
+
res = scsi_normalize_sense(sense_buffer, sense_len, sshdr);
if (0 == res) {
/* this may be SCSI-1 sense data */
@@ -1459,5 +1600,3 @@ void scsi_print_result(struct scsi_cmnd *cmd)
scsi_show_result(cmd->result);
}
EXPORT_SYMBOL(scsi_print_result);
-
-
diff --git a/drivers/scsi/csiostor/Makefile b/drivers/scsi/csiostor/Makefile
index b581966..913b9a9 100644
--- a/drivers/scsi/csiostor/Makefile
+++ b/drivers/scsi/csiostor/Makefile
@@ -8,4 +8,5 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor.o
csiostor-objs := csio_attr.o csio_init.o csio_lnode.o csio_scsi.o \
- csio_hw.o csio_isr.o csio_mb.o csio_rnode.o csio_wr.o
+ csio_hw.o csio_hw_t4.o csio_hw_t5.o csio_isr.o \
+ csio_mb.o csio_rnode.o csio_wr.o
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
index 8ecdb94..0eb35b9 100644
--- a/drivers/scsi/csiostor/csio_hw.c
+++ b/drivers/scsi/csiostor/csio_hw.c
@@ -61,7 +61,7 @@ int csio_msi = 2;
static int dev_num;
/* FCoE Adapter types & its description */
-static const struct csio_adap_desc csio_fcoe_adapters[] = {
+static const struct csio_adap_desc csio_t4_fcoe_adapters[] = {
{"T440-Dbg 10G", "Chelsio T440-Dbg 10G [FCoE]"},
{"T420-CR 10G", "Chelsio T420-CR 10G [FCoE]"},
{"T422-CR 10G/1G", "Chelsio T422-CR 10G/1G [FCoE]"},
@@ -77,7 +77,38 @@ static const struct csio_adap_desc csio_fcoe_adapters[] = {
{"B404-BT 1G", "Chelsio B404-BT 1G [FCoE]"},
{"T480-CR 10G", "Chelsio T480-CR 10G [FCoE]"},
{"T440-LP-CR 10G", "Chelsio T440-LP-CR 10G [FCoE]"},
- {"T4 FPGA", "Chelsio T4 FPGA [FCoE]"}
+ {"AMSTERDAM 10G", "Chelsio AMSTERDAM 10G [FCoE]"},
+ {"HUAWEI T480 10G", "Chelsio HUAWEI T480 10G [FCoE]"},
+ {"HUAWEI T440 10G", "Chelsio HUAWEI T440 10G [FCoE]"},
+ {"HUAWEI STG 10G", "Chelsio HUAWEI STG 10G [FCoE]"},
+ {"ACROMAG XAUI 10G", "Chelsio ACROMAG XAUI 10G [FCoE]"},
+ {"ACROMAG SFP+ 10G", "Chelsio ACROMAG SFP+ 10G [FCoE]"},
+ {"QUANTA SFP+ 10G", "Chelsio QUANTA SFP+ 10G [FCoE]"},
+ {"HUAWEI 10Gbase-T", "Chelsio HUAWEI 10Gbase-T [FCoE]"},
+ {"HUAWEI T4TOE 10G", "Chelsio HUAWEI T4TOE 10G [FCoE]"}
+};
+
+static const struct csio_adap_desc csio_t5_fcoe_adapters[] = {
+ {"T580-Dbg 10G", "Chelsio T580-Dbg 10G [FCoE]"},
+ {"T520-CR 10G", "Chelsio T520-CR 10G [FCoE]"},
+ {"T522-CR 10G/1G", "Chelsio T452-CR 10G/1G [FCoE]"},
+ {"T540-CR 10G", "Chelsio T540-CR 10G [FCoE]"},
+ {"T520-BCH 10G", "Chelsio T520-BCH 10G [FCoE]"},
+ {"T540-BCH 10G", "Chelsio T540-BCH 10G [FCoE]"},
+ {"T540-CH 10G", "Chelsio T540-CH 10G [FCoE]"},
+ {"T520-SO 10G", "Chelsio T520-SO 10G [FCoE]"},
+ {"T520-CX4 10G", "Chelsio T520-CX4 10G [FCoE]"},
+ {"T520-BT 10G", "Chelsio T520-BT 10G [FCoE]"},
+ {"T504-BT 1G", "Chelsio T504-BT 1G [FCoE]"},
+ {"B520-SR 10G", "Chelsio B520-SR 10G [FCoE]"},
+ {"B504-BT 1G", "Chelsio B504-BT 1G [FCoE]"},
+ {"T580-CR 10G", "Chelsio T580-CR 10G [FCoE]"},
+ {"T540-LP-CR 10G", "Chelsio T540-LP-CR 10G [FCoE]"},
+ {"AMSTERDAM 10G", "Chelsio AMSTERDAM 10G [FCoE]"},
+ {"T580-LP-CR 40G", "Chelsio T580-LP-CR 40G [FCoE]"},
+ {"T520-LL-CR 10G", "Chelsio T520-LL-CR 10G [FCoE]"},
+ {"T560-CR 40G", "Chelsio T560-CR 40G [FCoE]"},
+ {"T580-CR 40G", "Chelsio T580-CR 40G [FCoE]"}
};
static void csio_mgmtm_cleanup(struct csio_mgmtm *);
@@ -124,7 +155,7 @@ int csio_is_hw_removing(struct csio_hw *hw)
* at the time it indicated completion is stored there. Returns 0 if the
* operation completes and -EAGAIN otherwise.
*/
-static int
+int
csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask,
int polarity, int attempts, int delay, uint32_t *valp)
{
@@ -145,6 +176,24 @@ csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask,
}
}
+/*
+ * csio_hw_tp_wr_bits_indirect - set/clear bits in an indirect TP register
+ * @hw: the adapter
+ * @addr: the indirect TP register address
+ * @mask: specifies the field within the register to modify
+ * @val: new value for the field
+ *
+ * Sets a field of an indirect TP register to the given value.
+ */
+void
+csio_hw_tp_wr_bits_indirect(struct csio_hw *hw, unsigned int addr,
+ unsigned int mask, unsigned int val)
+{
+ csio_wr_reg32(hw, addr, TP_PIO_ADDR);
+ val |= csio_rd_reg32(hw, TP_PIO_DATA) & ~mask;
+ csio_wr_reg32(hw, val, TP_PIO_DATA);
+}
+
void
csio_set_reg_field(struct csio_hw *hw, uint32_t reg, uint32_t mask,
uint32_t value)
@@ -157,242 +206,22 @@ csio_set_reg_field(struct csio_hw *hw, uint32_t reg, uint32_t mask,
}
-/*
- * csio_hw_mc_read - read from MC through backdoor accesses
- * @hw: the hw module
- * @addr: address of first byte requested
- * @data: 64 bytes of data containing the requested address
- * @ecc: where to store the corresponding 64-bit ECC word
- *
- * Read 64 bytes of data from MC starting at a 64-byte-aligned address
- * that covers the requested address @addr. If @parity is not %NULL it
- * is assigned the 64-bit ECC word for the read data.
- */
-int
-csio_hw_mc_read(struct csio_hw *hw, uint32_t addr, __be32 *data,
- uint64_t *ecc)
-{
- int i;
-
- if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
- return -EBUSY;
- csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
- csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
- csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
- csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST | BIST_CMD_GAP(1),
- MC_BIST_CMD);
- i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
- 0, 10, 1, NULL);
- if (i)
- return i;
-
-#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
-
- for (i = 15; i >= 0; i--)
- *data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
- if (ecc)
- *ecc = csio_rd_reg64(hw, MC_DATA(16));
-#undef MC_DATA
- return 0;
-}
-
-/*
- * csio_hw_edc_read - read from EDC through backdoor accesses
- * @hw: the hw module
- * @idx: which EDC to access
- * @addr: address of first byte requested
- * @data: 64 bytes of data containing the requested address
- * @ecc: where to store the corresponding 64-bit ECC word
- *
- * Read 64 bytes of data from EDC starting at a 64-byte-aligned address
- * that covers the requested address @addr. If @parity is not %NULL it
- * is assigned the 64-bit ECC word for the read data.
- */
-int
-csio_hw_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
- uint64_t *ecc)
-{
- int i;
-
- idx *= EDC_STRIDE;
- if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
- return -EBUSY;
- csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
- csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
- csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
- csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
- EDC_BIST_CMD + idx);
- i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
- 0, 10, 1, NULL);
- if (i)
- return i;
-
-#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
-
- for (i = 15; i >= 0; i--)
- *data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
- if (ecc)
- *ecc = csio_rd_reg64(hw, EDC_DATA(16));
-#undef EDC_DATA
- return 0;
-}
-
-/*
- * csio_mem_win_rw - read/write memory through PCIE memory window
- * @hw: the adapter
- * @addr: address of first byte requested
- * @data: MEMWIN0_APERTURE bytes of data containing the requested address
- * @dir: direction of transfer 1 => read, 0 => write
- *
- * Read/write MEMWIN0_APERTURE bytes of data from MC starting at a
- * MEMWIN0_APERTURE-byte-aligned address that covers the requested
- * address @addr.
- */
-static int
-csio_mem_win_rw(struct csio_hw *hw, u32 addr, u32 *data, int dir)
-{
- int i;
-
- /*
- * Setup offset into PCIE memory window. Address must be a
- * MEMWIN0_APERTURE-byte-aligned address. (Read back MA register to
- * ensure that changes propagate before we attempt to use the new
- * values.)
- */
- csio_wr_reg32(hw, addr & ~(MEMWIN0_APERTURE - 1),
- PCIE_MEM_ACCESS_OFFSET);
- csio_rd_reg32(hw, PCIE_MEM_ACCESS_OFFSET);
-
- /* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
- for (i = 0; i < MEMWIN0_APERTURE; i = i + sizeof(__be32)) {
- if (dir)
- *data++ = csio_rd_reg32(hw, (MEMWIN0_BASE + i));
- else
- csio_wr_reg32(hw, *data++, (MEMWIN0_BASE + i));
- }
-
- return 0;
-}
-
-/*
- * csio_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
- * @hw: the csio_hw
- * @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC
- * @addr: address within indicated memory type
- * @len: amount of memory to transfer
- * @buf: host memory buffer
- * @dir: direction of transfer 1 => read, 0 => write
- *
- * Reads/writes an [almost] arbitrary memory region in the firmware: the
- * firmware memory address, length and host buffer must be aligned on
- * 32-bit boudaries. The memory is transferred as a raw byte sequence
- * from/to the firmware's memory. If this memory contains data
- * structures which contain multi-byte integers, it's the callers
- * responsibility to perform appropriate byte order conversions.
- */
-static int
-csio_memory_rw(struct csio_hw *hw, int mtype, u32 addr, u32 len,
- uint32_t *buf, int dir)
-{
- uint32_t pos, start, end, offset, memoffset;
- int ret;
- uint32_t *data;
-
- /*
- * Argument sanity checks ...
- */
- if ((addr & 0x3) || (len & 0x3))
- return -EINVAL;
-
- data = kzalloc(MEMWIN0_APERTURE, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- /* Offset into the region of memory which is being accessed
- * MEM_EDC0 = 0
- * MEM_EDC1 = 1
- * MEM_MC = 2
- */
- memoffset = (mtype * (5 * 1024 * 1024));
-
- /* Determine the PCIE_MEM_ACCESS_OFFSET */
- addr = addr + memoffset;
-
- /*
- * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes
- * at a time so we need to round down the start and round up the end.
- * We'll start copying out of the first line at (addr - start) a word
- * at a time.
- */
- start = addr & ~(MEMWIN0_APERTURE-1);
- end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1);
- offset = (addr - start)/sizeof(__be32);
-
- for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
- /*
- * If we're writing, copy the data from the caller's memory
- * buffer
- */
- if (!dir) {
- /*
- * If we're doing a partial write, then we need to do
- * a read-modify-write ...
- */
- if (offset || len < MEMWIN0_APERTURE) {
- ret = csio_mem_win_rw(hw, pos, data, 1);
- if (ret) {
- kfree(data);
- return ret;
- }
- }
- while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
- len > 0) {
- data[offset++] = *buf++;
- len -= sizeof(__be32);
- }
- }
-
- /*
- * Transfer a block of memory and bail if there's an error.
- */
- ret = csio_mem_win_rw(hw, pos, data, dir);
- if (ret) {
- kfree(data);
- return ret;
- }
-
- /*
- * If we're reading, copy the data into the caller's memory
- * buffer.
- */
- if (dir)
- while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
- len > 0) {
- *buf++ = data[offset++];
- len -= sizeof(__be32);
- }
- }
-
- kfree(data);
-
- return 0;
-}
-
static int
csio_memory_write(struct csio_hw *hw, int mtype, u32 addr, u32 len, u32 *buf)
{
- return csio_memory_rw(hw, mtype, addr, len, buf, 0);
+ return hw->chip_ops->chip_memory_rw(hw, MEMWIN_CSIOSTOR, mtype,
+ addr, len, buf, 0);
}
/*
* EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
*/
-#define EEPROM_MAX_RD_POLL 40
-#define EEPROM_MAX_WR_POLL 6
-#define EEPROM_STAT_ADDR 0x7bfc
-#define VPD_BASE 0x400
-#define VPD_BASE_OLD 0
-#define VPD_LEN 512
+#define EEPROM_MAX_RD_POLL 40
+#define EEPROM_MAX_WR_POLL 6
+#define EEPROM_STAT_ADDR 0x7bfc
+#define VPD_BASE 0x400
+#define VPD_BASE_OLD 0
+#define VPD_LEN 1024
#define VPD_INFO_FLD_HDR_SIZE 3
/*
@@ -817,23 +646,6 @@ out:
return 0;
}
-/*
- * csio_hw_flash_cfg_addr - return the address of the flash
- * configuration file
- * @hw: the HW module
- *
- * Return the address within the flash where the Firmware Configuration
- * File is stored.
- */
-static unsigned int
-csio_hw_flash_cfg_addr(struct csio_hw *hw)
-{
- if (hw->params.sf_size == 0x100000)
- return FPGA_FLASH_CFG_OFFSET;
- else
- return FLASH_CFG_OFFSET;
-}
-
static void
csio_hw_print_fw_version(struct csio_hw *hw, char *str)
{
@@ -898,13 +710,13 @@ csio_hw_check_fw_version(struct csio_hw *hw)
minor = FW_HDR_FW_VER_MINOR_GET(hw->fwrev);
micro = FW_HDR_FW_VER_MICRO_GET(hw->fwrev);
- if (major != FW_VERSION_MAJOR) { /* major mismatch - fail */
+ if (major != FW_VERSION_MAJOR(hw)) { /* major mismatch - fail */
csio_err(hw, "card FW has major version %u, driver wants %u\n",
- major, FW_VERSION_MAJOR);
+ major, FW_VERSION_MAJOR(hw));
return -EINVAL;
}
- if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
+ if (minor == FW_VERSION_MINOR(hw) && micro == FW_VERSION_MICRO(hw))
return 0; /* perfect match */
/* Minor/micro version mismatch */
@@ -1044,7 +856,7 @@ static void
csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
{
uint16_t val;
- uint32_t pcie_cap;
+ int pcie_cap;
if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) {
pci_read_config_word(hw->pdev,
@@ -1056,84 +868,6 @@ csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
}
}
-
-/*
- * Return the specified PCI-E Configuration Space register from our Physical
- * Function. We try first via a Firmware LDST Command since we prefer to let
- * the firmware own all of these registers, but if that fails we go for it
- * directly ourselves.
- */
-static uint32_t
-csio_read_pcie_cfg4(struct csio_hw *hw, int reg)
-{
- u32 val = 0;
- struct csio_mb *mbp;
- int rv;
- struct fw_ldst_cmd *ldst_cmd;
-
- mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
- if (!mbp) {
- CSIO_INC_STATS(hw, n_err_nomem);
- pci_read_config_dword(hw->pdev, reg, &val);
- return val;
- }
-
- csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
-
- rv = csio_mb_issue(hw, mbp);
-
- /*
- * If the LDST Command suucceeded, exctract the returned register
- * value. Otherwise read it directly ourself.
- */
- if (rv == 0) {
- ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
- val = ntohl(ldst_cmd->u.pcie.data[0]);
- } else
- pci_read_config_dword(hw->pdev, reg, &val);
-
- mempool_free(mbp, hw->mb_mempool);
-
- return val;
-} /* csio_read_pcie_cfg4 */
-
-static int
-csio_hw_set_mem_win(struct csio_hw *hw)
-{
- u32 bar0;
-
- /*
- * Truncation intentional: we only read the bottom 32-bits of the
- * 64-bit BAR0/BAR1 ... We use the hardware backdoor mechanism to
- * read BAR0 instead of using pci_resource_start() because we could be
- * operating from within a Virtual Machine which is trapping our
- * accesses to our Configuration Space and we need to set up the PCI-E
- * Memory Window decoders with the actual addresses which will be
- * coming across the PCI-E link.
- */
- bar0 = csio_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
- bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
-
- /*
- * Set up memory window for accessing adapter memory ranges. (Read
- * back MA register to ensure that changes propagate before we attempt
- * to use the new values.)
- */
- csio_wr_reg32(hw, (bar0 + MEMWIN0_BASE) | BIR(0) |
- WINDOW(ilog2(MEMWIN0_APERTURE) - 10),
- PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0));
- csio_wr_reg32(hw, (bar0 + MEMWIN1_BASE) | BIR(0) |
- WINDOW(ilog2(MEMWIN1_APERTURE) - 10),
- PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1));
- csio_wr_reg32(hw, (bar0 + MEMWIN2_BASE) | BIR(0) |
- WINDOW(ilog2(MEMWIN2_APERTURE) - 10),
- PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
- csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
- return 0;
-} /* csio_hw_set_mem_win */
-
-
-
/*****************************************************************************/
/* HW State machine assists */
/*****************************************************************************/
@@ -1234,7 +968,9 @@ retry:
for (;;) {
uint32_t pcie_fw;
+ spin_unlock_irq(&hw->lock);
msleep(50);
+ spin_lock_irq(&hw->lock);
waiting -= 50;
/*
@@ -1861,87 +1597,6 @@ out:
return rv;
}
-static int
-csio_config_global_rss(struct csio_hw *hw)
-{
- struct csio_mb *mbp;
- enum fw_retval retval;
-
- mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
- if (!mbp) {
- CSIO_INC_STATS(hw, n_err_nomem);
- return -ENOMEM;
- }
-
- csio_rss_glb_config(hw, mbp, CSIO_MB_DEFAULT_TMO,
- FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
- FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
- FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ |
- FW_RSS_GLB_CONFIG_CMD_TNLALLLKP,
- NULL);
-
- if (csio_mb_issue(hw, mbp)) {
- csio_err(hw, "Issue of FW_RSS_GLB_CONFIG_CMD failed!\n");
- mempool_free(mbp, hw->mb_mempool);
- return -EINVAL;
- }
-
- retval = csio_mb_fw_retval(mbp);
- if (retval != FW_SUCCESS) {
- csio_err(hw, "FW_RSS_GLB_CONFIG_CMD returned 0x%x!\n", retval);
- mempool_free(mbp, hw->mb_mempool);
- return -EINVAL;
- }
-
- mempool_free(mbp, hw->mb_mempool);
-
- return 0;
-}
-
-/*
- * csio_config_pfvf - Configure Physical/Virtual functions settings.
- * @hw: HW module
- *
- */
-static int
-csio_config_pfvf(struct csio_hw *hw)
-{
- struct csio_mb *mbp;
- enum fw_retval retval;
-
- mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
- if (!mbp) {
- CSIO_INC_STATS(hw, n_err_nomem);
- return -ENOMEM;
- }
-
- /*
- * For now, allow all PFs to access to all ports using a pmask
- * value of 0xF (M_FW_PFVF_CMD_PMASK). Once we have VFs, we will
- * need to provide access based on some rule.
- */
- csio_mb_pfvf(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0, CSIO_NEQ,
- CSIO_NETH_CTRL, CSIO_NIQ_FLINT, 0, 0, CSIO_NVI, CSIO_CMASK,
- CSIO_PMASK, CSIO_NEXACTF, CSIO_R_CAPS, CSIO_WX_CAPS, NULL);
-
- if (csio_mb_issue(hw, mbp)) {
- csio_err(hw, "Issue of FW_PFVF_CMD failed!\n");
- mempool_free(mbp, hw->mb_mempool);
- return -EINVAL;
- }
-
- retval = csio_mb_fw_retval(mbp);
- if (retval != FW_SUCCESS) {
- csio_err(hw, "FW_PFVF_CMD returned 0x%x!\n", retval);
- mempool_free(mbp, hw->mb_mempool);
- return -EINVAL;
- }
-
- mempool_free(mbp, hw->mb_mempool);
-
- return 0;
-}
-
/*
* csio_enable_ports - Bring up all available ports.
* @hw: HW module.
@@ -2121,9 +1776,9 @@ csio_hw_flash_config(struct csio_hw *hw, u32 *fw_cfg_param, char *path)
uint32_t *cfg_data;
int value_to_add = 0;
- if (request_firmware(&cf, CSIO_CF_FNAME, dev) < 0) {
- csio_err(hw, "could not find config file " CSIO_CF_FNAME
- ",err: %d\n", ret);
+ if (request_firmware(&cf, CSIO_CF_FNAME(hw), dev) < 0) {
+ csio_err(hw, "could not find config file %s, err: %d\n",
+ CSIO_CF_FNAME(hw), ret);
return -ENOENT;
}
@@ -2131,27 +1786,45 @@ csio_hw_flash_config(struct csio_hw *hw, u32 *fw_cfg_param, char *path)
value_to_add = 4 - (cf->size % 4);
cfg_data = kzalloc(cf->size+value_to_add, GFP_KERNEL);
- if (cfg_data == NULL)
- return -ENOMEM;
+ if (cfg_data == NULL) {
+ ret = -ENOMEM;
+ goto leave;
+ }
memcpy((void *)cfg_data, (const void *)cf->data, cf->size);
-
- if (csio_hw_check_fwconfig(hw, fw_cfg_param) != 0)
- return -EINVAL;
+ if (csio_hw_check_fwconfig(hw, fw_cfg_param) != 0) {
+ ret = -EINVAL;
+ goto leave;
+ }
mtype = FW_PARAMS_PARAM_Y_GET(*fw_cfg_param);
maddr = FW_PARAMS_PARAM_Z_GET(*fw_cfg_param) << 16;
ret = csio_memory_write(hw, mtype, maddr,
cf->size + value_to_add, cfg_data);
+
+ if ((ret == 0) && (value_to_add != 0)) {
+ union {
+ u32 word;
+ char buf[4];
+ } last;
+ size_t size = cf->size & ~0x3;
+ int i;
+
+ last.word = cfg_data[size >> 2];
+ for (i = value_to_add; i < 4; i++)
+ last.buf[i] = 0;
+ ret = csio_memory_write(hw, mtype, maddr + size, 4, &last.word);
+ }
if (ret == 0) {
- csio_info(hw, "config file upgraded to " CSIO_CF_FNAME "\n");
- strncpy(path, "/lib/firmware/" CSIO_CF_FNAME, 64);
+ csio_info(hw, "config file upgraded to %s\n",
+ CSIO_CF_FNAME(hw));
+ snprintf(path, 64, "%s%s", "/lib/firmware/", CSIO_CF_FNAME(hw));
}
+leave:
kfree(cfg_data);
release_firmware(cf);
-
return ret;
}
@@ -2176,7 +1849,7 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
{
unsigned int mtype, maddr;
int rv;
- uint32_t finiver, finicsum, cfcsum;
+ uint32_t finiver = 0, finicsum = 0, cfcsum = 0;
int using_flash;
char path[64];
@@ -2204,7 +1877,7 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
* config file from flash.
*/
mtype = FW_MEMTYPE_CF_FLASH;
- maddr = csio_hw_flash_cfg_addr(hw);
+ maddr = hw->chip_ops->chip_flash_cfg_addr(hw);
using_flash = 1;
} else {
/*
@@ -2302,16 +1975,6 @@ csio_hw_no_fwconfig(struct csio_hw *hw, int reset)
if (rv != 0)
goto out;
- /* Config Global RSS command */
- rv = csio_config_global_rss(hw);
- if (rv != 0)
- goto out;
-
- /* Configure PF/VF capabilities of device */
- rv = csio_config_pfvf(hw);
- if (rv != 0)
- goto out;
-
/* device parameters */
rv = csio_get_device_params(hw);
if (rv != 0)
@@ -2343,30 +2006,32 @@ csio_hw_flash_fw(struct csio_hw *hw)
struct pci_dev *pci_dev = hw->pdev;
struct device *dev = &pci_dev->dev ;
- if (request_firmware(&fw, CSIO_FW_FNAME, dev) < 0) {
- csio_err(hw, "could not find firmware image " CSIO_FW_FNAME
- ",err: %d\n", ret);
+ if (request_firmware(&fw, CSIO_FW_FNAME(hw), dev) < 0) {
+ csio_err(hw, "could not find firmware image %s, err: %d\n",
+ CSIO_FW_FNAME(hw), ret);
return -EINVAL;
}
hdr = (const struct fw_hdr *)fw->data;
fw_ver = ntohl(hdr->fw_ver);
- if (FW_HDR_FW_VER_MAJOR_GET(fw_ver) != FW_VERSION_MAJOR)
+ if (FW_HDR_FW_VER_MAJOR_GET(fw_ver) != FW_VERSION_MAJOR(hw))
return -EINVAL; /* wrong major version, won't do */
/*
* If the flash FW is unusable or we found something newer, load it.
*/
- if (FW_HDR_FW_VER_MAJOR_GET(hw->fwrev) != FW_VERSION_MAJOR ||
+ if (FW_HDR_FW_VER_MAJOR_GET(hw->fwrev) != FW_VERSION_MAJOR(hw) ||
fw_ver > hw->fwrev) {
ret = csio_hw_fw_upgrade(hw, hw->pfn, fw->data, fw->size,
/*force=*/false);
if (!ret)
- csio_info(hw, "firmware upgraded to version %pI4 from "
- CSIO_FW_FNAME "\n", &hdr->fw_ver);
+ csio_info(hw,
+ "firmware upgraded to version %pI4 from %s\n",
+ &hdr->fw_ver, CSIO_FW_FNAME(hw));
else
csio_err(hw, "firmware upgrade failed! err=%d\n", ret);
- }
+ } else
+ ret = -EINVAL;
release_firmware(fw);
@@ -2407,7 +2072,7 @@ csio_hw_configure(struct csio_hw *hw)
/* Set pci completion timeout value to 4 seconds. */
csio_set_pcie_completion_timeout(hw, 0xd);
- csio_hw_set_mem_win(hw);
+ hw->chip_ops->chip_set_mem_win(hw, MEMWIN_CSIOSTOR);
rv = csio_hw_get_fw_version(hw, &hw->fwrev);
if (rv != 0)
@@ -2475,6 +2140,8 @@ csio_hw_configure(struct csio_hw *hw)
} else {
if (hw->fw_state == CSIO_DEV_STATE_INIT) {
+ hw->flags |= CSIO_HWF_USING_SOFT_PARAMS;
+
/* device parameters */
rv = csio_get_device_params(hw);
if (rv != 0)
@@ -2648,7 +2315,7 @@ csio_hw_intr_disable(struct csio_hw *hw)
}
-static void
+void
csio_hw_fatal_err(struct csio_hw *hw)
{
csio_set_reg_field(hw, SGE_CONTROL, GLOBALENABLE, 0);
@@ -2987,14 +2654,6 @@ csio_hws_pcierr(struct csio_hw *hw, enum csio_hw_ev evt)
/* END: HW SM */
/*****************************************************************************/
-/* Slow path handlers */
-struct intr_info {
- unsigned int mask; /* bits to check in interrupt status */
- const char *msg; /* message to print or NULL */
- short stat_idx; /* stat counter to increment or -1 */
- unsigned short fatal; /* whether the condition reported is fatal */
-};
-
/*
* csio_handle_intr_status - table driven interrupt handler
* @hw: HW instance
@@ -3008,7 +2667,7 @@ struct intr_info {
* by an entry specifying mask 0. Returns the number of fatal interrupt
* conditions.
*/
-static int
+int
csio_handle_intr_status(struct csio_hw *hw, unsigned int reg,
const struct intr_info *acts)
{
@@ -3035,80 +2694,6 @@ csio_handle_intr_status(struct csio_hw *hw, unsigned int reg,
}
/*
- * Interrupt handler for the PCIE module.
- */
-static void
-csio_pcie_intr_handler(struct csio_hw *hw)
-{
- static struct intr_info sysbus_intr_info[] = {
- { RNPP, "RXNP array parity error", -1, 1 },
- { RPCP, "RXPC array parity error", -1, 1 },
- { RCIP, "RXCIF array parity error", -1, 1 },
- { RCCP, "Rx completions control array parity error", -1, 1 },
- { RFTP, "RXFT array parity error", -1, 1 },
- { 0, NULL, 0, 0 }
- };
- static struct intr_info pcie_port_intr_info[] = {
- { TPCP, "TXPC array parity error", -1, 1 },
- { TNPP, "TXNP array parity error", -1, 1 },
- { TFTP, "TXFT array parity error", -1, 1 },
- { TCAP, "TXCA array parity error", -1, 1 },
- { TCIP, "TXCIF array parity error", -1, 1 },
- { RCAP, "RXCA array parity error", -1, 1 },
- { OTDD, "outbound request TLP discarded", -1, 1 },
- { RDPE, "Rx data parity error", -1, 1 },
- { TDUE, "Tx uncorrectable data error", -1, 1 },
- { 0, NULL, 0, 0 }
- };
- static struct intr_info pcie_intr_info[] = {
- { MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
- { MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
- { MSIDATAPERR, "MSI data parity error", -1, 1 },
- { MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
- { MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
- { MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
- { MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
- { PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
- { PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
- { TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
- { CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
- { CREQPERR, "PCI CMD channel request parity error", -1, 1 },
- { CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
- { DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
- { DREQPERR, "PCI DMA channel request parity error", -1, 1 },
- { DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
- { HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
- { HREQPERR, "PCI HMA channel request parity error", -1, 1 },
- { HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
- { CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
- { FIDPERR, "PCI FID parity error", -1, 1 },
- { INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
- { MATAGPERR, "PCI MA tag parity error", -1, 1 },
- { PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
- { RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
- { RXWRPERR, "PCI Rx write parity error", -1, 1 },
- { RPLPERR, "PCI replay buffer parity error", -1, 1 },
- { PCIESINT, "PCI core secondary fault", -1, 1 },
- { PCIEPINT, "PCI core primary fault", -1, 1 },
- { UNXSPLCPLERR, "PCI unexpected split completion error", -1,
- 0 },
- { 0, NULL, 0, 0 }
- };
-
- int fat;
-
- fat = csio_handle_intr_status(hw,
- PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
- sysbus_intr_info) +
- csio_handle_intr_status(hw,
- PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
- pcie_port_intr_info) +
- csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
- if (fat)
- csio_hw_fatal_err(hw);
-}
-
-/*
* TP interrupt handler.
*/
static void csio_tp_intr_handler(struct csio_hw *hw)
@@ -3514,7 +3099,7 @@ static void csio_ncsi_intr_handler(struct csio_hw *hw)
*/
static void csio_xgmac_intr_handler(struct csio_hw *hw, int port)
{
- uint32_t v = csio_rd_reg32(hw, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+ uint32_t v = csio_rd_reg32(hw, CSIO_MAC_INT_CAUSE_REG(hw, port));
v &= TXFIFO_PRTY_ERR | RXFIFO_PRTY_ERR;
if (!v)
@@ -3524,7 +3109,7 @@ static void csio_xgmac_intr_handler(struct csio_hw *hw, int port)
csio_fatal(hw, "XGMAC %d Tx FIFO parity error\n", port);
if (v & RXFIFO_PRTY_ERR)
csio_fatal(hw, "XGMAC %d Rx FIFO parity error\n", port);
- csio_wr_reg32(hw, v, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+ csio_wr_reg32(hw, v, CSIO_MAC_INT_CAUSE_REG(hw, port));
csio_hw_fatal_err(hw);
}
@@ -3593,7 +3178,7 @@ csio_hw_slow_intr_handler(struct csio_hw *hw)
csio_xgmac_intr_handler(hw, 3);
if (cause & PCIE)
- csio_pcie_intr_handler(hw);
+ hw->chip_ops->chip_pcie_intr_handler(hw);
if (cause & MC)
csio_mem_intr_handler(hw, MEM_MC);
@@ -3889,7 +3474,6 @@ csio_process_fwevtq_entry(struct csio_hw *hw, void *wr, uint32_t len,
struct csio_fl_dma_buf *flb, void *priv)
{
__u8 op;
- __be64 *data;
void *msg = NULL;
uint32_t msg_len = 0;
bool msg_sg = 0;
@@ -3905,8 +3489,6 @@ csio_process_fwevtq_entry(struct csio_hw *hw, void *wr, uint32_t len,
msg = (void *) flb;
msg_len = flb->totlen;
msg_sg = 1;
-
- data = (__be64 *) msg;
} else if (op == CPL_FW6_MSG || op == CPL_FW4_MSG) {
CSIO_INC_STATS(hw, n_cpl_fw6_msg);
@@ -3914,8 +3496,6 @@ csio_process_fwevtq_entry(struct csio_hw *hw, void *wr, uint32_t len,
msg = (void *)((uintptr_t)wr + sizeof(__be64));
msg_len = (op == CPL_FW6_MSG) ? sizeof(struct cpl_fw6_msg) :
sizeof(struct cpl_fw4_msg);
-
- data = (__be64 *) msg;
} else {
csio_warn(hw, "unexpected CPL %#x on FW event queue\n", op);
CSIO_INC_STATS(hw, n_cpl_unexp);
@@ -4259,6 +3839,7 @@ csio_hw_get_device_id(struct csio_hw *hw)
&hw->params.pci.device_id);
csio_dev_id_cached(hw);
+ hw->chip_id = (hw->params.pci.device_id & CSIO_HW_CHIP_MASK);
} /* csio_hw_get_device_id */
@@ -4277,19 +3858,21 @@ csio_hw_set_description(struct csio_hw *hw, uint16_t ven_id, uint16_t dev_id)
prot_type = (dev_id & CSIO_ASIC_DEVID_PROTO_MASK);
adap_type = (dev_id & CSIO_ASIC_DEVID_TYPE_MASK);
- if (prot_type == CSIO_FPGA) {
+ if (prot_type == CSIO_T4_FCOE_ASIC) {
+ memcpy(hw->hw_ver,
+ csio_t4_fcoe_adapters[adap_type].model_no, 16);
memcpy(hw->model_desc,
- csio_fcoe_adapters[13].description, 32);
- } else if (prot_type == CSIO_T4_FCOE_ASIC) {
+ csio_t4_fcoe_adapters[adap_type].description,
+ 32);
+ } else if (prot_type == CSIO_T5_FCOE_ASIC) {
memcpy(hw->hw_ver,
- csio_fcoe_adapters[adap_type].model_no, 16);
+ csio_t5_fcoe_adapters[adap_type].model_no, 16);
memcpy(hw->model_desc,
- csio_fcoe_adapters[adap_type].description, 32);
+ csio_t5_fcoe_adapters[adap_type].description,
+ 32);
} else {
char tempName[32] = "Chelsio FCoE Controller";
memcpy(hw->model_desc, tempName, 32);
-
- CSIO_DB_ASSERT(0);
}
}
} /* csio_hw_set_description */
@@ -4318,6 +3901,9 @@ csio_hw_init(struct csio_hw *hw)
strcpy(hw->name, CSIO_HW_NAME);
+ /* Initialize the HW chip ops with T4/T5 specific ops */
+ hw->chip_ops = csio_is_t4(hw->chip_id) ? &t4_ops : &t5_ops;
+
/* Set the model & its description */
ven_id = hw->params.pci.vendor_id;
diff --git a/drivers/scsi/csiostor/csio_hw.h b/drivers/scsi/csiostor/csio_hw.h
index 9edcca4..49b1daa 100644
--- a/drivers/scsi/csiostor/csio_hw.h
+++ b/drivers/scsi/csiostor/csio_hw.h
@@ -48,6 +48,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport_fc.h>
+#include "csio_hw_chip.h"
#include "csio_wr.h"
#include "csio_mb.h"
#include "csio_scsi.h"
@@ -60,13 +61,6 @@
*/
#define FW_HOSTERROR 255
-#define CSIO_FW_FNAME "cxgb4/t4fw.bin"
-#define CSIO_CF_FNAME "cxgb4/t4-config.txt"
-
-#define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 2
-#define FW_VERSION_MICRO 8
-
#define CSIO_HW_NAME "Chelsio FCoE Adapter"
#define CSIO_MAX_PFN 8
#define CSIO_MAX_PPORTS 4
@@ -123,8 +117,6 @@ extern int csio_msi;
#define CSIO_VENDOR_ID 0x1425
#define CSIO_ASIC_DEVID_PROTO_MASK 0xFF00
#define CSIO_ASIC_DEVID_TYPE_MASK 0x00FF
-#define CSIO_FPGA 0xA000
-#define CSIO_T4_FCOE_ASIC 0x4600
#define CSIO_GLBL_INTR_MASK (CIM | MPS | PL | PCIE | MC | EDC0 | \
EDC1 | LE | TP | MA | PM_TX | PM_RX | \
@@ -161,17 +153,6 @@ enum {
CSIO_SGE_INT_CNT_VAL_1 = 4,
CSIO_SGE_INT_CNT_VAL_2 = 8,
CSIO_SGE_INT_CNT_VAL_3 = 16,
-
- /* Storage specific - used by FW_PFVF_CMD */
- CSIO_WX_CAPS = FW_CMD_CAP_PF, /* w/x all */
- CSIO_R_CAPS = FW_CMD_CAP_PF, /* r all */
- CSIO_NVI = 4,
- CSIO_NIQ_FLINT = 34,
- CSIO_NETH_CTRL = 32,
- CSIO_NEQ = 66,
- CSIO_NEXACTF = 32,
- CSIO_CMASK = FW_PFVF_CMD_CMASK_MASK,
- CSIO_PMASK = FW_PFVF_CMD_PMASK_MASK,
};
/* Slowpath events */
@@ -207,17 +188,6 @@ enum {
SF_SIZE = SF_SEC_SIZE * 16, /* serial flash size */
};
-enum { MEM_EDC0, MEM_EDC1, MEM_MC };
-
-enum {
- MEMWIN0_APERTURE = 2048,
- MEMWIN0_BASE = 0x1b800,
- MEMWIN1_APERTURE = 32768,
- MEMWIN1_BASE = 0x28000,
- MEMWIN2_APERTURE = 65536,
- MEMWIN2_BASE = 0x30000,
-};
-
/* serial flash and firmware constants */
enum {
SF_ATTEMPTS = 10, /* max retries for SF operations */
@@ -239,9 +209,6 @@ enum {
FLASH_CFG_MAX_SIZE = 0x10000 , /* max size of the flash config file*/
FLASH_CFG_OFFSET = 0x1f0000,
FLASH_CFG_START_SEC = FLASH_CFG_OFFSET / SF_SEC_SIZE,
- FPGA_FLASH_CFG_OFFSET = 0xf0000 , /* if FPGA mode, then cfg file is
- * at 1MB - 64KB */
- FPGA_FLASH_CFG_START_SEC = FPGA_FLASH_CFG_OFFSET / SF_SEC_SIZE,
};
/*
@@ -259,6 +226,8 @@ enum {
FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
+ /* Location of Firmware Configuration File in FLASH. */
+ FLASH_CFG_START = FLASH_START(FLASH_CFG_START_SEC),
};
#undef FLASH_START
@@ -310,7 +279,7 @@ struct csio_adap_desc {
struct pci_params {
uint16_t vendor_id;
uint16_t device_id;
- uint32_t vpd_cap_addr;
+ int vpd_cap_addr;
uint16_t speed;
uint8_t width;
};
@@ -513,6 +482,7 @@ struct csio_hw {
uint32_t fwrev;
uint32_t tp_vers;
char chip_ver;
+ uint16_t chip_id; /* Tells T4/T5 chip */
uint32_t cfg_finiver;
uint32_t cfg_finicsum;
uint32_t cfg_cfcsum;
@@ -556,6 +526,9 @@ struct csio_hw {
*/
struct csio_fcoe_res_info fres_info; /* Fcoe resource info */
+ struct csio_hw_chip_ops *chip_ops; /* T4/T5 Chip specific
+ * Operations
+ */
/* MSIX vectors */
struct csio_msix_entries msix_entries[CSIO_MAX_MSIX_VECS];
@@ -636,9 +609,16 @@ csio_us_to_core_ticks(struct csio_hw *hw, uint32_t us)
#define csio_dbg(__hw, __fmt, ...)
#endif
+int csio_hw_wait_op_done_val(struct csio_hw *, int, uint32_t, int,
+ int, int, uint32_t *);
+void csio_hw_tp_wr_bits_indirect(struct csio_hw *, unsigned int,
+ unsigned int, unsigned int);
int csio_mgmt_req_lookup(struct csio_mgmtm *, struct csio_ioreq *);
void csio_hw_intr_disable(struct csio_hw *);
-int csio_hw_slow_intr_handler(struct csio_hw *hw);
+int csio_hw_slow_intr_handler(struct csio_hw *);
+int csio_handle_intr_status(struct csio_hw *, unsigned int,
+ const struct intr_info *);
+
int csio_hw_start(struct csio_hw *);
int csio_hw_stop(struct csio_hw *);
int csio_hw_reset(struct csio_hw *);
@@ -647,19 +627,17 @@ int csio_is_hw_removing(struct csio_hw *);
int csio_fwevtq_handler(struct csio_hw *);
void csio_evtq_worker(struct work_struct *);
-int csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type,
- void *evt_msg, uint16_t len);
+int csio_enqueue_evt(struct csio_hw *, enum csio_evt, void *, uint16_t);
void csio_evtq_flush(struct csio_hw *hw);
int csio_request_irqs(struct csio_hw *);
void csio_intr_enable(struct csio_hw *);
void csio_intr_disable(struct csio_hw *, bool);
+void csio_hw_fatal_err(struct csio_hw *);
struct csio_lnode *csio_lnode_alloc(struct csio_hw *);
int csio_config_queues(struct csio_hw *);
-int csio_hw_mc_read(struct csio_hw *, uint32_t, __be32 *, uint64_t *);
-int csio_hw_edc_read(struct csio_hw *, int, uint32_t, __be32 *, uint64_t *);
int csio_hw_init(struct csio_hw *);
void csio_hw_exit(struct csio_hw *);
#endif /* ifndef __CSIO_HW_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw_chip.h b/drivers/scsi/csiostor/csio_hw_chip.h
new file mode 100644
index 0000000..bca0de6
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw_chip.h
@@ -0,0 +1,175 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_HW_CHIP_H__
+#define __CSIO_HW_CHIP_H__
+
+#include "csio_defs.h"
+
+/* FCoE device IDs for T4 */
+#define CSIO_DEVID_T440DBG_FCOE 0x4600
+#define CSIO_DEVID_T420CR_FCOE 0x4601
+#define CSIO_DEVID_T422CR_FCOE 0x4602
+#define CSIO_DEVID_T440CR_FCOE 0x4603
+#define CSIO_DEVID_T420BCH_FCOE 0x4604
+#define CSIO_DEVID_T440BCH_FCOE 0x4605
+#define CSIO_DEVID_T440CH_FCOE 0x4606
+#define CSIO_DEVID_T420SO_FCOE 0x4607
+#define CSIO_DEVID_T420CX_FCOE 0x4608
+#define CSIO_DEVID_T420BT_FCOE 0x4609
+#define CSIO_DEVID_T404BT_FCOE 0x460A
+#define CSIO_DEVID_B420_FCOE 0x460B
+#define CSIO_DEVID_B404_FCOE 0x460C
+#define CSIO_DEVID_T480CR_FCOE 0x460D
+#define CSIO_DEVID_T440LPCR_FCOE 0x460E
+#define CSIO_DEVID_AMSTERDAM_T4_FCOE 0x460F
+#define CSIO_DEVID_HUAWEI_T480_FCOE 0x4680
+#define CSIO_DEVID_HUAWEI_T440_FCOE 0x4681
+#define CSIO_DEVID_HUAWEI_STG310_FCOE 0x4682
+#define CSIO_DEVID_ACROMAG_XMC_XAUI 0x4683
+#define CSIO_DEVID_ACROMAG_XMC_SFP_FCOE 0x4684
+#define CSIO_DEVID_QUANTA_MEZZ_SFP_FCOE 0x4685
+#define CSIO_DEVID_HUAWEI_10GT_FCOE 0x4686
+#define CSIO_DEVID_HUAWEI_T440_TOE_FCOE 0x4687
+
+/* FCoE device IDs for T5 */
+#define CSIO_DEVID_T580DBG_FCOE 0x5600
+#define CSIO_DEVID_T520CR_FCOE 0x5601
+#define CSIO_DEVID_T522CR_FCOE 0x5602
+#define CSIO_DEVID_T540CR_FCOE 0x5603
+#define CSIO_DEVID_T520BCH_FCOE 0x5604
+#define CSIO_DEVID_T540BCH_FCOE 0x5605
+#define CSIO_DEVID_T540CH_FCOE 0x5606
+#define CSIO_DEVID_T520SO_FCOE 0x5607
+#define CSIO_DEVID_T520CX_FCOE 0x5608
+#define CSIO_DEVID_T520BT_FCOE 0x5609
+#define CSIO_DEVID_T504BT_FCOE 0x560A
+#define CSIO_DEVID_B520_FCOE 0x560B
+#define CSIO_DEVID_B504_FCOE 0x560C
+#define CSIO_DEVID_T580CR2_FCOE 0x560D
+#define CSIO_DEVID_T540LPCR_FCOE 0x560E
+#define CSIO_DEVID_AMSTERDAM_T5_FCOE 0x560F
+#define CSIO_DEVID_T580LPCR_FCOE 0x5610
+#define CSIO_DEVID_T520LLCR_FCOE 0x5611
+#define CSIO_DEVID_T560CR_FCOE 0x5612
+#define CSIO_DEVID_T580CR_FCOE 0x5613
+
+/* Define MACRO values */
+#define CSIO_HW_T4 0x4000
+#define CSIO_T4_FCOE_ASIC 0x4600
+#define CSIO_HW_T5 0x5000
+#define CSIO_T5_FCOE_ASIC 0x5600
+#define CSIO_HW_CHIP_MASK 0xF000
+#define T4_REGMAP_SIZE (160 * 1024)
+#define T5_REGMAP_SIZE (332 * 1024)
+#define FW_FNAME_T4 "cxgb4/t4fw.bin"
+#define FW_FNAME_T5 "cxgb4/t5fw.bin"
+#define FW_CFG_NAME_T4 "cxgb4/t4-config.txt"
+#define FW_CFG_NAME_T5 "cxgb4/t5-config.txt"
+
+/* Define static functions */
+static inline int csio_is_t4(uint16_t chip)
+{
+ return (chip == CSIO_HW_T4);
+}
+
+static inline int csio_is_t5(uint16_t chip)
+{
+ return (chip == CSIO_HW_T5);
+}
+
+/* Define MACRO DEFINITIONS */
+#define CSIO_DEVICE(devid, idx) \
+ { PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
+
+#define CSIO_HW_PIDX(hw, index) \
+ (csio_is_t4(hw->chip_id) ? (PIDX(index)) : \
+ (PIDX_T5(index) | DBTYPE(1U)))
+
+#define CSIO_HW_LP_INT_THRESH(hw, val) \
+ (csio_is_t4(hw->chip_id) ? (LP_INT_THRESH(val)) : \
+ (V_LP_INT_THRESH_T5(val)))
+
+#define CSIO_HW_M_LP_INT_THRESH(hw) \
+ (csio_is_t4(hw->chip_id) ? (LP_INT_THRESH_MASK) : (M_LP_INT_THRESH_T5))
+
+#define CSIO_MAC_INT_CAUSE_REG(hw, port) \
+ (csio_is_t4(hw->chip_id) ? (PORT_REG(port, XGMAC_PORT_INT_CAUSE)) : \
+ (T5_PORT_REG(port, MAC_PORT_INT_CAUSE)))
+
+#define FW_VERSION_MAJOR(hw) (csio_is_t4(hw->chip_id) ? 1 : 0)
+#define FW_VERSION_MINOR(hw) (csio_is_t4(hw->chip_id) ? 2 : 0)
+#define FW_VERSION_MICRO(hw) (csio_is_t4(hw->chip_id) ? 8 : 0)
+
+#define CSIO_FW_FNAME(hw) \
+ (csio_is_t4(hw->chip_id) ? FW_FNAME_T4 : FW_FNAME_T5)
+
+#define CSIO_CF_FNAME(hw) \
+ (csio_is_t4(hw->chip_id) ? FW_CFG_NAME_T4 : FW_CFG_NAME_T5)
+
+/* Declare ENUMS */
+enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };
+
+enum {
+ MEMWIN_APERTURE = 2048,
+ MEMWIN_BASE = 0x1b800,
+ MEMWIN_CSIOSTOR = 6, /* PCI-e Memory Window access */
+};
+
+/* Slow path handlers */
+struct intr_info {
+ unsigned int mask; /* bits to check in interrupt status */
+ const char *msg; /* message to print or NULL */
+ short stat_idx; /* stat counter to increment or -1 */
+ unsigned short fatal; /* whether the condition reported is fatal */
+};
+
+/* T4/T5 Chip specific ops */
+struct csio_hw;
+struct csio_hw_chip_ops {
+ int (*chip_set_mem_win)(struct csio_hw *, uint32_t);
+ void (*chip_pcie_intr_handler)(struct csio_hw *);
+ uint32_t (*chip_flash_cfg_addr)(struct csio_hw *);
+ int (*chip_mc_read)(struct csio_hw *, int, uint32_t,
+ __be32 *, uint64_t *);
+ int (*chip_edc_read)(struct csio_hw *, int, uint32_t,
+ __be32 *, uint64_t *);
+ int (*chip_memory_rw)(struct csio_hw *, u32, int, u32,
+ u32, uint32_t *, int);
+ void (*chip_dfs_create_ext_mem)(struct csio_hw *);
+};
+
+extern struct csio_hw_chip_ops t4_ops;
+extern struct csio_hw_chip_ops t5_ops;
+
+#endif /* #ifndef __CSIO_HW_CHIP_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw_t4.c b/drivers/scsi/csiostor/csio_hw_t4.c
new file mode 100644
index 0000000..89ecbac
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw_t4.c
@@ -0,0 +1,403 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "csio_hw.h"
+#include "csio_init.h"
+
+/*
+ * Return the specified PCI-E Configuration Space register from our Physical
+ * Function. We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static uint32_t
+csio_t4_read_pcie_cfg4(struct csio_hw *hw, int reg)
+{
+ u32 val = 0;
+ struct csio_mb *mbp;
+ int rv;
+ struct fw_ldst_cmd *ldst_cmd;
+
+ mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+ if (!mbp) {
+ CSIO_INC_STATS(hw, n_err_nomem);
+ pci_read_config_dword(hw->pdev, reg, &val);
+ return val;
+ }
+
+ csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
+ rv = csio_mb_issue(hw, mbp);
+
+ /*
+ * If the LDST Command suucceeded, exctract the returned register
+ * value. Otherwise read it directly ourself.
+ */
+ if (rv == 0) {
+ ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
+ val = ntohl(ldst_cmd->u.pcie.data[0]);
+ } else
+ pci_read_config_dword(hw->pdev, reg, &val);
+
+ mempool_free(mbp, hw->mb_mempool);
+
+ return val;
+}
+
+static int
+csio_t4_set_mem_win(struct csio_hw *hw, uint32_t win)
+{
+ u32 bar0;
+ u32 mem_win_base;
+
+ /*
+ * Truncation intentional: we only read the bottom 32-bits of the
+ * 64-bit BAR0/BAR1 ... We use the hardware backdoor mechanism to
+ * read BAR0 instead of using pci_resource_start() because we could be
+ * operating from within a Virtual Machine which is trapping our
+ * accesses to our Configuration Space and we need to set up the PCI-E
+ * Memory Window decoders with the actual addresses which will be
+ * coming across the PCI-E link.
+ */
+ bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
+ bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ mem_win_base = bar0 + MEMWIN_BASE;
+
+ /*
+ * Set up memory window for accessing adapter memory ranges. (Read
+ * back MA register to ensure that changes propagate before we attempt
+ * to use the new values.)
+ */
+ csio_wr_reg32(hw, mem_win_base | BIR(0) |
+ WINDOW(ilog2(MEMWIN_APERTURE) - 10),
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+ csio_rd_reg32(hw,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+ return 0;
+}
+
+/*
+ * Interrupt handler for the PCIE module.
+ */
+static void
+csio_t4_pcie_intr_handler(struct csio_hw *hw)
+{
+ static struct intr_info sysbus_intr_info[] = {
+ { RNPP, "RXNP array parity error", -1, 1 },
+ { RPCP, "RXPC array parity error", -1, 1 },
+ { RCIP, "RXCIF array parity error", -1, 1 },
+ { RCCP, "Rx completions control array parity error", -1, 1 },
+ { RFTP, "RXFT array parity error", -1, 1 },
+ { 0, NULL, 0, 0 }
+ };
+ static struct intr_info pcie_port_intr_info[] = {
+ { TPCP, "TXPC array parity error", -1, 1 },
+ { TNPP, "TXNP array parity error", -1, 1 },
+ { TFTP, "TXFT array parity error", -1, 1 },
+ { TCAP, "TXCA array parity error", -1, 1 },
+ { TCIP, "TXCIF array parity error", -1, 1 },
+ { RCAP, "RXCA array parity error", -1, 1 },
+ { OTDD, "outbound request TLP discarded", -1, 1 },
+ { RDPE, "Rx data parity error", -1, 1 },
+ { TDUE, "Tx uncorrectable data error", -1, 1 },
+ { 0, NULL, 0, 0 }
+ };
+
+ static struct intr_info pcie_intr_info[] = {
+ { MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
+ { MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
+ { MSIDATAPERR, "MSI data parity error", -1, 1 },
+ { MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+ { MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+ { MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+ { MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+ { PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
+ { PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
+ { TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+ { CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
+ { CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+ { CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+ { DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
+ { DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+ { DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+ { HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
+ { HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+ { HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+ { CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+ { FIDPERR, "PCI FID parity error", -1, 1 },
+ { INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
+ { MATAGPERR, "PCI MA tag parity error", -1, 1 },
+ { PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+ { RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
+ { RXWRPERR, "PCI Rx write parity error", -1, 1 },
+ { RPLPERR, "PCI replay buffer parity error", -1, 1 },
+ { PCIESINT, "PCI core secondary fault", -1, 1 },
+ { PCIEPINT, "PCI core primary fault", -1, 1 },
+ { UNXSPLCPLERR, "PCI unexpected split completion error", -1,
+ 0 },
+ { 0, NULL, 0, 0 }
+ };
+
+ int fat;
+ fat = csio_handle_intr_status(hw,
+ PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+ sysbus_intr_info) +
+ csio_handle_intr_status(hw,
+ PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+ pcie_port_intr_info) +
+ csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
+ if (fat)
+ csio_hw_fatal_err(hw);
+}
+
+/*
+ * csio_t4_flash_cfg_addr - return the address of the flash configuration file
+ * @hw: the HW module
+ *
+ * Return the address within the flash where the Firmware Configuration
+ * File is stored.
+ */
+static unsigned int
+csio_t4_flash_cfg_addr(struct csio_hw *hw)
+{
+ return FLASH_CFG_OFFSET;
+}
+
+/*
+ * csio_t4_mc_read - read from MC through backdoor accesses
+ * @hw: the hw module
+ * @idx: not used for T4 adapter
+ * @addr: address of first byte requested
+ * @data: 64 bytes of data containing the requested address
+ * @ecc: where to store the corresponding 64-bit ECC word
+ *
+ * Read 64 bytes of data from MC starting at a 64-byte-aligned address
+ * that covers the requested address @addr. If @parity is not %NULL it
+ * is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t4_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+ uint64_t *ecc)
+{
+ int i;
+
+ if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
+ return -EBUSY;
+ csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
+ csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
+ csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
+ csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST | BIST_CMD_GAP(1),
+ MC_BIST_CMD);
+ i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
+ 0, 10, 1, NULL);
+ if (i)
+ return i;
+
+#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+
+ for (i = 15; i >= 0; i--)
+ *data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
+ if (ecc)
+ *ecc = csio_rd_reg64(hw, MC_DATA(16));
+#undef MC_DATA
+ return 0;
+}
+
+/*
+ * csio_t4_edc_read - read from EDC through backdoor accesses
+ * @hw: the hw module
+ * @idx: which EDC to access
+ * @addr: address of first byte requested
+ * @data: 64 bytes of data containing the requested address
+ * @ecc: where to store the corresponding 64-bit ECC word
+ *
+ * Read 64 bytes of data from EDC starting at a 64-byte-aligned address
+ * that covers the requested address @addr. If @parity is not %NULL it
+ * is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t4_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+ uint64_t *ecc)
+{
+ int i;
+
+ idx *= EDC_STRIDE;
+ if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
+ return -EBUSY;
+ csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
+ csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
+ csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
+ csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
+ EDC_BIST_CMD + idx);
+ i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
+ 0, 10, 1, NULL);
+ if (i)
+ return i;
+
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+
+ for (i = 15; i >= 0; i--)
+ *data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
+ if (ecc)
+ *ecc = csio_rd_reg64(hw, EDC_DATA(16));
+#undef EDC_DATA
+ return 0;
+}
+
+/*
+ * csio_t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
+ * @hw: the csio_hw
+ * @win: PCI-E memory Window to use
+ * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_MC0 (or MEM_MC) or MEM_MC1
+ * @addr: address within indicated memory type
+ * @len: amount of memory to transfer
+ * @buf: host memory buffer
+ * @dir: direction of transfer 1 => read, 0 => write
+ *
+ * Reads/writes an [almost] arbitrary memory region in the firmware: the
+ * firmware memory address, length and host buffer must be aligned on
+ * 32-bit boudaries. The memory is transferred as a raw byte sequence
+ * from/to the firmware's memory. If this memory contains data
+ * structures which contain multi-byte integers, it's the callers
+ * responsibility to perform appropriate byte order conversions.
+ */
+static int
+csio_t4_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr,
+ u32 len, uint32_t *buf, int dir)
+{
+ u32 pos, start, offset, memoffset, bar0;
+ u32 edc_size, mc_size, mem_reg, mem_aperture, mem_base;
+
+ /*
+ * Argument sanity checks ...
+ */
+ if ((addr & 0x3) || (len & 0x3))
+ return -EINVAL;
+
+ /* Offset into the region of memory which is being accessed
+ * MEM_EDC0 = 0
+ * MEM_EDC1 = 1
+ * MEM_MC = 2 -- T4
+ */
+ edc_size = EDRAM_SIZE_GET(csio_rd_reg32(hw, MA_EDRAM0_BAR));
+ if (mtype != MEM_MC1)
+ memoffset = (mtype * (edc_size * 1024 * 1024));
+ else {
+ mc_size = EXT_MEM_SIZE_GET(csio_rd_reg32(hw,
+ MA_EXT_MEMORY_BAR));
+ memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
+ }
+
+ /* Determine the PCIE_MEM_ACCESS_OFFSET */
+ addr = addr + memoffset;
+
+ /*
+ * Each PCI-E Memory Window is programmed with a window size -- or
+ * "aperture" -- which controls the granularity of its mapping onto
+ * adapter memory. We need to grab that aperture in order to know
+ * how to use the specified window. The window is also programmed
+ * with the base address of the Memory Window in BAR0's address
+ * space. For T4 this is an absolute PCI-E Bus Address. For T5
+ * the address is relative to BAR0.
+ */
+ mem_reg = csio_rd_reg32(hw,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+ mem_aperture = 1 << (WINDOW(mem_reg) + 10);
+ mem_base = GET_PCIEOFST(mem_reg) << 10;
+
+ bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
+ bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+ mem_base -= bar0;
+
+ start = addr & ~(mem_aperture-1);
+ offset = addr - start;
+
+ csio_dbg(hw, "csio_t4_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n",
+ mem_reg, mem_aperture);
+ csio_dbg(hw, "csio_t4_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n",
+ mem_base, memoffset);
+ csio_dbg(hw, "csio_t4_memory_rw: bar0: 0x%x, start:0x%x, offset:0x%x\n",
+ bar0, start, offset);
+ csio_dbg(hw, "csio_t4_memory_rw: mtype: %d, addr: 0x%x, len: %d\n",
+ mtype, addr, len);
+
+ for (pos = start; len > 0; pos += mem_aperture, offset = 0) {
+ /*
+ * Move PCI-E Memory Window to our current transfer
+ * position. Read it back to ensure that changes propagate
+ * before we attempt to use the new value.
+ */
+ csio_wr_reg32(hw, pos,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+ csio_rd_reg32(hw,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+
+ while (offset < mem_aperture && len > 0) {
+ if (dir)
+ *buf++ = csio_rd_reg32(hw, mem_base + offset);
+ else
+ csio_wr_reg32(hw, *buf++, mem_base + offset);
+
+ offset += sizeof(__be32);
+ len -= sizeof(__be32);
+ }
+ }
+ return 0;
+}
+
+/*
+ * csio_t4_dfs_create_ext_mem - setup debugfs for MC to read the values
+ * @hw: the csio_hw
+ *
+ * This function creates files in the debugfs with external memory region MC.
+ */
+static void
+csio_t4_dfs_create_ext_mem(struct csio_hw *hw)
+{
+ u32 size;
+ int i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
+ if (i & EXT_MEM_ENABLE) {
+ size = csio_rd_reg32(hw, MA_EXT_MEMORY_BAR);
+ csio_add_debugfs_mem(hw, "mc", MEM_MC,
+ EXT_MEM_SIZE_GET(size));
+ }
+}
+
+/* T4 adapter specific function */
+struct csio_hw_chip_ops t4_ops = {
+ .chip_set_mem_win = csio_t4_set_mem_win,
+ .chip_pcie_intr_handler = csio_t4_pcie_intr_handler,
+ .chip_flash_cfg_addr = csio_t4_flash_cfg_addr,
+ .chip_mc_read = csio_t4_mc_read,
+ .chip_edc_read = csio_t4_edc_read,
+ .chip_memory_rw = csio_t4_memory_rw,
+ .chip_dfs_create_ext_mem = csio_t4_dfs_create_ext_mem,
+};
diff --git a/drivers/scsi/csiostor/csio_hw_t5.c b/drivers/scsi/csiostor/csio_hw_t5.c
new file mode 100644
index 0000000..27745c1
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw_t5.c
@@ -0,0 +1,397 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "csio_hw.h"
+#include "csio_init.h"
+
+static int
+csio_t5_set_mem_win(struct csio_hw *hw, uint32_t win)
+{
+ u32 mem_win_base;
+ /*
+ * Truncation intentional: we only read the bottom 32-bits of the
+ * 64-bit BAR0/BAR1 ... We use the hardware backdoor mechanism to
+ * read BAR0 instead of using pci_resource_start() because we could be
+ * operating from within a Virtual Machine which is trapping our
+ * accesses to our Configuration Space and we need to set up the PCI-E
+ * Memory Window decoders with the actual addresses which will be
+ * coming across the PCI-E link.
+ */
+
+ /* For T5, only relative offset inside the PCIe BAR is passed */
+ mem_win_base = MEMWIN_BASE;
+
+ /*
+ * Set up memory window for accessing adapter memory ranges. (Read
+ * back MA register to ensure that changes propagate before we attempt
+ * to use the new values.)
+ */
+ csio_wr_reg32(hw, mem_win_base | BIR(0) |
+ WINDOW(ilog2(MEMWIN_APERTURE) - 10),
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+ csio_rd_reg32(hw,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+
+ return 0;
+}
+
+/*
+ * Interrupt handler for the PCIE module.
+ */
+static void
+csio_t5_pcie_intr_handler(struct csio_hw *hw)
+{
+ static struct intr_info sysbus_intr_info[] = {
+ { RNPP, "RXNP array parity error", -1, 1 },
+ { RPCP, "RXPC array parity error", -1, 1 },
+ { RCIP, "RXCIF array parity error", -1, 1 },
+ { RCCP, "Rx completions control array parity error", -1, 1 },
+ { RFTP, "RXFT array parity error", -1, 1 },
+ { 0, NULL, 0, 0 }
+ };
+ static struct intr_info pcie_port_intr_info[] = {
+ { TPCP, "TXPC array parity error", -1, 1 },
+ { TNPP, "TXNP array parity error", -1, 1 },
+ { TFTP, "TXFT array parity error", -1, 1 },
+ { TCAP, "TXCA array parity error", -1, 1 },
+ { TCIP, "TXCIF array parity error", -1, 1 },
+ { RCAP, "RXCA array parity error", -1, 1 },
+ { OTDD, "outbound request TLP discarded", -1, 1 },
+ { RDPE, "Rx data parity error", -1, 1 },
+ { TDUE, "Tx uncorrectable data error", -1, 1 },
+ { 0, NULL, 0, 0 }
+ };
+
+ static struct intr_info pcie_intr_info[] = {
+ { MSTGRPPERR, "Master Response Read Queue parity error",
+ -1, 1 },
+ { MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 },
+ { MSIXSTIPERR, "MSI-X STI SRAM parity error", -1, 1 },
+ { MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+ { MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+ { MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+ { MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+ { PIOCPLGRPPERR, "PCI PIO completion Group FIFO parity error",
+ -1, 1 },
+ { PIOREQGRPPERR, "PCI PIO request Group FIFO parity error",
+ -1, 1 },
+ { TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+ { MSTTAGQPERR, "PCI master tag queue parity error", -1, 1 },
+ { CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+ { CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+ { DREQWRPERR, "PCI DMA channel write request parity error",
+ -1, 1 },
+ { DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+ { DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+ { HREQWRPERR, "PCI HMA channel count parity error", -1, 1 },
+ { HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+ { HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+ { CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+ { FIDPERR, "PCI FID parity error", -1, 1 },
+ { VFIDPERR, "PCI INTx clear parity error", -1, 1 },
+ { MAGRPPERR, "PCI MA group FIFO parity error", -1, 1 },
+ { PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+ { IPRXHDRGRPPERR, "PCI IP Rx header group parity error",
+ -1, 1 },
+ { IPRXDATAGRPPERR, "PCI IP Rx data group parity error",
+ -1, 1 },
+ { RPLPERR, "PCI IP replay buffer parity error", -1, 1 },
+ { IPSOTPERR, "PCI IP SOT buffer parity error", -1, 1 },
+ { TRGT1GRPPERR, "PCI TRGT1 group FIFOs parity error", -1, 1 },
+ { READRSPERR, "Outbound read error", -1, 0 },
+ { 0, NULL, 0, 0 }
+ };
+
+ int fat;
+ fat = csio_handle_intr_status(hw,
+ PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+ sysbus_intr_info) +
+ csio_handle_intr_status(hw,
+ PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+ pcie_port_intr_info) +
+ csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
+ if (fat)
+ csio_hw_fatal_err(hw);
+}
+
+/*
+ * csio_t5_flash_cfg_addr - return the address of the flash configuration file
+ * @hw: the HW module
+ *
+ * Return the address within the flash where the Firmware Configuration
+ * File is stored.
+ */
+static unsigned int
+csio_t5_flash_cfg_addr(struct csio_hw *hw)
+{
+ return FLASH_CFG_START;
+}
+
+/*
+ * csio_t5_mc_read - read from MC through backdoor accesses
+ * @hw: the hw module
+ * @idx: index to the register
+ * @addr: address of first byte requested
+ * @data: 64 bytes of data containing the requested address
+ * @ecc: where to store the corresponding 64-bit ECC word
+ *
+ * Read 64 bytes of data from MC starting at a 64-byte-aligned address
+ * that covers the requested address @addr. If @parity is not %NULL it
+ * is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t5_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+ uint64_t *ecc)
+{
+ int i;
+ uint32_t mc_bist_cmd_reg, mc_bist_cmd_addr_reg, mc_bist_cmd_len_reg;
+ uint32_t mc_bist_status_rdata_reg, mc_bist_data_pattern_reg;
+
+ mc_bist_cmd_reg = MC_REG(MC_P_BIST_CMD, idx);
+ mc_bist_cmd_addr_reg = MC_REG(MC_P_BIST_CMD_ADDR, idx);
+ mc_bist_cmd_len_reg = MC_REG(MC_P_BIST_CMD_LEN, idx);
+ mc_bist_status_rdata_reg = MC_REG(MC_P_BIST_STATUS_RDATA, idx);
+ mc_bist_data_pattern_reg = MC_REG(MC_P_BIST_DATA_PATTERN, idx);
+
+ if (csio_rd_reg32(hw, mc_bist_cmd_reg) & START_BIST)
+ return -EBUSY;
+ csio_wr_reg32(hw, addr & ~0x3fU, mc_bist_cmd_addr_reg);
+ csio_wr_reg32(hw, 64, mc_bist_cmd_len_reg);
+ csio_wr_reg32(hw, 0xc, mc_bist_data_pattern_reg);
+ csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST | BIST_CMD_GAP(1),
+ mc_bist_cmd_reg);
+ i = csio_hw_wait_op_done_val(hw, mc_bist_cmd_reg, START_BIST,
+ 0, 10, 1, NULL);
+ if (i)
+ return i;
+
+#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+
+ for (i = 15; i >= 0; i--)
+ *data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
+ if (ecc)
+ *ecc = csio_rd_reg64(hw, MC_DATA(16));
+#undef MC_DATA
+ return 0;
+}
+
+/*
+ * csio_t5_edc_read - read from EDC through backdoor accesses
+ * @hw: the hw module
+ * @idx: which EDC to access
+ * @addr: address of first byte requested
+ * @data: 64 bytes of data containing the requested address
+ * @ecc: where to store the corresponding 64-bit ECC word
+ *
+ * Read 64 bytes of data from EDC starting at a 64-byte-aligned address
+ * that covers the requested address @addr. If @parity is not %NULL it
+ * is assigned the 64-bit ECC word for the read data.
+ */
+static int
+csio_t5_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
+ uint64_t *ecc)
+{
+ int i;
+ uint32_t edc_bist_cmd_reg, edc_bist_cmd_addr_reg, edc_bist_cmd_len_reg;
+ uint32_t edc_bist_cmd_data_pattern, edc_bist_status_rdata_reg;
+
+/*
+ * These macro are missing in t4_regs.h file.
+ */
+#define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
+#define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
+
+ edc_bist_cmd_reg = EDC_REG_T5(EDC_H_BIST_CMD, idx);
+ edc_bist_cmd_addr_reg = EDC_REG_T5(EDC_H_BIST_CMD_ADDR, idx);
+ edc_bist_cmd_len_reg = EDC_REG_T5(EDC_H_BIST_CMD_LEN, idx);
+ edc_bist_cmd_data_pattern = EDC_REG_T5(EDC_H_BIST_DATA_PATTERN, idx);
+ edc_bist_status_rdata_reg = EDC_REG_T5(EDC_H_BIST_STATUS_RDATA, idx);
+#undef EDC_REG_T5
+#undef EDC_STRIDE_T5
+
+ if (csio_rd_reg32(hw, edc_bist_cmd_reg) & START_BIST)
+ return -EBUSY;
+ csio_wr_reg32(hw, addr & ~0x3fU, edc_bist_cmd_addr_reg);
+ csio_wr_reg32(hw, 64, edc_bist_cmd_len_reg);
+ csio_wr_reg32(hw, 0xc, edc_bist_cmd_data_pattern);
+ csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST | BIST_CMD_GAP(1),
+ edc_bist_cmd_reg);
+ i = csio_hw_wait_op_done_val(hw, edc_bist_cmd_reg, START_BIST,
+ 0, 10, 1, NULL);
+ if (i)
+ return i;
+
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+
+ for (i = 15; i >= 0; i--)
+ *data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
+ if (ecc)
+ *ecc = csio_rd_reg64(hw, EDC_DATA(16));
+#undef EDC_DATA
+ return 0;
+}
+
+/*
+ * csio_t5_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
+ * @hw: the csio_hw
+ * @win: PCI-E memory Window to use
+ * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_MC0 (or MEM_MC) or MEM_MC1
+ * @addr: address within indicated memory type
+ * @len: amount of memory to transfer
+ * @buf: host memory buffer
+ * @dir: direction of transfer 1 => read, 0 => write
+ *
+ * Reads/writes an [almost] arbitrary memory region in the firmware: the
+ * firmware memory address, length and host buffer must be aligned on
+ * 32-bit boudaries. The memory is transferred as a raw byte sequence
+ * from/to the firmware's memory. If this memory contains data
+ * structures which contain multi-byte integers, it's the callers
+ * responsibility to perform appropriate byte order conversions.
+ */
+static int
+csio_t5_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr,
+ u32 len, uint32_t *buf, int dir)
+{
+ u32 pos, start, offset, memoffset;
+ u32 edc_size, mc_size, win_pf, mem_reg, mem_aperture, mem_base;
+
+ /*
+ * Argument sanity checks ...
+ */
+ if ((addr & 0x3) || (len & 0x3))
+ return -EINVAL;
+
+ /* Offset into the region of memory which is being accessed
+ * MEM_EDC0 = 0
+ * MEM_EDC1 = 1
+ * MEM_MC = 2 -- T4
+ * MEM_MC0 = 2 -- For T5
+ * MEM_MC1 = 3 -- For T5
+ */
+ edc_size = EDRAM_SIZE_GET(csio_rd_reg32(hw, MA_EDRAM0_BAR));
+ if (mtype != MEM_MC1)
+ memoffset = (mtype * (edc_size * 1024 * 1024));
+ else {
+ mc_size = EXT_MEM_SIZE_GET(csio_rd_reg32(hw,
+ MA_EXT_MEMORY_BAR));
+ memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
+ }
+
+ /* Determine the PCIE_MEM_ACCESS_OFFSET */
+ addr = addr + memoffset;
+
+ /*
+ * Each PCI-E Memory Window is programmed with a window size -- or
+ * "aperture" -- which controls the granularity of its mapping onto
+ * adapter memory. We need to grab that aperture in order to know
+ * how to use the specified window. The window is also programmed
+ * with the base address of the Memory Window in BAR0's address
+ * space. For T4 this is an absolute PCI-E Bus Address. For T5
+ * the address is relative to BAR0.
+ */
+ mem_reg = csio_rd_reg32(hw,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
+ mem_aperture = 1 << (WINDOW(mem_reg) + 10);
+ mem_base = GET_PCIEOFST(mem_reg) << 10;
+
+ start = addr & ~(mem_aperture-1);
+ offset = addr - start;
+ win_pf = V_PFNUM(hw->pfn);
+
+ csio_dbg(hw, "csio_t5_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n",
+ mem_reg, mem_aperture);
+ csio_dbg(hw, "csio_t5_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n",
+ mem_base, memoffset);
+ csio_dbg(hw, "csio_t5_memory_rw: start:0x%x, offset:0x%x, win_pf:%d\n",
+ start, offset, win_pf);
+ csio_dbg(hw, "csio_t5_memory_rw: mtype: %d, addr: 0x%x, len: %d\n",
+ mtype, addr, len);
+
+ for (pos = start; len > 0; pos += mem_aperture, offset = 0) {
+ /*
+ * Move PCI-E Memory Window to our current transfer
+ * position. Read it back to ensure that changes propagate
+ * before we attempt to use the new value.
+ */
+ csio_wr_reg32(hw, pos | win_pf,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+ csio_rd_reg32(hw,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+
+ while (offset < mem_aperture && len > 0) {
+ if (dir)
+ *buf++ = csio_rd_reg32(hw, mem_base + offset);
+ else
+ csio_wr_reg32(hw, *buf++, mem_base + offset);
+
+ offset += sizeof(__be32);
+ len -= sizeof(__be32);
+ }
+ }
+ return 0;
+}
+
+/*
+ * csio_t5_dfs_create_ext_mem - setup debugfs for MC0 or MC1 to read the values
+ * @hw: the csio_hw
+ *
+ * This function creates files in the debugfs with external memory region
+ * MC0 & MC1.
+ */
+static void
+csio_t5_dfs_create_ext_mem(struct csio_hw *hw)
+{
+ u32 size;
+ int i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
+ if (i & EXT_MEM_ENABLE) {
+ size = csio_rd_reg32(hw, MA_EXT_MEMORY_BAR);
+ csio_add_debugfs_mem(hw, "mc0", MEM_MC0,
+ EXT_MEM_SIZE_GET(size));
+ }
+ if (i & EXT_MEM1_ENABLE) {
+ size = csio_rd_reg32(hw, MA_EXT_MEMORY1_BAR);
+ csio_add_debugfs_mem(hw, "mc1", MEM_MC1,
+ EXT_MEM_SIZE_GET(size));
+ }
+}
+
+/* T5 adapter specific function */
+struct csio_hw_chip_ops t5_ops = {
+ .chip_set_mem_win = csio_t5_set_mem_win,
+ .chip_pcie_intr_handler = csio_t5_pcie_intr_handler,
+ .chip_flash_cfg_addr = csio_t5_flash_cfg_addr,
+ .chip_mc_read = csio_t5_mc_read,
+ .chip_edc_read = csio_t5_edc_read,
+ .chip_memory_rw = csio_t5_memory_rw,
+ .chip_dfs_create_ext_mem = csio_t5_dfs_create_ext_mem,
+};
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
index fdd408f..00346fe 100644
--- a/drivers/scsi/csiostor/csio_init.c
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -60,18 +60,11 @@ static struct scsi_transport_template *csio_fcoe_transport_vport;
/*
* debugfs support
*/
-static int
-csio_mem_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t
csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
loff_t pos = *ppos;
- loff_t avail = file->f_path.dentry->d_inode->i_size;
+ loff_t avail = file_inode(file)->i_size;
unsigned int mem = (uintptr_t)file->private_data & 3;
struct csio_hw *hw = file->private_data - mem;
@@ -88,9 +81,11 @@ csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
__be32 data[16];
if (mem == MEM_MC)
- ret = csio_hw_mc_read(hw, pos, data, NULL);
+ ret = hw->chip_ops->chip_mc_read(hw, 0, pos,
+ data, NULL);
else
- ret = csio_hw_edc_read(hw, mem, pos, data, NULL);
+ ret = hw->chip_ops->chip_edc_read(hw, mem, pos,
+ data, NULL);
if (ret)
return ret;
@@ -110,14 +105,13 @@ csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
static const struct file_operations csio_mem_debugfs_fops = {
.owner = THIS_MODULE,
- .open = csio_mem_open,
+ .open = simple_open,
.read = csio_mem_read,
.llseek = default_llseek,
};
-static void __devinit
-csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
- unsigned int idx, unsigned int size_mb)
+void csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
+ unsigned int idx, unsigned int size_mb)
{
struct dentry *de;
@@ -127,8 +121,7 @@ csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
de->d_inode->i_size = size_mb << 20;
}
-static int __devinit
-csio_setup_debugfs(struct csio_hw *hw)
+static int csio_setup_debugfs(struct csio_hw *hw)
{
int i;
@@ -140,9 +133,8 @@ csio_setup_debugfs(struct csio_hw *hw)
csio_add_debugfs_mem(hw, "edc0", MEM_EDC0, 5);
if (i & EDRAM1_ENABLE)
csio_add_debugfs_mem(hw, "edc1", MEM_EDC1, 5);
- if (i & EXT_MEM_ENABLE)
- csio_add_debugfs_mem(hw, "mc", MEM_MC,
- EXT_MEM_SIZE_GET(csio_rd_reg32(hw, MA_EXT_MEMORY_BAR)));
+
+ hw->chip_ops->chip_dfs_create_ext_mem(hw);
return 0;
}
@@ -531,8 +523,7 @@ csio_resource_free(struct csio_hw *hw)
* Allocates HW structure, DMA, memory resources, maps BARS to
* host memory and initializes HW module.
*/
-static struct csio_hw * __devinit
-csio_hw_alloc(struct pci_dev *pdev)
+static struct csio_hw *csio_hw_alloc(struct pci_dev *pdev)
{
struct csio_hw *hw;
@@ -956,8 +947,7 @@ csio_lnode_init_post(struct csio_lnode *ln)
* - Once hardware is ready, initiated scan of the host via
* scsi_scan_host.
*/
-static int __devinit
-csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
int rv;
int bars;
@@ -1036,8 +1026,7 @@ err:
*
* Used during hotplug operation.
*/
-static void __devexit
-csio_remove_one(struct pci_dev *pdev)
+static void csio_remove_one(struct pci_dev *pdev)
{
struct csio_hw *hw = pci_get_drvdata(pdev);
int bars = pci_select_bars(pdev, IORESOURCE_MEM);
@@ -1181,7 +1170,7 @@ static struct pci_error_handlers csio_err_handler = {
};
static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
- CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0), /* T440DBG FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0), /* T4 DEBUG FCOE */
CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0), /* T420CR FCOE */
CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0), /* T422CR FCOE */
CSIO_DEVICE(CSIO_DEVID_T440CR_FCOE, 0), /* T440CR FCOE */
@@ -1196,8 +1185,34 @@ static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
CSIO_DEVICE(CSIO_DEVID_B404_FCOE, 0), /* B404 FCOE */
CSIO_DEVICE(CSIO_DEVID_T480CR_FCOE, 0), /* T480 CR FCOE */
CSIO_DEVICE(CSIO_DEVID_T440LPCR_FCOE, 0), /* T440 LP-CR FCOE */
- CSIO_DEVICE(CSIO_DEVID_PE10K, 0), /* PE10K FCOE */
- CSIO_DEVICE(CSIO_DEVID_PE10K_PF1, 0), /* PE10K FCOE on PF1 */
+ CSIO_DEVICE(CSIO_DEVID_AMSTERDAM_T4_FCOE, 0), /* AMSTERDAM T4 FCOE */
+ CSIO_DEVICE(CSIO_DEVID_HUAWEI_T480_FCOE, 0), /* HUAWEI T480 FCOE */
+ CSIO_DEVICE(CSIO_DEVID_HUAWEI_T440_FCOE, 0), /* HUAWEI T440 FCOE */
+ CSIO_DEVICE(CSIO_DEVID_HUAWEI_STG310_FCOE, 0), /* HUAWEI STG FCOE */
+ CSIO_DEVICE(CSIO_DEVID_ACROMAG_XMC_XAUI, 0), /* ACROMAG XAUI FCOE */
+ CSIO_DEVICE(CSIO_DEVID_QUANTA_MEZZ_SFP_FCOE, 0),/* QUANTA MEZZ FCOE */
+ CSIO_DEVICE(CSIO_DEVID_HUAWEI_10GT_FCOE, 0), /* HUAWEI 10GT FCOE */
+ CSIO_DEVICE(CSIO_DEVID_HUAWEI_T440_TOE_FCOE, 0),/* HUAWEI T4 TOE FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T580DBG_FCOE, 0), /* T5 DEBUG FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T520CR_FCOE, 0), /* T520CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T522CR_FCOE, 0), /* T522CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T540CR_FCOE, 0), /* T540CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T520BCH_FCOE, 0), /* T520BCH FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T540BCH_FCOE, 0), /* T540BCH FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T540CH_FCOE, 0), /* T540CH FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T520SO_FCOE, 0), /* T520SO FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T520CX_FCOE, 0), /* T520CX FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T520BT_FCOE, 0), /* T520BT FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T504BT_FCOE, 0), /* T504BT FCOE */
+ CSIO_DEVICE(CSIO_DEVID_B520_FCOE, 0), /* B520 FCOE */
+ CSIO_DEVICE(CSIO_DEVID_B504_FCOE, 0), /* B504 FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T580CR2_FCOE, 0), /* T580 CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T540LPCR_FCOE, 0), /* T540 LP-CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_AMSTERDAM_T5_FCOE, 0), /* AMSTERDAM T5 FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T580LPCR_FCOE, 0), /* T580 LP-CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T520LLCR_FCOE, 0), /* T520 LL-CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T560CR_FCOE, 0), /* T560 CR FCOE */
+ CSIO_DEVICE(CSIO_DEVID_T580CR_FCOE, 0), /* T580 CR FCOE */
{ 0, 0, 0, 0, 0, 0, 0 }
};
@@ -1271,4 +1286,5 @@ MODULE_DESCRIPTION(CSIO_DRV_DESC);
MODULE_LICENSE(CSIO_DRV_LICENSE);
MODULE_DEVICE_TABLE(pci, csio_pci_tbl);
MODULE_VERSION(CSIO_DRV_VERSION);
-MODULE_FIRMWARE(CSIO_FW_FNAME);
+MODULE_FIRMWARE(FW_FNAME_T4);
+MODULE_FIRMWARE(FW_FNAME_T5);
diff --git a/drivers/scsi/csiostor/csio_init.h b/drivers/scsi/csiostor/csio_init.h
index 0838fd7..5cc5d31 100644
--- a/drivers/scsi/csiostor/csio_init.h
+++ b/drivers/scsi/csiostor/csio_init.h
@@ -52,31 +52,6 @@
#define CSIO_DRV_DESC "Chelsio FCoE driver"
#define CSIO_DRV_VERSION "1.0.0"
-#define CSIO_DEVICE(devid, idx) \
-{ PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
-
-#define CSIO_IS_T4_FPGA(_dev) (((_dev) == CSIO_DEVID_PE10K) ||\
- ((_dev) == CSIO_DEVID_PE10K_PF1))
-
-/* FCoE device IDs */
-#define CSIO_DEVID_PE10K 0xA000
-#define CSIO_DEVID_PE10K_PF1 0xA001
-#define CSIO_DEVID_T440DBG_FCOE 0x4600
-#define CSIO_DEVID_T420CR_FCOE 0x4601
-#define CSIO_DEVID_T422CR_FCOE 0x4602
-#define CSIO_DEVID_T440CR_FCOE 0x4603
-#define CSIO_DEVID_T420BCH_FCOE 0x4604
-#define CSIO_DEVID_T440BCH_FCOE 0x4605
-#define CSIO_DEVID_T440CH_FCOE 0x4606
-#define CSIO_DEVID_T420SO_FCOE 0x4607
-#define CSIO_DEVID_T420CX_FCOE 0x4608
-#define CSIO_DEVID_T420BT_FCOE 0x4609
-#define CSIO_DEVID_T404BT_FCOE 0x460A
-#define CSIO_DEVID_B420_FCOE 0x460B
-#define CSIO_DEVID_B404_FCOE 0x460C
-#define CSIO_DEVID_T480CR_FCOE 0x460D
-#define CSIO_DEVID_T440LPCR_FCOE 0x460E
-
extern struct fc_function_template csio_fc_transport_funcs;
extern struct fc_function_template csio_fc_transport_vport_funcs;
@@ -100,6 +75,10 @@ struct csio_lnode *csio_shost_init(struct csio_hw *, struct device *, bool,
void csio_shost_exit(struct csio_lnode *);
void csio_lnodes_exit(struct csio_hw *, bool);
+/* DebugFS helper routines */
+void csio_add_debugfs_mem(struct csio_hw *, const char *,
+ unsigned int, unsigned int);
+
static inline struct Scsi_Host *
csio_ln_to_shost(struct csio_lnode *ln)
{
diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h
index 8d84988..372a67d 100644
--- a/drivers/scsi/csiostor/csio_lnode.h
+++ b/drivers/scsi/csiostor/csio_lnode.h
@@ -114,7 +114,7 @@ struct csio_lnode_stats {
uint32_t n_rnode_match; /* matched rnode */
uint32_t n_dev_loss_tmo; /* Device loss timeout */
uint32_t n_fdmi_err; /* fdmi err */
- uint32_t n_evt_fw[RSCN_DEV_LOST]; /* fw events */
+ uint32_t n_evt_fw[PROTO_ERR_IMPL_LOGO + 1]; /* fw events */
enum csio_ln_ev n_evt_sm[CSIO_LNE_MAX_EVENT]; /* State m/c events */
uint32_t n_rnode_alloc; /* rnode allocated */
uint32_t n_rnode_free; /* rnode freed */
diff --git a/drivers/scsi/csiostor/csio_mb.c b/drivers/scsi/csiostor/csio_mb.c
index 5b27c48..15b6351 100644
--- a/drivers/scsi/csiostor/csio_mb.c
+++ b/drivers/scsi/csiostor/csio_mb.c
@@ -182,7 +182,7 @@ csio_mb_reset(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
* @tmo: Command timeout.
* @pf: PF number.
* @vf: VF number.
- * @nparams: Number of paramters
+ * @nparams: Number of parameters
* @params: Parameter mnemonic array.
* @val: Parameter value array.
* @wr: Write/Read PARAMS.
@@ -326,83 +326,6 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
}
-void
-csio_rss_glb_config(struct csio_hw *hw, struct csio_mb *mbp,
- uint32_t tmo, uint8_t mode, unsigned int flags,
- void (*cbfn)(struct csio_hw *, struct csio_mb *))
-{
- struct fw_rss_glb_config_cmd *cmdp =
- (struct fw_rss_glb_config_cmd *)(mbp->mb);
-
- CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
-
- cmdp->op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
- FW_CMD_REQUEST | FW_CMD_WRITE);
- cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
-
- if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
- cmdp->u.manual.mode_pkd =
- htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
- } else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
- cmdp->u.basicvirtual.mode_pkd =
- htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
- cmdp->u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags);
- }
-}
-
-
-/*
- * csio_mb_pfvf - FW Write PF/VF capabilities command helper.
- * @hw: The HW structure
- * @mbp: Mailbox structure
- * @pf:
- * @vf:
- * @txq:
- * @txq_eht_ctrl:
- * @rxqi:
- * @rxq:
- * @tc:
- * @vi:
- * @pmask:
- * @rcaps:
- * @wxcaps:
- * @cbfn: Callback, if any.
- *
- */
-void
-csio_mb_pfvf(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
- unsigned int pf, unsigned int vf, unsigned int txq,
- unsigned int txq_eth_ctrl, unsigned int rxqi,
- unsigned int rxq, unsigned int tc, unsigned int vi,
- unsigned int cmask, unsigned int pmask, unsigned int nexactf,
- unsigned int rcaps, unsigned int wxcaps,
- void (*cbfn) (struct csio_hw *, struct csio_mb *))
-{
- struct fw_pfvf_cmd *cmdp = (struct fw_pfvf_cmd *)(mbp->mb);
-
- CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
-
- cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD) |
- FW_CMD_REQUEST |
- FW_CMD_WRITE |
- FW_PFVF_CMD_PFN(pf) |
- FW_PFVF_CMD_VFN(vf));
- cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
- cmdp->niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi) |
- FW_PFVF_CMD_NIQ(rxq));
-
- cmdp->type_to_neq = htonl(FW_PFVF_CMD_TYPE |
- FW_PFVF_CMD_CMASK(cmask) |
- FW_PFVF_CMD_PMASK(pmask) |
- FW_PFVF_CMD_NEQ(txq));
- cmdp->tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc) |
- FW_PFVF_CMD_NVI(vi) |
- FW_PFVF_CMD_NEXACTF(nexactf));
- cmdp->r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps) |
- FW_PFVF_CMD_WX_CAPS(wxcaps) |
- FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
-}
-
#define CSIO_ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG)
@@ -721,7 +644,7 @@ csio_mb_iq_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
* @mbp: Mailbox structure to initialize
* @priv: Private data
* @mb_tmo: Mailbox time-out period (in ms).
- * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @eq_ofld_params: (Offload) Egress queue parameters.
* @cbfn: The call-back function
*
*
@@ -752,7 +675,7 @@ csio_mb_eq_ofld_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
* @priv: Private data
* @mb_tmo: Mailbox time-out period (in ms).
* @cascaded_req: TRUE - if this request is cascased with Eq-alloc request.
- * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @eq_ofld_params: (Offload) Egress queue parameters.
* @cbfn: The call-back function
*
*
@@ -817,7 +740,7 @@ csio_mb_eq_ofld_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
* @mbp: Mailbox structure to initialize
* @priv: Private data.
* @mb_tmo: Mailbox time-out period (in ms).
- * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @eq_ofld_params: (Offload) Egress queue parameters.
* @cbfn: The call-back function
*
*
@@ -840,7 +763,7 @@ csio_mb_eq_ofld_alloc_write(struct csio_hw *hw, struct csio_mb *mbp,
* @hw: The HW structure.
* @mbp: Mailbox structure to initialize.
* @retval: Firmware return value.
- * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @eq_ofld_params: (Offload) Egress queue parameters.
*
*/
void
@@ -870,7 +793,7 @@ csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *hw,
* @mbp: Mailbox structure to initialize
* @priv: Private data area.
* @mb_tmo: Mailbox time-out period (in ms).
- * @eq_ofld_params: (Offload) Egress queue paramters, that is to be freed.
+ * @eq_ofld_params: (Offload) Egress queue parameters, that is to be freed.
* @cbfn: The call-back function
*
*
diff --git a/drivers/scsi/csiostor/csio_mb.h b/drivers/scsi/csiostor/csio_mb.h
index 1788ea5..a84179e 100644
--- a/drivers/scsi/csiostor/csio_mb.h
+++ b/drivers/scsi/csiostor/csio_mb.h
@@ -183,17 +183,6 @@ void csio_mb_caps_config(struct csio_hw *, struct csio_mb *, uint32_t,
bool, bool, bool, bool,
void (*)(struct csio_hw *, struct csio_mb *));
-void csio_rss_glb_config(struct csio_hw *, struct csio_mb *,
- uint32_t, uint8_t, unsigned int,
- void (*)(struct csio_hw *, struct csio_mb *));
-
-void csio_mb_pfvf(struct csio_hw *, struct csio_mb *, uint32_t,
- unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int, unsigned int,
- unsigned int, void (*) (struct csio_hw *, struct csio_mb *));
-
void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
uint8_t, bool, uint32_t, uint16_t,
void (*) (struct csio_hw *, struct csio_mb *));
diff --git a/drivers/scsi/csiostor/csio_rnode.c b/drivers/scsi/csiostor/csio_rnode.c
index 51c6a38..e9c3b04 100644
--- a/drivers/scsi/csiostor/csio_rnode.c
+++ b/drivers/scsi/csiostor/csio_rnode.c
@@ -302,7 +302,7 @@ csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
{
uint8_t rport_type;
struct csio_rnode *rn, *match_rn;
- uint32_t vnp_flowid;
+ uint32_t vnp_flowid = 0;
__be32 *port_id;
port_id = (__be32 *)&rdevp->r_id[0];
@@ -350,6 +350,14 @@ csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
* Else, go ahead and alloc a new rnode.
*/
if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
+ if (rn == match_rn)
+ goto found_rnode;
+ csio_ln_dbg(ln,
+ "nport_id:x%x and wwpn:%llx"
+ " match for ssni:x%x\n",
+ rn->nport_id,
+ wwn_to_u64(rdevp->wwpn),
+ rdev_flowid);
if (csio_is_rnode_ready(rn)) {
csio_ln_warn(ln,
"rnode is already"
diff --git a/drivers/scsi/csiostor/csio_rnode.h b/drivers/scsi/csiostor/csio_rnode.h
index a3b434c..4334342 100644
--- a/drivers/scsi/csiostor/csio_rnode.h
+++ b/drivers/scsi/csiostor/csio_rnode.h
@@ -63,7 +63,7 @@ struct csio_rnode_stats {
uint32_t n_err_nomem; /* error nomem */
uint32_t n_evt_unexp; /* unexpected event */
uint32_t n_evt_drop; /* unexpected event */
- uint32_t n_evt_fw[RSCN_DEV_LOST]; /* fw events */
+ uint32_t n_evt_fw[PROTO_ERR_IMPL_LOGO + 1]; /* fw events */
enum csio_rn_ev n_evt_sm[CSIO_RNFE_MAX_EVENT]; /* State m/c events */
uint32_t n_lun_rst; /* Number of resets of
* of LUNs under this
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index ddd38e5..7494e4b 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -1479,8 +1479,8 @@ csio_store_dbg_level(struct device *dev,
}
static DEVICE_ATTR(hw_state, S_IRUGO, csio_show_hw_state, NULL);
-static DEVICE_ATTR(device_reset, S_IRUGO | S_IWUSR, NULL, csio_device_reset);
-static DEVICE_ATTR(disable_port, S_IRUGO | S_IWUSR, NULL, csio_disable_port);
+static DEVICE_ATTR(device_reset, S_IWUSR, NULL, csio_device_reset);
+static DEVICE_ATTR(disable_port, S_IWUSR, NULL, csio_disable_port);
static DEVICE_ATTR(dbg_level, S_IRUGO | S_IWUSR, csio_show_dbg_level,
csio_store_dbg_level);
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
index c32df1b..4255ce2 100644
--- a/drivers/scsi/csiostor/csio_wr.c
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -85,8 +85,8 @@ csio_wr_ring_fldb(struct csio_hw *hw, struct csio_q *flq)
*/
if (flq->inc_idx >= 8) {
csio_wr_reg32(hw, DBPRIO(1) | QID(flq->un.fl.flid) |
- PIDX(flq->inc_idx / 8),
- MYPF_REG(SGE_PF_KDOORBELL));
+ CSIO_HW_PIDX(hw, flq->inc_idx / 8),
+ MYPF_REG(SGE_PF_KDOORBELL));
flq->inc_idx &= 7;
}
}
@@ -989,7 +989,8 @@ csio_wr_issue(struct csio_hw *hw, int qidx, bool prio)
wmb();
/* Ring SGE Doorbell writing q->pidx into it */
csio_wr_reg32(hw, DBPRIO(prio) | QID(q->un.eq.physeqid) |
- PIDX(q->inc_idx), MYPF_REG(SGE_PF_KDOORBELL));
+ CSIO_HW_PIDX(hw, q->inc_idx),
+ MYPF_REG(SGE_PF_KDOORBELL));
q->inc_idx = 0;
return 0;
@@ -1331,20 +1332,30 @@ csio_wr_fixup_host_params(struct csio_hw *hw)
/* FL BUFFER SIZE#0 is Page size i,e already aligned to cache line */
csio_wr_reg32(hw, PAGE_SIZE, SGE_FL_BUFFER_SIZE0);
- csio_wr_reg32(hw,
- (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE2) +
- sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
- SGE_FL_BUFFER_SIZE2);
- csio_wr_reg32(hw,
- (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE3) +
- sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
- SGE_FL_BUFFER_SIZE3);
+
+ /*
+ * If using hard params, the following will get set correctly
+ * in csio_wr_set_sge().
+ */
+ if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS) {
+ csio_wr_reg32(hw,
+ (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE2) +
+ sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+ SGE_FL_BUFFER_SIZE2);
+ csio_wr_reg32(hw,
+ (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE3) +
+ sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+ SGE_FL_BUFFER_SIZE3);
+ }
csio_wr_reg32(hw, HPZ0(PAGE_SHIFT - 12), ULP_RX_TDDP_PSZ);
/* default value of rx_dma_offset of the NIC driver */
csio_set_reg_field(hw, SGE_CONTROL, PKTSHIFT_MASK,
PKTSHIFT(CSIO_SGE_RX_DMA_OFFSET));
+
+ csio_hw_tp_wr_bits_indirect(hw, TP_INGRESS_CONFIG,
+ CSUM_HAS_PSEUDO_HDR, 0);
}
static void
@@ -1460,18 +1471,21 @@ csio_wr_set_sge(struct csio_hw *hw)
* and generate an interrupt when this occurs so we can recover.
*/
csio_set_reg_field(hw, SGE_DBFIFO_STATUS,
- HP_INT_THRESH(HP_INT_THRESH_MASK) |
- LP_INT_THRESH(LP_INT_THRESH_MASK),
- HP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH) |
- LP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH));
+ HP_INT_THRESH(HP_INT_THRESH_MASK) |
+ CSIO_HW_LP_INT_THRESH(hw, CSIO_HW_M_LP_INT_THRESH(hw)),
+ HP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH) |
+ CSIO_HW_LP_INT_THRESH(hw, CSIO_SGE_DBFIFO_INT_THRESH));
+
csio_set_reg_field(hw, SGE_DOORBELL_CONTROL, ENABLE_DROP,
ENABLE_DROP);
/* SGE_FL_BUFFER_SIZE0 is set up by csio_wr_fixup_host_params(). */
CSIO_SET_FLBUF_SIZE(hw, 1, CSIO_SGE_FLBUF_SIZE1);
- CSIO_SET_FLBUF_SIZE(hw, 2, CSIO_SGE_FLBUF_SIZE2);
- CSIO_SET_FLBUF_SIZE(hw, 3, CSIO_SGE_FLBUF_SIZE3);
+ csio_wr_reg32(hw, (CSIO_SGE_FLBUF_SIZE2 + sge->csio_fl_align - 1)
+ & ~(sge->csio_fl_align - 1), SGE_FL_BUFFER_SIZE2);
+ csio_wr_reg32(hw, (CSIO_SGE_FLBUF_SIZE3 + sge->csio_fl_align - 1)
+ & ~(sge->csio_fl_align - 1), SGE_FL_BUFFER_SIZE3);
CSIO_SET_FLBUF_SIZE(hw, 4, CSIO_SGE_FLBUF_SIZE4);
CSIO_SET_FLBUF_SIZE(hw, 5, CSIO_SGE_FLBUF_SIZE5);
CSIO_SET_FLBUF_SIZE(hw, 6, CSIO_SGE_FLBUF_SIZE6);
@@ -1522,22 +1536,24 @@ void
csio_wr_sge_init(struct csio_hw *hw)
{
/*
- * If we are master:
+ * If we are master and chip is not initialized:
* - If we plan to use the config file, we need to fixup some
* host specific registers, and read the rest of the SGE
* configuration.
* - If we dont plan to use the config file, we need to initialize
* SGE entirely, including fixing the host specific registers.
+ * If we are master and chip is initialized, just read and work off of
+ * the already initialized SGE values.
* If we arent the master, we are only allowed to read and work off of
* the already initialized SGE values.
*
* Therefore, before calling this function, we assume that the master-
- * ship of the card, and whether to use config file or not, have
- * already been decided. In other words, CSIO_HWF_USING_SOFT_PARAMS and
- * CSIO_HWF_MASTER should be set/unset.
+ * ship of the card, state and whether to use config file or not, have
+ * already been decided.
*/
if (csio_is_hw_master(hw)) {
- csio_wr_fixup_host_params(hw);
+ if (hw->fw_state != CSIO_DEV_STATE_INIT)
+ csio_wr_fixup_host_params(hw);
if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS)
csio_wr_get_sge(hw);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index f924b3c..5a9f842 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -20,6 +20,7 @@
#include <net/dst.h>
#include <linux/netdevice.h>
+#include "t4_regs.h"
#include "t4_msg.h"
#include "cxgb4.h"
#include "cxgb4_uld.h"
@@ -32,13 +33,12 @@ static unsigned int dbg_level;
#include "../libcxgbi.h"
#define DRV_MODULE_NAME "cxgb4i"
-#define DRV_MODULE_DESC "Chelsio T4 iSCSI Driver"
-#define DRV_MODULE_VERSION "0.9.1"
-#define DRV_MODULE_RELDATE "Aug. 2010"
+#define DRV_MODULE_DESC "Chelsio T4/T5 iSCSI Driver"
+#define DRV_MODULE_VERSION "0.9.4"
static char version[] =
DRV_MODULE_DESC " " DRV_MODULE_NAME
- " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ " v" DRV_MODULE_VERSION "\n";
MODULE_AUTHOR("Chelsio Communications, Inc.");
MODULE_DESCRIPTION(DRV_MODULE_DESC);
@@ -175,10 +175,56 @@ static inline int is_ofld_imm(const struct sk_buff *skb)
sizeof(struct fw_ofld_tx_data_wr));
}
+
+#define VLAN_NONE 0xfff
+#define FILTER_SEL_VLAN_NONE 0xffff
+#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
+#define FILTER_SEL_WIDTH_VIN_P_FC \
+ (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
+#define FILTER_SEL_WIDTH_TAG_P_FC \
+ (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
+#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
+
+static unsigned int select_ntuple(struct cxgbi_device *cdev,
+ struct l2t_entry *l2t)
+{
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ unsigned int ntuple = 0;
+ u32 viid;
+
+ switch (lldi->filt_mode) {
+
+ /* default filter mode */
+ case HW_TPL_FR_MT_PR_IV_P_FC:
+ if (l2t->vlan == VLAN_NONE)
+ ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
+ else {
+ ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
+ ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+ }
+ ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
+ FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+ break;
+ case HW_TPL_FR_MT_PR_OV_P_FC: {
+ viid = cxgb4_port_viid(l2t->neigh->dev);
+
+ ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
+ ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
+ ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
+ ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
+ FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+ break;
+ }
+ default:
+ break;
+ }
+ return ntuple;
+}
+
static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
struct l2t_entry *e)
{
- struct cpl_act_open_req *req;
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
unsigned long long opt0;
unsigned int opt2;
@@ -195,29 +241,58 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
opt2 = RX_CHANNEL(0) |
RSS_QUEUE_VALID |
- (1 << 20) | (1 << 22) |
+ (1 << 20) |
RSS_QUEUE(csk->rss_qid);
- set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
- req = (struct cpl_act_open_req *)skb->head;
+ if (is_t4(lldi->adapter_type)) {
+ struct cpl_act_open_req *req =
+ (struct cpl_act_open_req *)skb->head;
- INIT_TP_WR(req, 0);
- OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+ req = (struct cpl_act_open_req *)skb->head;
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
qid_atid));
- req->local_port = csk->saddr.sin_port;
- req->peer_port = csk->daddr.sin_port;
- req->local_ip = csk->saddr.sin_addr.s_addr;
- req->peer_ip = csk->daddr.sin_addr.s_addr;
- req->opt0 = cpu_to_be64(opt0);
- req->params = 0;
- req->opt2 = cpu_to_be32(opt2);
+ req->local_port = csk->saddr.sin_port;
+ req->peer_port = csk->daddr.sin_port;
+ req->local_ip = csk->saddr.sin_addr.s_addr;
+ req->peer_ip = csk->daddr.sin_addr.s_addr;
+ req->opt0 = cpu_to_be64(opt0);
+ req->params = cpu_to_be32(select_ntuple(csk->cdev, csk->l2t));
+ opt2 |= 1 << 22;
+ req->opt2 = cpu_to_be32(opt2);
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "csk 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n",
- csk, &req->local_ip, ntohs(req->local_port),
- &req->peer_ip, ntohs(req->peer_port),
- csk->atid, csk->rss_qid);
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk t4 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n",
+ csk, &req->local_ip, ntohs(req->local_port),
+ &req->peer_ip, ntohs(req->peer_port),
+ csk->atid, csk->rss_qid);
+ } else {
+ struct cpl_t5_act_open_req *req =
+ (struct cpl_t5_act_open_req *)skb->head;
+
+ req = (struct cpl_t5_act_open_req *)skb->head;
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+ qid_atid));
+ req->local_port = csk->saddr.sin_port;
+ req->peer_port = csk->daddr.sin_port;
+ req->local_ip = csk->saddr.sin_addr.s_addr;
+ req->peer_ip = csk->daddr.sin_addr.s_addr;
+ req->opt0 = cpu_to_be64(opt0);
+ req->params = cpu_to_be32(select_ntuple(csk->cdev, csk->l2t));
+ opt2 |= 1 << 31;
+ req->opt2 = cpu_to_be32(opt2);
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk t5 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n",
+ csk, &req->local_ip, ntohs(req->local_port),
+ &req->peer_ip, ntohs(req->peer_port),
+ csk->atid, csk->rss_qid);
+ }
+
+ set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
}
@@ -358,7 +433,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
return DIV_ROUND_UP(skb->len, 8);
flits = skb_transport_offset(skb) / 8;
cnt = skb_shinfo(skb)->nr_frags;
- if (skb->tail != skb->transport_header)
+ if (skb_tail_pointer(skb) != skb_transport_header(skb))
cnt++;
return flits + sgl_len(cnt);
}
@@ -632,6 +707,7 @@ static void csk_act_open_retry_timer(unsigned long data)
{
struct sk_buff *skb;
struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p,%u,0x%lx,%u.\n",
@@ -639,7 +715,10 @@ static void csk_act_open_retry_timer(unsigned long data)
cxgbi_sock_get(csk);
spin_lock_bh(&csk->lock);
- skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+ skb = alloc_wr(is_t4(lldi->adapter_type) ?
+ sizeof(struct cpl_act_open_req) :
+ sizeof(struct cpl_t5_act_open_req),
+ 0, GFP_ATOMIC);
if (!skb)
cxgbi_sock_fail_act_open(csk, -ENOMEM);
else {
@@ -871,7 +950,7 @@ static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb)
if (!csk->skb_ulp_lhdr) {
unsigned char *bhs;
- unsigned int hlen, dlen;
+ unsigned int hlen, dlen, plen;
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
"csk 0x%p,%u,0x%lx, tid %u, skb 0x%p header.\n",
@@ -890,11 +969,15 @@ static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb)
hlen = ntohs(cpl->len);
dlen = ntohl(*(unsigned int *)(bhs + 4)) & 0xFFFFFF;
- if ((hlen + dlen) != ISCSI_PDU_LEN(pdu_len_ddp) - 40) {
+ plen = ISCSI_PDU_LEN(pdu_len_ddp);
+ if (is_t4(lldi->adapter_type))
+ plen -= 40;
+
+ if ((hlen + dlen) != plen) {
pr_info("tid 0x%x, CPL_ISCSI_HDR, pdu len "
"mismatch %u != %u + %u, seq 0x%x.\n",
- csk->tid, ISCSI_PDU_LEN(pdu_len_ddp) - 40,
- hlen, dlen, cxgbi_skcb_tcp_seq(skb));
+ csk->tid, plen, hlen, dlen,
+ cxgbi_skcb_tcp_seq(skb));
goto abort_conn;
}
@@ -1154,7 +1237,10 @@ static int init_act_open(struct cxgbi_sock *csk)
}
cxgbi_sock_get(csk);
- skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+ skb = alloc_wr(is_t4(lldi->adapter_type) ?
+ sizeof(struct cpl_act_open_req) :
+ sizeof(struct cpl_t5_act_open_req),
+ 0, GFP_ATOMIC);
if (!skb)
goto rel_resource;
skb->sk = (struct sock *)csk;
@@ -1193,6 +1279,8 @@ rel_resource:
return -EINVAL;
}
+#define CPL_ISCSI_DATA 0xB2
+#define CPL_RX_ISCSI_DDP 0x49
cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
[CPL_ACT_ESTABLISH] = do_act_establish,
[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
@@ -1202,8 +1290,10 @@ cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
[CPL_CLOSE_CON_RPL] = do_close_con_rpl,
[CPL_FW4_ACK] = do_fw4_ack,
[CPL_ISCSI_HDR] = do_rx_iscsi_hdr,
+ [CPL_ISCSI_DATA] = do_rx_iscsi_hdr,
[CPL_SET_TCB_RPL] = do_set_tcb_rpl,
[CPL_RX_DATA_DDP] = do_rx_data_ddp,
+ [CPL_RX_ISCSI_DDP] = do_rx_data_ddp,
};
int cxgb4i_ofld_init(struct cxgbi_device *cdev)
@@ -1234,14 +1324,20 @@ int cxgb4i_ofld_init(struct cxgbi_device *cdev)
* functions to program the pagepod in h/w
*/
#define ULPMEM_IDATA_MAX_NPPODS 4 /* 256/PPOD_SIZE */
-static inline void ulp_mem_io_set_hdr(struct ulp_mem_io *req,
+static inline void ulp_mem_io_set_hdr(struct cxgb4_lld_info *lldi,
+ struct ulp_mem_io *req,
unsigned int wr_len, unsigned int dlen,
unsigned int pm_addr)
{
struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1);
INIT_ULPTX_WR(req, wr_len, 0, 0);
- req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1 << 23));
+ if (is_t4(lldi->adapter_type))
+ req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) |
+ (ULP_MEMIO_ORDER(1)));
+ else
+ req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) |
+ (V_T5_ULP_MEMIO_IMM(1)));
req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5));
req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5));
req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
@@ -1257,6 +1353,7 @@ static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id,
unsigned int gl_pidx)
{
struct cxgbi_ddp_info *ddp = cdev->ddp;
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
struct sk_buff *skb;
struct ulp_mem_io *req;
struct ulptx_idata *idata;
@@ -1276,7 +1373,7 @@ static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id,
req = (struct ulp_mem_io *)skb->head;
set_queue(skb, CPL_PRIORITY_CONTROL, NULL);
- ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr);
+ ulp_mem_io_set_hdr(lldi, req, wr_len, dlen, pm_addr);
idata = (struct ulptx_idata *)(req + 1);
ppod = (struct cxgbi_pagepod *)(idata + 1);
@@ -1564,6 +1661,7 @@ static int t4_uld_state_change(void *handle, enum cxgb4_state state)
break;
case CXGB4_STATE_DETACH:
pr_info("cdev 0x%p, DETACH.\n", cdev);
+ cxgbi_device_unregister(cdev);
break;
default:
pr_info("cdev 0x%p, unknown state %d.\n", cdev, state);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 13aeca3..694e13c 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -489,7 +489,7 @@ struct ParameterData {
int def; /* default value */
int safe; /* safe value */
};
-static struct ParameterData __devinitdata cfg_data[] = {
+static struct ParameterData cfg_data[] = {
{ /* adapter id */
CFG_PARAM_UNSET,
0,
@@ -574,7 +574,7 @@ MODULE_PARM_DESC(reset_delay, "Reset delay in seconds. Default 1 (0-180)");
* set_safe_settings - if the use_safe_settings option is set then
* set all values to the safe and slow values.
**/
-static void __devinit set_safe_settings(void)
+static void set_safe_settings(void)
{
if (use_safe_settings)
{
@@ -593,7 +593,7 @@ static void __devinit set_safe_settings(void)
* fix_settings - reset any boot parameters which are out of range
* back to the default values.
**/
-static void __devinit fix_settings(void)
+static void fix_settings(void)
{
int i;
@@ -620,7 +620,7 @@ static void __devinit fix_settings(void)
* Mapping from the eeprom delay index value (index into this array)
* to the number of actual seconds that the delay should be for.
*/
-static char __devinitdata eeprom_index_to_delay_map[] =
+static char eeprom_index_to_delay_map[] =
{ 1, 3, 5, 10, 16, 30, 60, 120 };
@@ -630,7 +630,7 @@ static char __devinitdata eeprom_index_to_delay_map[] =
*
* @eeprom: The eeprom structure in which we find the delay index to map.
**/
-static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom)
+static void eeprom_index_to_delay(struct NvRamType *eeprom)
{
eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time];
}
@@ -643,7 +643,7 @@ static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom)
*
* @delay: The delay, in seconds, to find the eeprom index for.
**/
-static int __devinit delay_to_eeprom_index(int delay)
+static int delay_to_eeprom_index(int delay)
{
u8 idx = 0;
while (idx < 7 && eeprom_index_to_delay_map[idx] < delay)
@@ -659,7 +659,7 @@ static int __devinit delay_to_eeprom_index(int delay)
*
* @eeprom: The eeprom data to override with command line options.
**/
-static void __devinit eeprom_override(struct NvRamType *eeprom)
+static void eeprom_override(struct NvRamType *eeprom)
{
u8 id;
@@ -3747,13 +3747,13 @@ static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb,
dcb->max_command = 1;
dcb->target_id = target;
dcb->target_lun = lun;
+ dcb->dev_mode = eeprom->target[target].cfg0;
#ifndef DC395x_NO_DISCONNECT
dcb->identify_msg =
IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun);
#else
dcb->identify_msg = IDENTIFY(0, lun);
#endif
- dcb->dev_mode = eeprom->target[target].cfg0;
dcb->inquiry7 = 0;
dcb->sync_mode = 0;
dcb->min_nego_period = clock_period[period_index];
@@ -3938,7 +3938,7 @@ static void dc395x_slave_destroy(struct scsi_device *scsi_device)
*
* @io_port: base I/O address
**/
-static void __devinit trms1040_wait_30us(unsigned long io_port)
+static void trms1040_wait_30us(unsigned long io_port)
{
/* ScsiPortStallExecution(30); wait 30 us */
outb(5, io_port + TRM_S1040_GEN_TIMER);
@@ -3955,7 +3955,7 @@ static void __devinit trms1040_wait_30us(unsigned long io_port)
* @cmd: SB + op code (command) to send
* @addr: address to send
**/
-static void __devinit trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
+static void trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
{
int i;
u8 send_data;
@@ -4000,7 +4000,7 @@ static void __devinit trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
* @addr: offset into EEPROM
* @byte: bytes to write
**/
-static void __devinit trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
+static void trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
{
int i;
u8 send_data;
@@ -4054,7 +4054,7 @@ static void __devinit trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
* @eeprom: the data to write
* @io_port: the base io port
**/
-static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
+static void trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
{
u8 *b_eeprom = (u8 *)eeprom;
u8 addr;
@@ -4094,7 +4094,7 @@ static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long
*
* Returns the byte read.
**/
-static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
+static u8 trms1040_get_data(unsigned long io_port, u8 addr)
{
int i;
u8 read_byte;
@@ -4132,7 +4132,7 @@ static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
* @eeprom: where to store the data
* @io_port: the base io port
**/
-static void __devinit trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
+static void trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
{
u8 *b_eeprom = (u8 *)eeprom;
u8 addr;
@@ -4162,7 +4162,7 @@ static void __devinit trms1040_read_all(struct NvRamType *eeprom, unsigned long
* @eeprom: caller allocated strcuture to read the eeprom data into
* @io_port: io port to read from
**/
-static void __devinit check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
+static void check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
{
u16 *w_eeprom = (u16 *)eeprom;
u16 w_addr;
@@ -4232,7 +4232,7 @@ static void __devinit check_eeprom(struct NvRamType *eeprom, unsigned long io_po
*
* @eeprom: The eeprom data strucutre to show details for.
**/
-static void __devinit print_eeprom_settings(struct NvRamType *eeprom)
+static void print_eeprom_settings(struct NvRamType *eeprom)
{
dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n",
eeprom->scsi_id,
@@ -4260,7 +4260,7 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
/*
* Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*)
* should never cross a page boundary */
-static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
+static int adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
{
const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1)
*SEGMENTX_LEN;
@@ -4306,7 +4306,7 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
*
* @acb: The adapter to print the information for.
**/
-static void __devinit adapter_print_config(struct AdapterCtlBlk *acb)
+static void adapter_print_config(struct AdapterCtlBlk *acb)
{
u8 bval;
@@ -4350,7 +4350,7 @@ static void __devinit adapter_print_config(struct AdapterCtlBlk *acb)
*
* @acb: The adapter to initialize.
**/
-static void __devinit adapter_init_params(struct AdapterCtlBlk *acb)
+static void adapter_init_params(struct AdapterCtlBlk *acb)
{
struct NvRamType *eeprom = &acb->eeprom;
int i;
@@ -4412,7 +4412,7 @@ static void __devinit adapter_init_params(struct AdapterCtlBlk *acb)
*
* @host: The scsi host instance to fill in the values for.
**/
-static void __devinit adapter_init_scsi_host(struct Scsi_Host *host)
+static void adapter_init_scsi_host(struct Scsi_Host *host)
{
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
struct NvRamType *eeprom = &acb->eeprom;
@@ -4453,7 +4453,7 @@ static void __devinit adapter_init_scsi_host(struct Scsi_Host *host)
*
* @acb: The adapter which we are to init.
**/
-static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb)
+static void adapter_init_chip(struct AdapterCtlBlk *acb)
{
struct NvRamType *eeprom = &acb->eeprom;
@@ -4506,8 +4506,8 @@ static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb)
* Returns 0 if the initialization succeeds, any other value on
* failure.
**/
-static int __devinit adapter_init(struct AdapterCtlBlk *acb,
- unsigned long io_port, u32 io_port_len, unsigned int irq)
+static int adapter_init(struct AdapterCtlBlk *acb, unsigned long io_port,
+ u32 io_port_len, unsigned int irq)
{
if (!request_region(io_port, io_port_len, DC395X_NAME)) {
dprintkl(KERN_ERR, "Failed to reserve IO region 0x%lx\n", io_port);
@@ -4616,26 +4616,21 @@ static void adapter_uninit(struct AdapterCtlBlk *acb)
#undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, args)
+#define SPRINTF(args...) seq_printf(m,##args)
#undef YESNO
#define YESNO(YN) \
if (YN) SPRINTF(" Yes ");\
else SPRINTF(" No ")
-static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
- char **start, off_t offset, int length, int inout)
+static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
int spd, spd1;
- char *pos = buffer;
struct DeviceCtlBlk *dcb;
unsigned long flags;
int dev;
- if (inout) /* Has data been written to the file ? */
- return -EPERM;
-
SPRINTF(DC395X_BANNER " PCI SCSI Host Adapter\n");
SPRINTF(" Driver Version " DC395X_VERSION "\n");
@@ -4735,22 +4730,15 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
SPRINTF("END\n");
}
- *start = buffer + offset;
DC395x_UNLOCK_IO(acb->scsi_host, flags);
-
- if (pos - buffer < offset)
- return 0;
- else if (pos - buffer - offset < length)
- return pos - buffer - offset;
- else
- return length;
+ return 0;
}
static struct scsi_host_template dc395x_driver_template = {
.module = THIS_MODULE,
.proc_name = DC395X_NAME,
- .proc_info = dc395x_proc_info,
+ .show_info = dc395x_show_info,
.name = DC395X_BANNER " " DC395X_VERSION,
.queuecommand = dc395x_queue_command,
.bios_param = dc395x_bios_param,
@@ -4794,8 +4782,7 @@ static void banner_display(void)
*
* Returns 0 on success, or an error code (-ve) on failure.
**/
-static int __devinit dc395x_init_one(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
struct Scsi_Host *scsi_host = NULL;
struct AdapterCtlBlk *acb = NULL;
@@ -4861,7 +4848,7 @@ fail:
*
* @dev: The PCI device to initialize.
**/
-static void __devexit dc395x_remove_one(struct pci_dev *dev)
+static void dc395x_remove_one(struct pci_dev *dev)
{
struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(scsi_host->hostdata);
@@ -4892,7 +4879,7 @@ static struct pci_driver dc395x_driver = {
.name = DC395X_NAME,
.id_table = dc395x_pci_table,
.probe = dc395x_init_one,
- .remove = __devexit_p(dc395x_remove_one),
+ .remove = dc395x_remove_one,
};
diff --git a/drivers/scsi/device_handler/Kconfig b/drivers/scsi/device_handler/Kconfig
index 6707025..69abd0a 100644
--- a/drivers/scsi/device_handler/Kconfig
+++ b/drivers/scsi/device_handler/Kconfig
@@ -32,8 +32,8 @@ config SCSI_DH_EMC
If you have a EMC CLARiiON select y. Otherwise, say N.
config SCSI_DH_ALUA
- tristate "SPC-3 ALUA Device Handler (EXPERIMENTAL)"
- depends on SCSI_DH && EXPERIMENTAL
+ tristate "SPC-3 ALUA Device Handler"
+ depends on SCSI_DH
help
SCSI Device handler for generic SPC-3 Asymmetric Logical Unit
Access (ALUA).
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 6f4d8e6..68adb89 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -232,13 +232,13 @@ static void stpg_endio(struct request *req, int error)
struct scsi_sense_hdr sense_hdr;
unsigned err = SCSI_DH_OK;
- if (error || host_byte(req->errors) != DID_OK ||
- msg_byte(req->errors) != COMMAND_COMPLETE) {
+ if (host_byte(req->errors) != DID_OK ||
+ msg_byte(req->errors) != COMMAND_COMPLETE) {
err = SCSI_DH_IO;
goto done;
}
- if (h->senselen > 0) {
+ if (req->sense_len > 0) {
err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
&sense_hdr);
if (!err) {
@@ -255,7 +255,9 @@ static void stpg_endio(struct request *req, int error)
ALUA_DH_NAME, sense_hdr.sense_key,
sense_hdr.asc, sense_hdr.ascq);
err = SCSI_DH_IO;
- }
+ } else if (error)
+ err = SCSI_DH_IO;
+
if (err == SCSI_DH_OK) {
h->state = TPGS_STATE_OPTIMIZED;
sdev_printk(KERN_INFO, h->sdev,
@@ -710,6 +712,10 @@ static int alua_set_params(struct scsi_device *sdev, const char *params)
return result;
}
+static uint optimize_stpg;
+module_param(optimize_stpg, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(optimize_stpg, "Allow use of a non-optimized path, rather than sending a STPG, when implicit TPGS is supported (0=No,1=Yes). Default is 0.");
+
/*
* alua_activate - activate a path
* @sdev: device on the path to be activated
@@ -731,6 +737,9 @@ static int alua_activate(struct scsi_device *sdev,
if (err != SCSI_DH_OK)
goto out;
+ if (optimize_stpg)
+ h->flags |= ALUA_OPTIMIZE_STPG;
+
if (h->tpgs & TPGS_MODE_EXPLICIT) {
switch (h->state) {
case TPGS_STATE_NONOPTIMIZED:
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 207352c..4b0dd8c 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -68,8 +68,8 @@ static struct scsi_host_template dmx3191d_driver_template = {
.use_clustering = DISABLE_CLUSTERING,
};
-static int __devinit dmx3191d_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int dmx3191d_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct Scsi_Host *shost;
unsigned long io;
@@ -123,7 +123,7 @@ static int __devinit dmx3191d_probe_one(struct pci_dev *pdev,
return error;
}
-static void __devexit dmx3191d_remove_one(struct pci_dev *pdev)
+static void dmx3191d_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -150,7 +150,7 @@ static struct pci_driver dmx3191d_pci_driver = {
.name = DMX3191D_DRIVER_NAME,
.id_table = dmx3191d_pci_tbl,
.probe = dmx3191d_probe_one,
- .remove = __devexit_p(dmx3191d_remove_one),
+ .remove = dmx3191d_remove_one,
};
static int __init dmx3191d_init(void)
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index b4f6c9a..19e1b42 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -553,36 +553,14 @@ static const char *adpt_info(struct Scsi_Host *host)
return (char *) (pHba->detail);
}
-static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host)
{
struct adpt_device* d;
int id;
int chan;
- int len = 0;
- int begin = 0;
- int pos = 0;
adpt_hba* pHba;
int unit;
- *start = buffer;
- if (inout == TRUE) {
- /*
- * The user has done a write and wants us to take the
- * data in the buffer and do something with it.
- * proc_scsiwrite calls us with inout = 1
- *
- * Read data from buffer (writing to us) - NOT SUPPORTED
- */
- return -EINVAL;
- }
-
- /*
- * inout = 0 means the user has done a read and wants information
- * returned, so we write information about the cards into the buffer
- * proc_scsiread() calls us with inout = 0
- */
-
// Find HBA (host bus adapter) we are looking for
mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
@@ -596,86 +574,30 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of
}
host = pHba->host;
- len = sprintf(buffer , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
- len += sprintf(buffer+len, "%s\n", pHba->detail);
- len += sprintf(buffer+len, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n",
+ seq_printf(m, "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION);
+ seq_printf(m, "%s\n", pHba->detail);
+ seq_printf(m, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n",
pHba->host->host_no, pHba->name, host->irq);
- len += sprintf(buffer+len, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n",
+ seq_printf(m, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n",
host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize);
- pos = begin + len;
-
- /* CHECKPOINT */
- if(pos > offset + length) {
- goto stop_output;
- }
- if(pos <= offset) {
- /*
- * If we haven't even written to where we last left
- * off (the last time we were called), reset the
- * beginning pointer.
- */
- len = 0;
- begin = pos;
- }
- len += sprintf(buffer+len, "Devices:\n");
+ seq_printf(m, "Devices:\n");
for(chan = 0; chan < MAX_CHANNEL; chan++) {
for(id = 0; id < MAX_ID; id++) {
d = pHba->channel[chan].device[id];
- while(d){
- len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor);
- len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev);
- pos = begin + len;
-
-
- /* CHECKPOINT */
- if(pos > offset + length) {
- goto stop_output;
- }
- if(pos <= offset) {
- len = 0;
- begin = pos;
- }
+ while(d) {
+ seq_printf(m,"\t%-24.24s", d->pScsi_dev->vendor);
+ seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev);
unit = d->pI2o_dev->lct_data.tid;
- len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n",
+ seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n",
unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun,
scsi_device_online(d->pScsi_dev)? "online":"offline");
- pos = begin + len;
-
- /* CHECKPOINT */
- if(pos > offset + length) {
- goto stop_output;
- }
- if(pos <= offset) {
- len = 0;
- begin = pos;
- }
-
d = d->next_lun;
}
}
}
-
- /*
- * begin is where we last checked our position with regards to offset
- * begin is always less than offset. len is relative to begin. It
- * is the number of bytes written past begin
- *
- */
-stop_output:
- /* stop the output and calculate the correct length */
- *(buffer + len) = '\0';
-
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin);
- if(len > length) {
- len = length;
- } else if(len < 0){
- len = 0;
- **start = '\0';
- }
- return len;
+ return 0;
}
/*
@@ -2161,7 +2083,7 @@ static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
struct inode *inode;
long ret;
- inode = file->f_dentry->d_inode;
+ inode = file_inode(file);
mutex_lock(&adpt_mutex);
ret = adpt_ioctl(inode, file, cmd, arg);
@@ -2177,7 +2099,7 @@ static long compat_adpt_ioctl(struct file *file,
struct inode *inode;
long ret;
- inode = file->f_dentry->d_inode;
+ inode = file_inode(file);
mutex_lock(&adpt_mutex);
@@ -3639,7 +3561,7 @@ static struct scsi_host_template driver_template = {
.module = THIS_MODULE,
.name = "dpt_i2o",
.proc_name = "dpt_i2o",
- .proc_info = adpt_proc_info,
+ .show_info = adpt_show_info,
.info = adpt_info,
.queuecommand = adpt_queue,
.eh_abort_handler = adpt_abort,
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 4b11bb0..d01f016 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -216,7 +216,8 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
int sig, count;
tpnt->proc_name = "dtc3x80";
- tpnt->proc_info = &dtc_proc_info;
+ tpnt->show_info = dtc_show_info;
+ tpnt->write_info = dtc_write_info;
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
addr = 0;
diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h
index cdc6212..92d7cfc 100644
--- a/drivers/scsi/dtc.h
+++ b/drivers/scsi/dtc.h
@@ -88,7 +88,8 @@ static int dtc_bus_reset(Scsi_Cmnd *);
#define NCR5380_queue_command dtc_queue_command
#define NCR5380_abort dtc_abort
#define NCR5380_bus_reset dtc_bus_reset
-#define NCR5380_proc_info dtc_proc_info
+#define NCR5380_show_info dtc_show_info
+#define NCR5380_write_info dtc_write_info
/* 15 12 11 10
1001 1100 0000 0000 */
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index d5f8362..356def4 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -92,58 +92,22 @@ static unsigned long queue_counter;
static struct scsi_host_template driver_template;
-/*
- * eata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the
- * variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file
- * from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer
- * else number of bytes in the buffer
- */
-static int eata_pio_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
- int length, int rw)
+static int eata_pio_show_info(struct seq_file *m, struct Scsi_Host *shost)
{
- int len = 0;
- off_t begin = 0, pos = 0;
-
- if (rw)
- return -ENOSYS;
-
- len += sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: "
+ seq_printf(m, "EATA (Extended Attachment) PIO driver version: "
"%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB);
- len += sprintf(buffer + len, "queued commands: %10ld\n"
+ seq_printf(m, "queued commands: %10ld\n"
"processed interrupts:%10ld\n", queue_counter, int_counter);
- len += sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n",
+ seq_printf(m, "\nscsi%-2d: HBA %.10s\n",
shost->host_no, SD(shost)->name);
- len += sprintf(buffer + len, "Firmware revision: v%s\n",
+ seq_printf(m, "Firmware revision: v%s\n",
SD(shost)->revision);
- len += sprintf(buffer + len, "IO: PIO\n");
- len += sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base);
- len += sprintf(buffer + len, "Host Bus: %s\n",
+ seq_printf(m, "IO: PIO\n");
+ seq_printf(m, "Base IO : %#.4x\n", (u32) shost->base);
+ seq_printf(m, "Host Bus: %s\n",
(SD(shost)->bustype == 'P')?"PCI ":
(SD(shost)->bustype == 'E')?"EISA":"ISA ");
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length)
- goto stop_output;
-
-stop_output:
- DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin); /* Start slop */
- if (len > length)
- len = length; /* Ending slop */
- DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len));
-
- return len;
+ return 0;
}
static int eata_pio_release(struct Scsi_Host *sh)
@@ -985,7 +949,7 @@ static int eata_pio_detect(struct scsi_host_template *tpnt)
static struct scsi_host_template driver_template = {
.proc_name = "eata_pio",
.name = "EATA (Extended Attachment) PIO driver",
- .proc_info = eata_pio_proc_info,
+ .show_info = eata_pio_show_info,
.detect = eata_pio_detect,
.release = eata_pio_release,
.queuecommand = eata_pio_queue,
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 666b7ac..07453bb 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -82,11 +82,11 @@ static int fcoe_rcv(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
static int fcoe_percpu_receive_thread(void *);
static void fcoe_percpu_clean(struct fc_lport *);
-static int fcoe_link_speed_update(struct fc_lport *);
static int fcoe_link_ok(struct fc_lport *);
static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
static int fcoe_hostlist_add(const struct fc_lport *);
+static void fcoe_hostlist_del(const struct fc_lport *);
static int fcoe_device_notification(struct notifier_block *, ulong, void *);
static void fcoe_dev_setup(void);
@@ -117,6 +117,11 @@ static int fcoe_destroy(struct net_device *netdev);
static int fcoe_enable(struct net_device *netdev);
static int fcoe_disable(struct net_device *netdev);
+/* fcoe_syfs control interface handlers */
+static int fcoe_ctlr_alloc(struct net_device *netdev);
+static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev);
+
+
static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
u32 did, struct fc_frame *,
unsigned int op,
@@ -126,8 +131,6 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
void *, u32 timeout);
static void fcoe_recv_frame(struct sk_buff *skb);
-static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
-
/* notification function for packets from net device */
static struct notifier_block fcoe_notifier = {
.notifier_call = fcoe_device_notification,
@@ -151,11 +154,11 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled);
static int fcoe_vport_disable(struct fc_vport *, bool disable);
static void fcoe_set_vport_symbolic_name(struct fc_vport *);
static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
-static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *);
static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *);
static struct fcoe_sysfs_function_template fcoe_sysfs_templ = {
- .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode,
+ .set_fcoe_ctlr_mode = fcoe_ctlr_set_fip_mode,
+ .set_fcoe_ctlr_enabled = fcoe_ctlr_enabled,
.get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb,
.get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb,
.get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb,
@@ -487,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
- struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
rtnl_lock();
if (!fcoe->removed)
@@ -498,7 +500,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
/* tear-down the FCoE controller */
fcoe_ctlr_destroy(fip);
scsi_host_put(fip->lp->host);
- fcoe_ctlr_device_delete(ctlr_dev);
dev_put(netdev);
module_put(THIS_MODULE);
}
@@ -773,7 +774,6 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev)
struct fcoe_port *port;
struct net_device *realdev;
int rc;
- struct netdev_fcoe_hbainfo fdmi;
port = lport_priv(lport);
fcoe = port->priv;
@@ -787,9 +787,13 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev)
return;
if (realdev->netdev_ops->ndo_fcoe_get_hbainfo) {
- memset(&fdmi, 0, sizeof(fdmi));
+ struct netdev_fcoe_hbainfo *fdmi;
+ fdmi = kzalloc(sizeof(*fdmi), GFP_KERNEL);
+ if (!fdmi)
+ return;
+
rc = realdev->netdev_ops->ndo_fcoe_get_hbainfo(realdev,
- &fdmi);
+ fdmi);
if (rc) {
printk(KERN_INFO "fcoe: Failed to retrieve FDMI "
"information from netdev.\n");
@@ -799,38 +803,39 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev)
snprintf(fc_host_serial_number(lport->host),
FC_SERIAL_NUMBER_SIZE,
"%s",
- fdmi.serial_number);
+ fdmi->serial_number);
snprintf(fc_host_manufacturer(lport->host),
FC_SERIAL_NUMBER_SIZE,
"%s",
- fdmi.manufacturer);
+ fdmi->manufacturer);
snprintf(fc_host_model(lport->host),
FC_SYMBOLIC_NAME_SIZE,
"%s",
- fdmi.model);
+ fdmi->model);
snprintf(fc_host_model_description(lport->host),
FC_SYMBOLIC_NAME_SIZE,
"%s",
- fdmi.model_description);
+ fdmi->model_description);
snprintf(fc_host_hardware_version(lport->host),
FC_VERSION_STRING_SIZE,
"%s",
- fdmi.hardware_version);
+ fdmi->hardware_version);
snprintf(fc_host_driver_version(lport->host),
FC_VERSION_STRING_SIZE,
"%s",
- fdmi.driver_version);
+ fdmi->driver_version);
snprintf(fc_host_optionrom_version(lport->host),
FC_VERSION_STRING_SIZE,
"%s",
- fdmi.optionrom_version);
+ fdmi->optionrom_version);
snprintf(fc_host_firmware_version(lport->host),
FC_VERSION_STRING_SIZE,
"%s",
- fdmi.firmware_version);
+ fdmi->firmware_version);
/* Enable FDMI lport states */
lport->fdmi_enabled = 1;
+ kfree(fdmi);
} else {
lport->fdmi_enabled = 0;
printk(KERN_INFO "fcoe: No FDMI support.\n");
@@ -1112,10 +1117,17 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
port = lport_priv(lport);
port->lport = lport;
port->priv = fcoe;
+ port->get_netdev = fcoe_netdev;
port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH;
port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH;
INIT_WORK(&port->destroy_work, fcoe_destroy_work);
+ /*
+ * Need to add the lport to the hostlist
+ * so we catch NETDEV_CHANGE events.
+ */
+ fcoe_hostlist_add(lport);
+
/* configure a fc_lport including the exchange manager */
rc = fcoe_lport_config(lport);
if (rc) {
@@ -1187,6 +1199,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
out_lp_destroy:
fc_exch_mgr_free(lport);
out_host_put:
+ fcoe_hostlist_del(lport);
scsi_host_put(lport->host);
out:
return ERR_PTR(rc);
@@ -1646,10 +1659,13 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
skb->priority = fcoe->priority;
if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN &&
- fcoe->realdev->features & NETIF_F_HW_VLAN_TX) {
- skb->vlan_tci = VLAN_TAG_PRESENT |
- vlan_dev_vlan_id(fcoe->netdev);
+ fcoe->realdev->features & NETIF_F_HW_VLAN_CTAG_TX) {
+ /* must set skb->dev before calling vlan_put_tag */
skb->dev = fcoe->realdev;
+ skb = __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ vlan_dev_vlan_id(fcoe->netdev));
+ if (!skb)
+ return -ENOMEM;
} else
skb->dev = fcoe->netdev;
@@ -1964,8 +1980,9 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier,
static int fcoe_device_notification(struct notifier_block *notifier,
ulong event, void *ptr)
{
+ struct fcoe_ctlr_device *cdev;
struct fc_lport *lport = NULL;
- struct net_device *netdev = ptr;
+ struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
struct fcoe_ctlr *ctlr;
struct fcoe_interface *fcoe;
struct fcoe_port *port;
@@ -2020,13 +2037,29 @@ static int fcoe_device_notification(struct notifier_block *notifier,
fcoe_link_speed_update(lport);
- if (link_possible && !fcoe_link_ok(lport))
- fcoe_ctlr_link_up(ctlr);
- else if (fcoe_ctlr_link_down(ctlr)) {
- stats = per_cpu_ptr(lport->stats, get_cpu());
- stats->LinkFailureCount++;
- put_cpu();
- fcoe_clean_pending_queue(lport);
+ cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
+
+ if (link_possible && !fcoe_link_ok(lport)) {
+ switch (cdev->enabled) {
+ case FCOE_CTLR_DISABLED:
+ pr_info("Link up while interface is disabled.\n");
+ break;
+ case FCOE_CTLR_ENABLED:
+ case FCOE_CTLR_UNUSED:
+ fcoe_ctlr_link_up(ctlr);
+ };
+ } else if (fcoe_ctlr_link_down(ctlr)) {
+ switch (cdev->enabled) {
+ case FCOE_CTLR_DISABLED:
+ pr_info("Link down while interface is disabled.\n");
+ break;
+ case FCOE_CTLR_ENABLED:
+ case FCOE_CTLR_UNUSED:
+ stats = per_cpu_ptr(lport->stats, get_cpu());
+ stats->LinkFailureCount++;
+ put_cpu();
+ fcoe_clean_pending_queue(lport);
+ };
}
out:
return rc;
@@ -2039,6 +2072,8 @@ out:
* Called from fcoe transport.
*
* Returns: 0 for success
+ *
+ * Deprecated: use fcoe_ctlr_enabled()
*/
static int fcoe_disable(struct net_device *netdev)
{
@@ -2098,6 +2133,33 @@ out:
}
/**
+ * fcoe_ctlr_enabled() - Enable or disable an FCoE Controller
+ * @cdev: The FCoE Controller that is being enabled or disabled
+ *
+ * fcoe_sysfs will ensure that the state of 'enabled' has
+ * changed, so no checking is necessary here. This routine simply
+ * calls fcoe_enable or fcoe_disable, both of which are deprecated.
+ * When those routines are removed the functionality can be merged
+ * here.
+ */
+static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev)
+{
+ struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev);
+ struct fc_lport *lport = ctlr->lp;
+ struct net_device *netdev = fcoe_netdev(lport);
+
+ switch (cdev->enabled) {
+ case FCOE_CTLR_ENABLED:
+ return fcoe_enable(netdev);
+ case FCOE_CTLR_DISABLED:
+ return fcoe_disable(netdev);
+ case FCOE_CTLR_UNUSED:
+ default:
+ return -ENOTSUPP;
+ };
+}
+
+/**
* fcoe_destroy() - Destroy a FCoE interface
* @netdev : The net_device object the Ethernet interface to create on
*
@@ -2137,17 +2199,47 @@ out_nodev:
*/
static void fcoe_destroy_work(struct work_struct *work)
{
+ struct fcoe_ctlr_device *cdev;
+ struct fcoe_ctlr *ctlr;
struct fcoe_port *port;
struct fcoe_interface *fcoe;
+ struct Scsi_Host *shost;
+ struct fc_host_attrs *fc_host;
+ unsigned long flags;
+ struct fc_vport *vport;
+ struct fc_vport *next_vport;
port = container_of(work, struct fcoe_port, destroy_work);
+ shost = port->lport->host;
+ fc_host = shost_to_fc_host(shost);
+
+ /* Loop through all the vports and mark them for deletion */
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) {
+ if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) {
+ continue;
+ } else {
+ vport->flags |= FC_VPORT_DELETING;
+ queue_work(fc_host_work_q(shost),
+ &vport->vport_delete_work);
+ }
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ flush_workqueue(fc_host_work_q(shost));
+
mutex_lock(&fcoe_config_mutex);
fcoe = port->priv;
+ ctlr = fcoe_to_ctlr(fcoe);
+ cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
+
fcoe_if_destroy(port->lport);
fcoe_interface_cleanup(fcoe);
mutex_unlock(&fcoe_config_mutex);
+
+ fcoe_ctlr_device_delete(cdev);
}
/**
@@ -2204,16 +2296,26 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
#endif
}
+enum fcoe_create_link_state {
+ FCOE_CREATE_LINK_DOWN,
+ FCOE_CREATE_LINK_UP,
+};
+
/**
- * fcoe_create() - Create a fcoe interface
- * @netdev : The net_device object the Ethernet interface to create on
- * @fip_mode: The FIP mode for this creation
+ * _fcoe_create() - (internal) Create a fcoe interface
+ * @netdev : The net_device object the Ethernet interface to create on
+ * @fip_mode: The FIP mode for this creation
+ * @link_state: The ctlr link state on creation
*
- * Called from fcoe transport
+ * Called from either the libfcoe 'create' module parameter
+ * via fcoe_create or from fcoe_syfs's ctlr_create file.
*
- * Returns: 0 for success
+ * libfcoe's 'create' module parameter is deprecated so some
+ * consolidation of code can be done when that interface is
+ * removed.
*/
-static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
+static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
+ enum fcoe_create_link_state link_state)
{
int rc = 0;
struct fcoe_ctlr_device *ctlr_dev;
@@ -2245,7 +2347,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
rc = -EIO;
rtnl_unlock();
fcoe_interface_cleanup(fcoe);
- goto out_nortnl;
+ mutex_unlock(&fcoe_config_mutex);
+ fcoe_ctlr_device_delete(ctlr_dev);
+ goto out;
}
/* Make this the "master" N_Port */
@@ -2254,13 +2358,29 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
/* setup DCB priority attributes. */
fcoe_dcb_create(fcoe);
- /* add to lports list */
- fcoe_hostlist_add(lport);
-
/* start FIP Discovery and FLOGI */
lport->boot_time = jiffies;
fc_fabric_login(lport);
- if (!fcoe_link_ok(lport)) {
+
+ /*
+ * If the fcoe_ctlr_device is to be set to DISABLED
+ * it must be done after the lport is added to the
+ * hostlist, but before the rtnl_lock is released.
+ * This is because the rtnl_lock protects the
+ * hostlist that fcoe_device_notification uses. If
+ * the FCoE Controller is intended to be created
+ * DISABLED then 'enabled' needs to be considered
+ * handling link events. 'enabled' must be set
+ * before the lport can be found in the hostlist
+ * when a link up event is received.
+ */
+ if (link_state == FCOE_CREATE_LINK_UP)
+ ctlr_dev->enabled = FCOE_CTLR_ENABLED;
+ else
+ ctlr_dev->enabled = FCOE_CTLR_DISABLED;
+
+ if (link_state == FCOE_CREATE_LINK_UP &&
+ !fcoe_link_ok(lport)) {
rtnl_unlock();
fcoe_ctlr_link_up(ctlr);
mutex_unlock(&fcoe_config_mutex);
@@ -2269,43 +2389,40 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
out_nodev:
rtnl_unlock();
-out_nortnl:
mutex_unlock(&fcoe_config_mutex);
+out:
return rc;
}
/**
- * fcoe_link_speed_update() - Update the supported and actual link speeds
- * @lport: The local port to update speeds for
+ * fcoe_create() - Create a fcoe interface
+ * @netdev : The net_device object the Ethernet interface to create on
+ * @fip_mode: The FIP mode for this creation
+ *
+ * Called from fcoe transport
*
- * Returns: 0 if the ethtool query was successful
- * -1 if the ethtool query failed
+ * Returns: 0 for success
*/
-static int fcoe_link_speed_update(struct fc_lport *lport)
+static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
{
- struct net_device *netdev = fcoe_netdev(lport);
- struct ethtool_cmd ecmd;
-
- if (!__ethtool_get_settings(netdev, &ecmd)) {
- lport->link_supported_speeds &=
- ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
- if (ecmd.supported & (SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full))
- lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
- if (ecmd.supported & SUPPORTED_10000baseT_Full)
- lport->link_supported_speeds |=
- FC_PORTSPEED_10GBIT;
- switch (ethtool_cmd_speed(&ecmd)) {
- case SPEED_1000:
- lport->link_speed = FC_PORTSPEED_1GBIT;
- break;
- case SPEED_10000:
- lport->link_speed = FC_PORTSPEED_10GBIT;
- break;
- }
- return 0;
- }
- return -1;
+ return _fcoe_create(netdev, fip_mode, FCOE_CREATE_LINK_UP);
+}
+
+/**
+ * fcoe_ctlr_alloc() - Allocate a fcoe interface from fcoe_sysfs
+ * @netdev: The net_device to be used by the allocated FCoE Controller
+ *
+ * This routine is called from fcoe_sysfs. It will start the fcoe_ctlr
+ * in a link_down state. The allows the user an opportunity to configure
+ * the FCoE Controller from sysfs before enabling the FCoE Controller.
+ *
+ * Creating in with this routine starts the FCoE Controller in Fabric
+ * mode. The user can change to VN2VN or another mode before enabling.
+ */
+static int fcoe_ctlr_alloc(struct net_device *netdev)
+{
+ return _fcoe_create(netdev, FIP_MODE_FABRIC,
+ FCOE_CREATE_LINK_DOWN);
}
/**
@@ -2375,10 +2492,13 @@ static int fcoe_reset(struct Scsi_Host *shost)
struct fcoe_port *port = lport_priv(lport);
struct fcoe_interface *fcoe = port->priv;
struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe);
+ struct fcoe_ctlr_device *cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
fcoe_ctlr_link_down(ctlr);
fcoe_clean_pending_queue(ctlr->lp);
- if (!fcoe_link_ok(ctlr->lp))
+
+ if (cdev->enabled != FCOE_CTLR_DISABLED &&
+ !fcoe_link_ok(ctlr->lp))
fcoe_ctlr_link_up(ctlr);
return 0;
}
@@ -2445,12 +2565,31 @@ static int fcoe_hostlist_add(const struct fc_lport *lport)
return 0;
}
+/**
+ * fcoe_hostlist_del() - Remove the FCoE interface identified by a local
+ * port to the hostlist
+ * @lport: The local port that identifies the FCoE interface to be added
+ *
+ * Locking: must be called with the RTNL mutex held
+ *
+ */
+static void fcoe_hostlist_del(const struct fc_lport *lport)
+{
+ struct fcoe_interface *fcoe;
+ struct fcoe_port *port;
+
+ port = lport_priv(lport);
+ fcoe = port->priv;
+ list_del(&fcoe->list);
+ return;
+}
static struct fcoe_transport fcoe_sw_transport = {
.name = {FCOE_TRANSPORT_DEFAULT},
.attached = false,
.list = LIST_HEAD_INIT(fcoe_sw_transport.list),
.match = fcoe_match,
+ .alloc = fcoe_ctlr_alloc,
.create = fcoe_create,
.destroy = fcoe_destroy,
.enable = fcoe_enable,
@@ -2534,9 +2673,9 @@ static void __exit fcoe_exit(void)
/* releases the associated fcoe hosts */
rtnl_lock();
list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) {
- list_del(&fcoe->list);
ctlr = fcoe_to_ctlr(fcoe);
port = lport_priv(ctlr->lp);
+ fcoe_hostlist_del(port->lport);
queue_work(fcoe_wq, &port->destroy_work);
}
rtnl_unlock();
@@ -2776,43 +2915,6 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport)
NULL, NULL, 3 * lport->r_a_tov);
}
-/**
- * fcoe_get_lesb() - Fill the FCoE Link Error Status Block
- * @lport: the local port
- * @fc_lesb: the link error status block
- */
-static void fcoe_get_lesb(struct fc_lport *lport,
- struct fc_els_lesb *fc_lesb)
-{
- struct net_device *netdev = fcoe_netdev(lport);
-
- __fcoe_get_lesb(lport, fc_lesb, netdev);
-}
-
-static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
-{
- struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
- struct net_device *netdev = fcoe_netdev(fip->lp);
- struct fcoe_fc_els_lesb *fcoe_lesb;
- struct fc_els_lesb fc_lesb;
-
- __fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
- fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
-
- ctlr_dev->lesb.lesb_link_fail =
- ntohl(fcoe_lesb->lesb_link_fail);
- ctlr_dev->lesb.lesb_vlink_fail =
- ntohl(fcoe_lesb->lesb_vlink_fail);
- ctlr_dev->lesb.lesb_miss_fka =
- ntohl(fcoe_lesb->lesb_miss_fka);
- ctlr_dev->lesb.lesb_symb_err =
- ntohl(fcoe_lesb->lesb_symb_err);
- ctlr_dev->lesb.lesb_err_block =
- ntohl(fcoe_lesb->lesb_err_block);
- ctlr_dev->lesb.lesb_fcs_error =
- ntohl(fcoe_lesb->lesb_fcs_error);
-}
-
static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
{
struct fcoe_ctlr_device *ctlr_dev =
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index b42dc32c..2b53672 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -55,12 +55,12 @@ do { \
#define FCOE_DBG(fmt, args...) \
FCOE_CHECK_LOGGING(FCOE_LOGGING, \
- printk(KERN_INFO "fcoe: " fmt, ##args);)
+ pr_info("fcoe: " fmt, ##args);)
#define FCOE_NETDEV_DBG(netdev, fmt, args...) \
FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING, \
- printk(KERN_INFO "fcoe: %s: " fmt, \
- netdev->name, ##args);)
+ pr_info("fcoe: %s: " fmt, \
+ netdev->name, ##args);)
/**
* struct fcoe_interface - A FCoE interface
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 4a909d7..203415e 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -1291,8 +1291,16 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
- if (!fcf || !lport->port_id)
+ if (!fcf || !lport->port_id) {
+ /*
+ * We are yet to select best FCF, but we got CVL in the
+ * meantime. reset the ctlr and let it rediscover the FCF
+ */
+ mutex_lock(&fip->ctlr_mutex);
+ fcoe_ctlr_reset(fip);
+ mutex_unlock(&fip->ctlr_mutex);
return;
+ }
/*
* mask of required descriptors. Validating each one clears its bit.
@@ -1540,9 +1548,6 @@ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
{
struct fcoe_fcf *fcf;
struct fcoe_fcf *best = fip->sel_fcf;
- struct fcoe_fcf *first;
-
- first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
list_for_each_entry(fcf, &fip->fcfs, list) {
LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
@@ -1551,15 +1556,6 @@ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
fcf->flogi_sent, fcf->pri);
- if (fcf->fabric_name != first->fabric_name ||
- fcf->vfid != first->vfid ||
- fcf->fc_map != first->fc_map) {
- LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
- "or FC-MAP\n");
- return NULL;
- }
- if (fcf->flogi_sent)
- continue;
if (!fcoe_ctlr_fcf_usable(fcf)) {
LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
"map %x %svalid %savailable\n",
@@ -1571,6 +1567,13 @@ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
}
if (!best || fcf->pri < best->pri || best->flogi_sent)
best = fcf;
+ if (fcf->fabric_name != best->fabric_name ||
+ fcf->vfid != best->vfid ||
+ fcf->fc_map != best->fc_map) {
+ LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
+ "or FC-MAP\n");
+ return NULL;
+ }
}
fip->sel_fcf = best;
if (best) {
@@ -2087,7 +2090,11 @@ static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = {
*/
static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
{
+ struct fc_rport_priv *rdata;
+
mutex_lock(&lport->disc.disc_mutex);
+ list_for_each_entry_rcu(rdata, &lport->disc.rports, peers)
+ lport->tt.rport_logoff(rdata);
lport->disc.disc_callback = NULL;
mutex_unlock(&lport->disc.disc_mutex);
}
@@ -2153,7 +2160,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
fip->probe_tries++;
- wait = random32() % FIP_VN_PROBE_WAIT;
+ wait = prandom_u32() % FIP_VN_PROBE_WAIT;
} else
wait = FIP_VN_RLIM_INT;
mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
@@ -2786,7 +2793,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
fcoe_all_vn2vn, 0);
fip->port_ka_time = jiffies +
msecs_to_jiffies(FIP_VN_BEACON_INT +
- (random32() % FIP_VN_BEACON_FUZZ));
+ (prandom_u32() % FIP_VN_BEACON_FUZZ));
}
if (time_before(fip->port_ka_time, next_time))
next_time = fip->port_ka_time;
@@ -2807,6 +2814,47 @@ unlock:
}
/**
+ * fcoe_ctlr_mode_set() - Set or reset the ctlr's mode
+ * @lport: The local port to be (re)configured
+ * @fip: The FCoE controller whose mode is changing
+ * @fip_mode: The new fip mode
+ *
+ * Note that the we shouldn't be changing the libfc discovery settings
+ * (fc_disc_config) while an lport is going through the libfc state
+ * machine. The mode can only be changed when a fcoe_ctlr device is
+ * disabled, so that should ensure that this routine is only called
+ * when nothing is happening.
+ */
+void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip,
+ enum fip_state fip_mode)
+{
+ void *priv;
+
+ WARN_ON(lport->state != LPORT_ST_RESET &&
+ lport->state != LPORT_ST_DISABLED);
+
+ if (fip_mode == FIP_MODE_VN2VN) {
+ lport->rport_priv_size = sizeof(struct fcoe_rport);
+ lport->point_to_multipoint = 1;
+ lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
+ lport->tt.disc_start = fcoe_ctlr_disc_start;
+ lport->tt.disc_stop = fcoe_ctlr_disc_stop;
+ lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
+ priv = fip;
+ } else {
+ lport->rport_priv_size = 0;
+ lport->point_to_multipoint = 0;
+ lport->tt.disc_recv_req = NULL;
+ lport->tt.disc_start = NULL;
+ lport->tt.disc_stop = NULL;
+ lport->tt.disc_stop_final = NULL;
+ priv = lport;
+ }
+
+ fc_disc_config(lport, priv);
+}
+
+/**
* fcoe_libfc_config() - Sets up libfc related properties for local port
* @lport: The local port to configure libfc for
* @fip: The FCoE controller in use by the local port
@@ -2825,21 +2873,9 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
fc_exch_init(lport);
fc_elsct_init(lport);
fc_lport_init(lport);
- if (fip->mode == FIP_MODE_VN2VN)
- lport->rport_priv_size = sizeof(struct fcoe_rport);
fc_rport_init(lport);
- if (fip->mode == FIP_MODE_VN2VN) {
- lport->point_to_multipoint = 1;
- lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
- lport->tt.disc_start = fcoe_ctlr_disc_start;
- lport->tt.disc_stop = fcoe_ctlr_disc_stop;
- lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
- mutex_init(&lport->disc.disc_mutex);
- INIT_LIST_HEAD(&lport->disc.rports);
- lport->disc.priv = fip;
- } else {
- fc_disc_init(lport);
- }
+ fc_disc_init(lport);
+ fcoe_ctlr_mode_set(lport, fip, fip->mode);
return 0;
}
EXPORT_SYMBOL_GPL(fcoe_libfc_config);
@@ -2864,22 +2900,24 @@ void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev)
}
EXPORT_SYMBOL(fcoe_fcf_get_selected);
-void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
+void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
{
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+ struct fc_lport *lport = ctlr->lp;
mutex_lock(&ctlr->ctlr_mutex);
- switch (ctlr->mode) {
- case FIP_MODE_FABRIC:
- ctlr_dev->mode = FIP_CONN_TYPE_FABRIC;
- break;
- case FIP_MODE_VN2VN:
- ctlr_dev->mode = FIP_CONN_TYPE_VN2VN;
+ switch (ctlr_dev->mode) {
+ case FIP_CONN_TYPE_VN2VN:
+ ctlr->mode = FIP_MODE_VN2VN;
break;
+ case FIP_CONN_TYPE_FABRIC:
default:
- ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN;
+ ctlr->mode = FIP_MODE_FABRIC;
break;
}
+
mutex_unlock(&ctlr->ctlr_mutex);
+
+ fcoe_ctlr_mode_set(lport, ctlr, ctlr->mode);
}
-EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode);
+EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 5e75168..c9382d6 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -21,8 +21,17 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/etherdevice.h>
+#include <linux/ctype.h>
#include <scsi/fcoe_sysfs.h>
+#include <scsi/libfcoe.h>
+
+/*
+ * OK to include local libfcoe.h for debug_logging, but cannot include
+ * <scsi/libfcoe.h> otherwise non-netdev based fcoe solutions would have
+ * have to include more than fcoe_sysfs.h.
+ */
+#include "libfcoe.h"
static atomic_t ctlr_num;
static atomic_t fcf_num;
@@ -71,6 +80,8 @@ MODULE_PARM_DESC(fcf_dev_loss_tmo,
((x)->lesb.lesb_err_block)
#define fcoe_ctlr_fcs_error(x) \
((x)->lesb.lesb_fcs_error)
+#define fcoe_ctlr_enabled(x) \
+ ((x)->enabled)
#define fcoe_fcf_state(x) \
((x)->state)
#define fcoe_fcf_fabric_name(x) \
@@ -210,25 +221,34 @@ static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
#define fcoe_enum_name_search(title, table_type, table) \
static const char *get_fcoe_##title##_name(enum table_type table_key) \
{ \
- int i; \
- char *name = NULL; \
- \
- for (i = 0; i < ARRAY_SIZE(table); i++) { \
- if (table[i].value == table_key) { \
- name = table[i].name; \
- break; \
- } \
- } \
- return name; \
+ if (table_key < 0 || table_key >= ARRAY_SIZE(table)) \
+ return NULL; \
+ return table[table_key]; \
+}
+
+static char *fip_conn_type_names[] = {
+ [ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
+ [ FIP_CONN_TYPE_FABRIC ] = "Fabric",
+ [ FIP_CONN_TYPE_VN2VN ] = "VN2VN",
+};
+fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
+
+static enum fip_conn_type fcoe_parse_mode(const char *buf)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fip_conn_type_names); i++) {
+ if (strcasecmp(buf, fip_conn_type_names[i]) == 0)
+ return i;
+ }
+
+ return FIP_CONN_TYPE_UNKNOWN;
}
-static struct {
- enum fcf_state value;
- char *name;
-} fcf_state_names[] = {
- { FCOE_FCF_STATE_UNKNOWN, "Unknown" },
- { FCOE_FCF_STATE_DISCONNECTED, "Disconnected" },
- { FCOE_FCF_STATE_CONNECTED, "Connected" },
+static char *fcf_state_names[] = {
+ [ FCOE_FCF_STATE_UNKNOWN ] = "Unknown",
+ [ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
+ [ FCOE_FCF_STATE_CONNECTED ] = "Connected",
};
fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names)
#define FCOE_FCF_STATE_MAX_NAMELEN 50
@@ -246,17 +266,7 @@ static ssize_t show_fcf_state(struct device *dev,
}
static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL);
-static struct {
- enum fip_conn_type value;
- char *name;
-} fip_conn_type_names[] = {
- { FIP_CONN_TYPE_UNKNOWN, "Unknown" },
- { FIP_CONN_TYPE_FABRIC, "Fabric" },
- { FIP_CONN_TYPE_VN2VN, "VN2VN" },
-};
-fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
-#define FCOE_CTLR_MODE_MAX_NAMELEN 50
-
+#define FCOE_MAX_MODENAME_LEN 20
static ssize_t show_ctlr_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -264,17 +274,116 @@ static ssize_t show_ctlr_mode(struct device *dev,
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
const char *name;
- if (ctlr->f->get_fcoe_ctlr_mode)
- ctlr->f->get_fcoe_ctlr_mode(ctlr);
-
name = get_fcoe_ctlr_mode_name(ctlr->mode);
if (!name)
return -EINVAL;
- return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN,
+ return snprintf(buf, FCOE_MAX_MODENAME_LEN,
+ "%s\n", name);
+}
+
+static ssize_t store_ctlr_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
+ char mode[FCOE_MAX_MODENAME_LEN + 1];
+
+ if (count > FCOE_MAX_MODENAME_LEN)
+ return -EINVAL;
+
+ strncpy(mode, buf, count);
+
+ if (mode[count - 1] == '\n')
+ mode[count - 1] = '\0';
+ else
+ mode[count] = '\0';
+
+ switch (ctlr->enabled) {
+ case FCOE_CTLR_ENABLED:
+ LIBFCOE_SYSFS_DBG(ctlr, "Cannot change mode when enabled.");
+ return -EBUSY;
+ case FCOE_CTLR_DISABLED:
+ if (!ctlr->f->set_fcoe_ctlr_mode) {
+ LIBFCOE_SYSFS_DBG(ctlr,
+ "Mode change not supported by LLD.");
+ return -ENOTSUPP;
+ }
+
+ ctlr->mode = fcoe_parse_mode(mode);
+ if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
+ LIBFCOE_SYSFS_DBG(ctlr,
+ "Unknown mode %s provided.", buf);
+ return -EINVAL;
+ }
+
+ ctlr->f->set_fcoe_ctlr_mode(ctlr);
+ LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.", buf);
+
+ return count;
+ case FCOE_CTLR_UNUSED:
+ default:
+ LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.");
+ return -ENOTSUPP;
+ };
+}
+
+static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO | S_IWUSR,
+ show_ctlr_mode, store_ctlr_mode);
+
+static ssize_t store_ctlr_enabled(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
+ int rc;
+
+ switch (ctlr->enabled) {
+ case FCOE_CTLR_ENABLED:
+ if (*buf == '1')
+ return count;
+ ctlr->enabled = FCOE_CTLR_DISABLED;
+ break;
+ case FCOE_CTLR_DISABLED:
+ if (*buf == '0')
+ return count;
+ ctlr->enabled = FCOE_CTLR_ENABLED;
+ break;
+ case FCOE_CTLR_UNUSED:
+ return -ENOTSUPP;
+ };
+
+ rc = ctlr->f->set_fcoe_ctlr_enabled(ctlr);
+ if (rc)
+ return rc;
+
+ return count;
+}
+
+static char *ctlr_enabled_state_names[] = {
+ [ FCOE_CTLR_ENABLED ] = "1",
+ [ FCOE_CTLR_DISABLED ] = "0",
+};
+fcoe_enum_name_search(ctlr_enabled_state, ctlr_enabled_state,
+ ctlr_enabled_state_names)
+#define FCOE_CTLR_ENABLED_MAX_NAMELEN 50
+
+static ssize_t show_ctlr_enabled_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
+ const char *name;
+
+ name = get_fcoe_ctlr_enabled_state_name(ctlr->enabled);
+ if (!name)
+ return -EINVAL;
+ return snprintf(buf, FCOE_CTLR_ENABLED_MAX_NAMELEN,
"%s\n", name);
}
-static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO,
- show_ctlr_mode, NULL);
+
+static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
+ show_ctlr_enabled_state,
+ store_ctlr_enabled);
static ssize_t
store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
@@ -359,6 +468,7 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
static struct attribute *fcoe_ctlr_attrs[] = {
&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
+ &device_attr_fcoe_ctlr_enabled.attr,
&device_attr_fcoe_ctlr_mode.attr,
NULL,
};
@@ -397,7 +507,7 @@ static const struct attribute_group *fcoe_fcf_attr_groups[] = {
NULL,
};
-struct bus_type fcoe_bus_type;
+static struct bus_type fcoe_bus_type;
static int fcoe_bus_match(struct device *dev,
struct device_driver *drv)
@@ -431,28 +541,35 @@ static void fcoe_fcf_device_release(struct device *dev)
kfree(fcf);
}
-struct device_type fcoe_ctlr_device_type = {
+static struct device_type fcoe_ctlr_device_type = {
.name = "fcoe_ctlr",
.groups = fcoe_ctlr_attr_groups,
.release = fcoe_ctlr_device_release,
};
-struct device_type fcoe_fcf_device_type = {
+static struct device_type fcoe_fcf_device_type = {
.name = "fcoe_fcf",
.groups = fcoe_fcf_attr_groups,
.release = fcoe_fcf_device_release,
};
-struct bus_type fcoe_bus_type = {
+static struct bus_attribute fcoe_bus_attr_group[] = {
+ __ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store),
+ __ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store),
+ __ATTR_NULL
+};
+
+static struct bus_type fcoe_bus_type = {
.name = "fcoe",
.match = &fcoe_bus_match,
+ .bus_attrs = fcoe_bus_attr_group,
};
/**
* fcoe_ctlr_device_flush_work() - Flush a FIP ctlr's workqueue
* @ctlr: Pointer to the FIP ctlr whose workqueue is to be flushed
*/
-void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr)
+static void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr)
{
if (!fcoe_ctlr_work_q(ctlr)) {
printk(KERN_ERR
@@ -473,8 +590,8 @@ void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr)
* Return value:
* 1 on success / 0 already queued / < 0 for error
*/
-int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr,
- struct work_struct *work)
+static int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr,
+ struct work_struct *work)
{
if (unlikely(!fcoe_ctlr_work_q(ctlr))) {
printk(KERN_ERR
@@ -492,7 +609,7 @@ int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr,
* fcoe_ctlr_device_flush_devloss() - Flush a FIP ctlr's devloss workqueue
* @ctlr: Pointer to FIP ctlr whose workqueue is to be flushed
*/
-void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr)
+static void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr)
{
if (!fcoe_ctlr_devloss_work_q(ctlr)) {
printk(KERN_ERR
@@ -514,9 +631,9 @@ void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr)
* Return value:
* 1 on success / 0 already queued / < 0 for error
*/
-int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr,
- struct delayed_work *work,
- unsigned long delay)
+static int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr,
+ struct delayed_work *work,
+ unsigned long delay)
{
if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) {
printk(KERN_ERR
@@ -566,6 +683,7 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
ctlr->id = atomic_inc_return(&ctlr_num) - 1;
ctlr->f = f;
+ ctlr->mode = FIP_CONN_TYPE_FABRIC;
INIT_LIST_HEAD(&ctlr->fcfs);
mutex_init(&ctlr->lock);
ctlr->dev.parent = parent;
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index ac76d8a..74277c2 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -83,6 +83,50 @@ static struct notifier_block libfcoe_notifier = {
.notifier_call = libfcoe_device_notification,
};
+/**
+ * fcoe_link_speed_update() - Update the supported and actual link speeds
+ * @lport: The local port to update speeds for
+ *
+ * Returns: 0 if the ethtool query was successful
+ * -1 if the ethtool query failed
+ */
+int fcoe_link_speed_update(struct fc_lport *lport)
+{
+ struct net_device *netdev = fcoe_get_netdev(lport);
+ struct ethtool_cmd ecmd;
+
+ if (!__ethtool_get_settings(netdev, &ecmd)) {
+ lport->link_supported_speeds &=
+ ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+ if (ecmd.supported & (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full))
+ lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
+ if (ecmd.supported & SUPPORTED_10000baseT_Full)
+ lport->link_supported_speeds |=
+ FC_PORTSPEED_10GBIT;
+ switch (ethtool_cmd_speed(&ecmd)) {
+ case SPEED_1000:
+ lport->link_speed = FC_PORTSPEED_1GBIT;
+ break;
+ case SPEED_10000:
+ lport->link_speed = FC_PORTSPEED_10GBIT;
+ break;
+ }
+ return 0;
+ }
+ return -1;
+}
+EXPORT_SYMBOL_GPL(fcoe_link_speed_update);
+
+/**
+ * __fcoe_get_lesb() - Get the Link Error Status Block (LESB) for a given lport
+ * @lport: The local port to update speeds for
+ * @fc_lesb: Pointer to the LESB to be filled up
+ * @netdev: Pointer to the netdev that is associated with the lport
+ *
+ * Note, the Link Error Status Block (LESB) for FCoE is defined in FC-BB-6
+ * Clause 7.11 in v1.04.
+ */
void __fcoe_get_lesb(struct fc_lport *lport,
struct fc_els_lesb *fc_lesb,
struct net_device *netdev)
@@ -112,6 +156,37 @@ void __fcoe_get_lesb(struct fc_lport *lport,
}
EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
+/**
+ * fcoe_get_lesb() - Fill the FCoE Link Error Status Block
+ * @lport: the local port
+ * @fc_lesb: the link error status block
+ */
+void fcoe_get_lesb(struct fc_lport *lport,
+ struct fc_els_lesb *fc_lesb)
+{
+ struct net_device *netdev = fcoe_get_netdev(lport);
+
+ __fcoe_get_lesb(lport, fc_lesb, netdev);
+}
+EXPORT_SYMBOL_GPL(fcoe_get_lesb);
+
+/**
+ * fcoe_ctlr_get_lesb() - Get the Link Error Status Block (LESB) for a given
+ * fcoe controller device
+ * @ctlr_dev: The given fcoe controller device
+ *
+ */
+void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
+{
+ struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
+ struct net_device *netdev = fcoe_get_netdev(fip->lp);
+ struct fc_els_lesb *fc_lesb;
+
+ fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb);
+ __fcoe_get_lesb(fip->lp, fc_lesb, netdev);
+}
+EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
+
void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
{
u8 wwpn[8];
@@ -615,7 +690,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
static int libfcoe_device_notification(struct notifier_block *notifier,
ulong event, void *ptr)
{
- struct net_device *netdev = ptr;
+ struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
switch (event) {
case NETDEV_UNREGISTER:
@@ -627,6 +702,108 @@ static int libfcoe_device_notification(struct notifier_block *notifier,
return NOTIFY_OK;
}
+ssize_t fcoe_ctlr_create_store(struct bus_type *bus,
+ const char *buf, size_t count)
+{
+ struct net_device *netdev = NULL;
+ struct fcoe_transport *ft = NULL;
+ int rc = 0;
+ int err;
+
+ mutex_lock(&ft_mutex);
+
+ netdev = fcoe_if_to_netdev(buf);
+ if (!netdev) {
+ LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buf);
+ rc = -ENODEV;
+ goto out_nodev;
+ }
+
+ ft = fcoe_netdev_map_lookup(netdev);
+ if (ft) {
+ LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
+ "FCoE instance on %s.\n",
+ ft->name, netdev->name);
+ rc = -EEXIST;
+ goto out_putdev;
+ }
+
+ ft = fcoe_transport_lookup(netdev);
+ if (!ft) {
+ LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
+ netdev->name);
+ rc = -ENODEV;
+ goto out_putdev;
+ }
+
+ /* pass to transport create */
+ err = ft->alloc ? ft->alloc(netdev) : -ENODEV;
+ if (err) {
+ fcoe_del_netdev_mapping(netdev);
+ rc = -ENOMEM;
+ goto out_putdev;
+ }
+
+ err = fcoe_add_netdev_mapping(netdev, ft);
+ if (err) {
+ LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
+ "for FCoE transport %s for %s.\n",
+ ft->name, netdev->name);
+ rc = -ENODEV;
+ goto out_putdev;
+ }
+
+ LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n",
+ ft->name, netdev->name);
+
+out_putdev:
+ dev_put(netdev);
+out_nodev:
+ mutex_unlock(&ft_mutex);
+ if (rc)
+ return rc;
+ return count;
+}
+
+ssize_t fcoe_ctlr_destroy_store(struct bus_type *bus,
+ const char *buf, size_t count)
+{
+ int rc = -ENODEV;
+ struct net_device *netdev = NULL;
+ struct fcoe_transport *ft = NULL;
+
+ mutex_lock(&ft_mutex);
+
+ netdev = fcoe_if_to_netdev(buf);
+ if (!netdev) {
+ LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buf);
+ goto out_nodev;
+ }
+
+ ft = fcoe_netdev_map_lookup(netdev);
+ if (!ft) {
+ LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
+ netdev->name);
+ goto out_putdev;
+ }
+
+ /* pass to transport destroy */
+ rc = ft->destroy(netdev);
+ if (rc)
+ goto out_putdev;
+
+ fcoe_del_netdev_mapping(netdev);
+ LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
+ ft->name, (rc) ? "failed" : "succeeded",
+ netdev->name);
+ rc = count; /* required for successful return */
+out_putdev:
+ dev_put(netdev);
+out_nodev:
+ mutex_unlock(&ft_mutex);
+ return rc;
+}
+EXPORT_SYMBOL(fcoe_ctlr_destroy_store);
/**
* fcoe_transport_create() - Create a fcoe interface
@@ -769,11 +946,7 @@ out_putdev:
dev_put(netdev);
out_nodev:
mutex_unlock(&ft_mutex);
-
- if (rc == -ERESTARTSYS)
- return restart_syscall();
- else
- return rc;
+ return rc;
}
/**
diff --git a/drivers/scsi/fcoe/libfcoe.h b/drivers/scsi/fcoe/libfcoe.h
index 6af5fc3..d3bb16d 100644
--- a/drivers/scsi/fcoe/libfcoe.h
+++ b/drivers/scsi/fcoe/libfcoe.h
@@ -2,9 +2,10 @@
#define _FCOE_LIBFCOE_H_
extern unsigned int libfcoe_debug_logging;
-#define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */
-#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
-#define LIBFCOE_TRANSPORT_LOGGING 0x04 /* FCoE transport logging */
+#define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */
+#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
+#define LIBFCOE_TRANSPORT_LOGGING 0x04 /* FCoE transport logging */
+#define LIBFCOE_SYSFS_LOGGING 0x08 /* fcoe_sysfs logging */
#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \
do { \
@@ -16,16 +17,19 @@ do { \
#define LIBFCOE_DBG(fmt, args...) \
LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \
- printk(KERN_INFO "libfcoe: " fmt, ##args);)
+ pr_info("libfcoe: " fmt, ##args);)
#define LIBFCOE_FIP_DBG(fip, fmt, args...) \
LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \
- printk(KERN_INFO "host%d: fip: " fmt, \
- (fip)->lp->host->host_no, ##args);)
+ pr_info("host%d: fip: " fmt, \
+ (fip)->lp->host->host_no, ##args);)
#define LIBFCOE_TRANSPORT_DBG(fmt, args...) \
LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING, \
- printk(KERN_INFO "%s: " fmt, \
- __func__, ##args);)
+ pr_info("%s: " fmt, __func__, ##args);)
+
+#define LIBFCOE_SYSFS_DBG(cdev, fmt, args...) \
+ LIBFCOE_CHECK_LOGGING(LIBFCOE_SYSFS_LOGGING, \
+ pr_info("ctlr_%d: " fmt, cdev->id, ##args);)
#endif /* _FCOE_LIBFCOE_H_ */
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 1a2a1e5..fff6829 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1771,7 +1771,7 @@ struct scsi_host_template fdomain_driver_template = {
#ifndef PCMCIA
#ifdef CONFIG_PCI
-static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
+static struct pci_device_id fdomain_pci_tbl[] = {
{ PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ }
diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile
index 37c3440..383598f 100644
--- a/drivers/scsi/fnic/Makefile
+++ b/drivers/scsi/fnic/Makefile
@@ -7,6 +7,8 @@ fnic-y := \
fnic_res.o \
fnic_fcs.o \
fnic_scsi.o \
+ fnic_trace.o \
+ fnic_debugfs.o \
vnic_cq.o \
vnic_dev.o \
vnic_intr.o \
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 95a5ba2..b6d1f92 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -26,6 +26,7 @@
#include <scsi/libfcoe.h>
#include "fnic_io.h"
#include "fnic_res.h"
+#include "fnic_trace.h"
#include "vnic_dev.h"
#include "vnic_wq.h"
#include "vnic_rq.h"
@@ -37,7 +38,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.5.0.2"
+#define DRV_VERSION "1.5.0.22"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
@@ -56,6 +57,34 @@
#define FNIC_NO_TAG -1
/*
+ * Command flags to identify the type of command and for other future
+ * use.
+ */
+#define FNIC_NO_FLAGS 0
+#define FNIC_IO_INITIALIZED BIT(0)
+#define FNIC_IO_ISSUED BIT(1)
+#define FNIC_IO_DONE BIT(2)
+#define FNIC_IO_REQ_NULL BIT(3)
+#define FNIC_IO_ABTS_PENDING BIT(4)
+#define FNIC_IO_ABORTED BIT(5)
+#define FNIC_IO_ABTS_ISSUED BIT(6)
+#define FNIC_IO_TERM_ISSUED BIT(7)
+#define FNIC_IO_INTERNAL_TERM_ISSUED BIT(8)
+#define FNIC_IO_ABT_TERM_DONE BIT(9)
+#define FNIC_IO_ABT_TERM_REQ_NULL BIT(10)
+#define FNIC_IO_ABT_TERM_TIMED_OUT BIT(11)
+#define FNIC_DEVICE_RESET BIT(12) /* Device reset request */
+#define FNIC_DEV_RST_ISSUED BIT(13)
+#define FNIC_DEV_RST_TIMED_OUT BIT(14)
+#define FNIC_DEV_RST_ABTS_ISSUED BIT(15)
+#define FNIC_DEV_RST_TERM_ISSUED BIT(16)
+#define FNIC_DEV_RST_DONE BIT(17)
+#define FNIC_DEV_RST_REQ_NULL BIT(18)
+#define FNIC_DEV_RST_ABTS_DONE BIT(19)
+#define FNIC_DEV_RST_TERM_DONE BIT(20)
+#define FNIC_DEV_RST_ABTS_PENDING BIT(21)
+
+/*
* Usage of the scsi_cmnd scratchpad.
* These fields are locked by the hashed io_req_lock.
*/
@@ -64,6 +93,7 @@
#define CMD_ABTS_STATUS(Cmnd) ((Cmnd)->SCp.Message)
#define CMD_LR_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in)
#define CMD_TAG(Cmnd) ((Cmnd)->SCp.sent_command)
+#define CMD_FLAGS(Cmnd) ((Cmnd)->SCp.Status)
#define FCPIO_INVALID_CODE 0x100 /* hdr_status value unused by firmware */
@@ -71,9 +101,28 @@
#define FNIC_HOST_RESET_TIMEOUT 10000 /* mSec */
#define FNIC_RMDEVICE_TIMEOUT 1000 /* mSec */
#define FNIC_HOST_RESET_SETTLE_TIME 30 /* Sec */
+#define FNIC_ABT_TERM_DELAY_TIMEOUT 500 /* mSec */
#define FNIC_MAX_FCP_TARGET 256
+/**
+ * state_flags to identify host state along along with fnic's state
+ **/
+#define __FNIC_FLAGS_FWRESET BIT(0) /* fwreset in progress */
+#define __FNIC_FLAGS_BLOCK_IO BIT(1) /* IOs are blocked */
+
+#define FNIC_FLAGS_NONE (0)
+#define FNIC_FLAGS_FWRESET (__FNIC_FLAGS_FWRESET | \
+ __FNIC_FLAGS_BLOCK_IO)
+
+#define FNIC_FLAGS_IO_BLOCKED (__FNIC_FLAGS_BLOCK_IO)
+
+#define fnic_set_state_flags(fnicp, st_flags) \
+ __fnic_set_state_flags(fnicp, st_flags, 0)
+
+#define fnic_clear_state_flags(fnicp, st_flags) \
+ __fnic_set_state_flags(fnicp, st_flags, 1)
+
extern unsigned int fnic_log_level;
#define FNIC_MAIN_LOGGING 0x01
@@ -143,6 +192,18 @@ enum fnic_state {
struct mempool;
+enum fnic_evt {
+ FNIC_EVT_START_VLAN_DISC = 1,
+ FNIC_EVT_START_FCF_DISC = 2,
+ FNIC_EVT_MAX,
+};
+
+struct fnic_event {
+ struct list_head list;
+ struct fnic *fnic;
+ enum fnic_evt event;
+};
+
/* Per-instance private data structure */
struct fnic {
struct fc_lport *lport;
@@ -170,6 +231,9 @@ struct fnic {
struct completion *remove_wait; /* device remove thread blocks */
+ atomic_t in_flight; /* io counter */
+ u32 _reserved; /* fill hole */
+ unsigned long state_flags; /* protected by host lock */
enum fnic_state state;
spinlock_t fnic_lock;
@@ -202,6 +266,18 @@ struct fnic {
struct sk_buff_head frame_queue;
struct sk_buff_head tx_queue;
+ /*** FIP related data members -- start ***/
+ void (*set_vlan)(struct fnic *, u16 vlan);
+ struct work_struct fip_frame_work;
+ struct sk_buff_head fip_frame_queue;
+ struct timer_list fip_timer;
+ struct list_head vlans;
+ spinlock_t vlans_lock;
+
+ struct work_struct event_work;
+ struct list_head evlist;
+ /*** FIP related data members -- end ***/
+
/* copy work queue cache line section */
____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX];
/* completion queue cache line section */
@@ -226,6 +302,7 @@ static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip)
}
extern struct workqueue_struct *fnic_event_queue;
+extern struct workqueue_struct *fnic_fip_queue;
extern struct device_attribute *fnic_attrs[];
void fnic_clear_intr_mode(struct fnic *fnic);
@@ -237,6 +314,7 @@ int fnic_send(struct fc_lport *, struct fc_frame *);
void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);
void fnic_handle_frame(struct work_struct *work);
void fnic_handle_link(struct work_struct *work);
+void fnic_handle_event(struct work_struct *work);
int fnic_rq_cmpl_handler(struct fnic *fnic, int);
int fnic_alloc_rq_frame(struct vnic_rq *rq);
void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
@@ -267,4 +345,18 @@ const char *fnic_state_to_str(unsigned int state);
void fnic_log_q_error(struct fnic *fnic);
void fnic_handle_link_event(struct fnic *fnic);
+int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);
+
+void fnic_handle_fip_frame(struct work_struct *work);
+void fnic_handle_fip_event(struct fnic *fnic);
+void fnic_fcoe_reset_vlans(struct fnic *fnic);
+void fnic_fcoe_evlist_free(struct fnic *fnic);
+extern void fnic_handle_fip_timer(struct fnic *fnic);
+
+static inline int
+fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
+{
+ return ((fnic->state_flags & st_flags) == st_flags);
+}
+void __fnic_set_state_flags(struct fnic *, unsigned long, unsigned long);
#endif /* _FNIC_H_ */
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
new file mode 100644
index 0000000..cbcb012
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2012 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/debugfs.h>
+#include "fnic.h"
+
+static struct dentry *fnic_trace_debugfs_root;
+static struct dentry *fnic_trace_debugfs_file;
+static struct dentry *fnic_trace_enable;
+
+/*
+ * fnic_trace_ctrl_open - Open the trace_enable file
+ * @inode: The inode pointer.
+ * @file: The file pointer to attach the trace enable/disable flag.
+ *
+ * Description:
+ * This routine opens a debugsfs file trace_enable.
+ *
+ * Returns:
+ * This function returns zero if successful.
+ */
+static int fnic_trace_ctrl_open(struct inode *inode, struct file *filp)
+{
+ filp->private_data = inode->i_private;
+ return 0;
+}
+
+/*
+ * fnic_trace_ctrl_read - Read a trace_enable debugfs file
+ * @filp: The file pointer to read from.
+ * @ubuf: The buffer to copy the data to.
+ * @cnt: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads value of variable fnic_tracing_enabled
+ * and stores into local @buf. It will start reading file at @ppos and
+ * copy up to @cnt of data to @ubuf from @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read.
+ */
+static ssize_t fnic_trace_ctrl_read(struct file *filp,
+ char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char buf[64];
+ int len;
+ len = sprintf(buf, "%u\n", fnic_tracing_enabled);
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
+}
+
+/*
+ * fnic_trace_ctrl_write - Write to trace_enable debugfs file
+ * @filp: The file pointer to write from.
+ * @ubuf: The buffer to copy the data from.
+ * @cnt: The number of bytes to write.
+ * @ppos: The position in the file to start writing to.
+ *
+ * Description:
+ * This routine writes data from user buffer @ubuf to buffer @buf and
+ * sets fnic_tracing_enabled value as per user input.
+ *
+ * Returns:
+ * This function returns the amount of data that was written.
+ */
+static ssize_t fnic_trace_ctrl_write(struct file *filp,
+ const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char buf[64];
+ unsigned long val;
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ return -EFAULT;
+
+ buf[cnt] = 0;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ fnic_tracing_enabled = val;
+ (*ppos)++;
+
+ return cnt;
+}
+
+/*
+ * fnic_trace_debugfs_open - Open the fnic trace log
+ * @inode: The inode pointer
+ * @file: The file pointer to attach the log output
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation.
+ * It allocates the necessary buffer for the log, fills the buffer from
+ * the in-memory log and then returns a pointer to that log in
+ * the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return
+ * a negative error value.
+ */
+static int fnic_trace_debugfs_open(struct inode *inode,
+ struct file *file)
+{
+ fnic_dbgfs_t *fnic_dbg_prt;
+ fnic_dbg_prt = kzalloc(sizeof(fnic_dbgfs_t), GFP_KERNEL);
+ if (!fnic_dbg_prt)
+ return -ENOMEM;
+
+ fnic_dbg_prt->buffer = vmalloc((3*(trace_max_pages * PAGE_SIZE)));
+ if (!fnic_dbg_prt->buffer) {
+ kfree(fnic_dbg_prt);
+ return -ENOMEM;
+ }
+ memset((void *)fnic_dbg_prt->buffer, 0,
+ (3*(trace_max_pages * PAGE_SIZE)));
+ fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
+ file->private_data = fnic_dbg_prt;
+ return 0;
+}
+
+/*
+ * fnic_trace_debugfs_lseek - Seek through a debugfs file
+ * @file: The file pointer to seek through.
+ * @offset: The offset to seek to or the amount to seek by.
+ * @howto: Indicates how to seek.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs lseek file operation.
+ * The @howto parameter indicates whether @offset is the offset to directly
+ * seek to, or if it is a value to seek forward or reverse by. This function
+ * figures out what the new offset of the debugfs file will be and assigns
+ * that value to the f_pos field of @file.
+ *
+ * Returns:
+ * This function returns the new offset if successful and returns a negative
+ * error if unable to process the seek.
+ */
+static loff_t fnic_trace_debugfs_lseek(struct file *file,
+ loff_t offset,
+ int howto)
+{
+ fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
+ return fixed_size_llseek(file, offset, howto,
+ fnic_dbg_prt->buffer_len);
+}
+
+/*
+ * fnic_trace_debugfs_read - Read a debugfs file
+ * @file: The file pointer to read from.
+ * @ubuf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @pos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the buffer indicated in the private_data
+ * field of @file. It will start reading at @pos and copy up to @nbytes of
+ * data to @ubuf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be
+ * less than @nbytes if the end of the file was reached).
+ */
+static ssize_t fnic_trace_debugfs_read(struct file *file,
+ char __user *ubuf,
+ size_t nbytes,
+ loff_t *pos)
+{
+ fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
+ int rc = 0;
+ rc = simple_read_from_buffer(ubuf, nbytes, pos,
+ fnic_dbg_prt->buffer,
+ fnic_dbg_prt->buffer_len);
+ return rc;
+}
+
+/*
+ * fnic_trace_debugfs_release - Release the buffer used to store
+ * debugfs file data
+ * @inode: The inode pointer
+ * @file: The file pointer that contains the buffer to release
+ *
+ * Description:
+ * This routine frees the buffer that was allocated when the debugfs
+ * file was opened.
+ *
+ * Returns:
+ * This function returns zero.
+ */
+static int fnic_trace_debugfs_release(struct inode *inode,
+ struct file *file)
+{
+ fnic_dbgfs_t *fnic_dbg_prt = file->private_data;
+
+ vfree(fnic_dbg_prt->buffer);
+ kfree(fnic_dbg_prt);
+ return 0;
+}
+
+static const struct file_operations fnic_trace_ctrl_fops = {
+ .owner = THIS_MODULE,
+ .open = fnic_trace_ctrl_open,
+ .read = fnic_trace_ctrl_read,
+ .write = fnic_trace_ctrl_write,
+};
+
+static const struct file_operations fnic_trace_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = fnic_trace_debugfs_open,
+ .llseek = fnic_trace_debugfs_lseek,
+ .read = fnic_trace_debugfs_read,
+ .release = fnic_trace_debugfs_release,
+};
+
+/*
+ * fnic_trace_debugfs_init - Initialize debugfs for fnic trace logging
+ *
+ * Description:
+ * When Debugfs is configured this routine sets up the fnic debugfs
+ * file system. If not already created, this routine will create the
+ * fnic directory. It will create file trace to log fnic trace buffer
+ * output into debugfs and it will also create file trace_enable to
+ * control enable/disable of trace logging into trace buffer.
+ */
+int fnic_trace_debugfs_init(void)
+{
+ int rc = -1;
+ fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL);
+ if (!fnic_trace_debugfs_root) {
+ printk(KERN_DEBUG "Cannot create debugfs root\n");
+ return rc;
+ }
+ fnic_trace_enable = debugfs_create_file("tracing_enable",
+ S_IFREG|S_IRUGO|S_IWUSR,
+ fnic_trace_debugfs_root,
+ NULL, &fnic_trace_ctrl_fops);
+
+ if (!fnic_trace_enable) {
+ printk(KERN_DEBUG "Cannot create trace_enable file"
+ " under debugfs");
+ return rc;
+ }
+
+ fnic_trace_debugfs_file = debugfs_create_file("trace",
+ S_IFREG|S_IRUGO|S_IWUSR,
+ fnic_trace_debugfs_root,
+ NULL,
+ &fnic_trace_debugfs_fops);
+
+ if (!fnic_trace_debugfs_file) {
+ printk(KERN_DEBUG "Cannot create trace file under debugfs");
+ return rc;
+ }
+ rc = 0;
+ return rc;
+}
+
+/*
+ * fnic_trace_debugfs_terminate - Tear down debugfs infrastructure
+ *
+ * Description:
+ * When Debugfs is configured this routine removes debugfs file system
+ * elements that are specific to fnic trace logging.
+ */
+void fnic_trace_debugfs_terminate(void)
+{
+ if (fnic_trace_debugfs_file) {
+ debugfs_remove(fnic_trace_debugfs_file);
+ fnic_trace_debugfs_file = NULL;
+ }
+ if (fnic_trace_enable) {
+ debugfs_remove(fnic_trace_enable);
+ fnic_trace_enable = NULL;
+ }
+ if (fnic_trace_debugfs_root) {
+ debugfs_remove(fnic_trace_debugfs_root);
+ fnic_trace_debugfs_root = NULL;
+ }
+}
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 3c53c34..006fa92 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -31,12 +31,20 @@
#include <scsi/libfc.h>
#include "fnic_io.h"
#include "fnic.h"
+#include "fnic_fip.h"
#include "cq_enet_desc.h"
#include "cq_exch_desc.h"
+static u8 fcoe_all_fcfs[ETH_ALEN];
+struct workqueue_struct *fnic_fip_queue;
struct workqueue_struct *fnic_event_queue;
static void fnic_set_eth_mode(struct fnic *);
+static void fnic_fcoe_send_vlan_req(struct fnic *fnic);
+static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
+static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
+static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
+static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);
void fnic_handle_link(struct work_struct *work)
{
@@ -69,6 +77,11 @@ void fnic_handle_link(struct work_struct *work)
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
"link down\n");
fcoe_ctlr_link_down(&fnic->ctlr);
+ if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+ /* start FCoE VLAN discovery */
+ fnic_fcoe_send_vlan_req(fnic);
+ return;
+ }
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
"link up\n");
fcoe_ctlr_link_up(&fnic->ctlr);
@@ -79,6 +92,11 @@ void fnic_handle_link(struct work_struct *work)
} else if (fnic->link_status) {
/* DOWN -> UP */
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+ /* start FCoE VLAN discovery */
+ fnic_fcoe_send_vlan_req(fnic);
+ return;
+ }
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n");
fcoe_ctlr_link_up(&fnic->ctlr);
} else {
@@ -128,6 +146,441 @@ void fnic_handle_frame(struct work_struct *work)
}
}
+void fnic_fcoe_evlist_free(struct fnic *fnic)
+{
+ struct fnic_event *fevt = NULL;
+ struct fnic_event *next = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (list_empty(&fnic->evlist)) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+
+ list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
+ list_del(&fevt->list);
+ kfree(fevt);
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+void fnic_handle_event(struct work_struct *work)
+{
+ struct fnic *fnic = container_of(work, struct fnic, event_work);
+ struct fnic_event *fevt = NULL;
+ struct fnic_event *next = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (list_empty(&fnic->evlist)) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+
+ list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
+ if (fnic->stop_rx_link_events) {
+ list_del(&fevt->list);
+ kfree(fevt);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ /*
+ * If we're in a transitional state, just re-queue and return.
+ * The queue will be serviced when we get to a stable state.
+ */
+ if (fnic->state != FNIC_IN_FC_MODE &&
+ fnic->state != FNIC_IN_ETH_MODE) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+
+ list_del(&fevt->list);
+ switch (fevt->event) {
+ case FNIC_EVT_START_VLAN_DISC:
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ fnic_fcoe_send_vlan_req(fnic);
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ break;
+ case FNIC_EVT_START_FCF_DISC:
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ "Start FCF Discovery\n");
+ fnic_fcoe_start_fcf_disc(fnic);
+ break;
+ default:
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ "Unknown event 0x%x\n", fevt->event);
+ break;
+ }
+ kfree(fevt);
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+/**
+ * Check if the Received FIP FLOGI frame is rejected
+ * @fip: The FCoE controller that received the frame
+ * @skb: The received FIP frame
+ *
+ * Returns non-zero if the frame is rejected with unsupported cmd with
+ * insufficient resource els explanation.
+ */
+static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
+ struct sk_buff *skb)
+{
+ struct fc_lport *lport = fip->lp;
+ struct fip_header *fiph;
+ struct fc_frame_header *fh = NULL;
+ struct fip_desc *desc;
+ struct fip_encaps *els;
+ enum fip_desc_type els_dtype = 0;
+ u16 op;
+ u8 els_op;
+ u8 sub;
+
+ size_t els_len = 0;
+ size_t rlen;
+ size_t dlen = 0;
+
+ if (skb_linearize(skb))
+ return 0;
+
+ if (skb->len < sizeof(*fiph))
+ return 0;
+
+ fiph = (struct fip_header *)skb->data;
+ op = ntohs(fiph->fip_op);
+ sub = fiph->fip_subcode;
+
+ if (op != FIP_OP_LS)
+ return 0;
+
+ if (sub != FIP_SC_REP)
+ return 0;
+
+ rlen = ntohs(fiph->fip_dl_len) * 4;
+ if (rlen + sizeof(*fiph) > skb->len)
+ return 0;
+
+ desc = (struct fip_desc *)(fiph + 1);
+ dlen = desc->fip_dlen * FIP_BPW;
+
+ if (desc->fip_dtype == FIP_DT_FLOGI) {
+
+ shost_printk(KERN_DEBUG, lport->host,
+ " FIP TYPE FLOGI: fab name:%llx "
+ "vfid:%d map:%x\n",
+ fip->sel_fcf->fabric_name, fip->sel_fcf->vfid,
+ fip->sel_fcf->fc_map);
+ if (dlen < sizeof(*els) + sizeof(*fh) + 1)
+ return 0;
+
+ els_len = dlen - sizeof(*els);
+ els = (struct fip_encaps *)desc;
+ fh = (struct fc_frame_header *)(els + 1);
+ els_dtype = desc->fip_dtype;
+
+ if (!fh)
+ return 0;
+
+ /*
+ * ELS command code, reason and explanation should be = Reject,
+ * unsupported command and insufficient resource
+ */
+ els_op = *(u8 *)(fh + 1);
+ if (els_op == ELS_LS_RJT) {
+ shost_printk(KERN_INFO, lport->host,
+ "Flogi Request Rejected by Switch\n");
+ return 1;
+ }
+ shost_printk(KERN_INFO, lport->host,
+ "Flogi Request Accepted by Switch\n");
+ }
+ return 0;
+}
+
+static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
+{
+ struct fcoe_ctlr *fip = &fnic->ctlr;
+ struct sk_buff *skb;
+ char *eth_fr;
+ int fr_len;
+ struct fip_vlan *vlan;
+ u64 vlan_tov;
+
+ fnic_fcoe_reset_vlans(fnic);
+ fnic->set_vlan(fnic, 0);
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ "Sending VLAN request...\n");
+ skb = dev_alloc_skb(sizeof(struct fip_vlan));
+ if (!skb)
+ return;
+
+ fr_len = sizeof(*vlan);
+ eth_fr = (char *)skb->data;
+ vlan = (struct fip_vlan *)eth_fr;
+
+ memset(vlan, 0, sizeof(*vlan));
+ memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+ memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN);
+ vlan->eth.h_proto = htons(ETH_P_FIP);
+
+ vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+ vlan->fip.fip_op = htons(FIP_OP_VLAN);
+ vlan->fip.fip_subcode = FIP_SC_VL_REQ;
+ vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
+
+ vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
+ vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW;
+ memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+ vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+ vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW;
+ put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn);
+
+ skb_put(skb, sizeof(*vlan));
+ skb->protocol = htons(ETH_P_FIP);
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
+ fip->send(fip, skb);
+
+ /* set a timer so that we can retry if there no response */
+ vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
+ mod_timer(&fnic->fip_timer, round_jiffies(vlan_tov));
+}
+
+static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
+{
+ struct fcoe_ctlr *fip = &fnic->ctlr;
+ struct fip_header *fiph;
+ struct fip_desc *desc;
+ u16 vid;
+ size_t rlen;
+ size_t dlen;
+ struct fcoe_vlan *vlan;
+ u64 sol_time;
+ unsigned long flags;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ "Received VLAN response...\n");
+
+ fiph = (struct fip_header *) skb->data;
+
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ "Received VLAN response... OP 0x%x SUB_OP 0x%x\n",
+ ntohs(fiph->fip_op), fiph->fip_subcode);
+
+ rlen = ntohs(fiph->fip_dl_len) * 4;
+ fnic_fcoe_reset_vlans(fnic);
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ desc = (struct fip_desc *)(fiph + 1);
+ while (rlen > 0) {
+ dlen = desc->fip_dlen * FIP_BPW;
+ switch (desc->fip_dtype) {
+ case FIP_DT_VLAN:
+ vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "process_vlan_resp: FIP VLAN %d\n", vid);
+ vlan = kmalloc(sizeof(*vlan),
+ GFP_ATOMIC);
+ if (!vlan) {
+ /* retry from timer */
+ spin_unlock_irqrestore(&fnic->vlans_lock,
+ flags);
+ goto out;
+ }
+ memset(vlan, 0, sizeof(struct fcoe_vlan));
+ vlan->vid = vid & 0x0fff;
+ vlan->state = FIP_VLAN_AVAIL;
+ list_add_tail(&vlan->list, &fnic->vlans);
+ break;
+ }
+ desc = (struct fip_desc *)((char *)desc + dlen);
+ rlen -= dlen;
+ }
+
+ /* any VLAN descriptors present ? */
+ if (list_empty(&fnic->vlans)) {
+ /* retry from timer */
+ FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+ "No VLAN descriptors in FIP VLAN response\n");
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ goto out;
+ }
+
+ vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+ fnic->set_vlan(fnic, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+ vlan->sol_count++;
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+
+ /* start the solicitation */
+ fcoe_ctlr_link_up(fip);
+
+ sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+ mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
+out:
+ return;
+}
+
+static void fnic_fcoe_start_fcf_disc(struct fnic *fnic)
+{
+ unsigned long flags;
+ struct fcoe_vlan *vlan;
+ u64 sol_time;
+
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+ fnic->set_vlan(fnic, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+ vlan->sol_count = 1;
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+
+ /* start the solicitation */
+ fcoe_ctlr_link_up(&fnic->ctlr);
+
+ sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+ mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
+}
+
+static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag)
+{
+ unsigned long flags;
+ struct fcoe_vlan *fvlan;
+
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ if (list_empty(&fnic->vlans)) {
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ return -EINVAL;
+ }
+
+ fvlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+ if (fvlan->state == FIP_VLAN_USED) {
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ return 0;
+ }
+
+ if (fvlan->state == FIP_VLAN_SENT) {
+ fvlan->state = FIP_VLAN_USED;
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ return -EINVAL;
+}
+
+static void fnic_event_enq(struct fnic *fnic, enum fnic_evt ev)
+{
+ struct fnic_event *fevt;
+ unsigned long flags;
+
+ fevt = kmalloc(sizeof(*fevt), GFP_ATOMIC);
+ if (!fevt)
+ return;
+
+ fevt->fnic = fnic;
+ fevt->event = ev;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ list_add_tail(&fevt->list, &fnic->evlist);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ schedule_work(&fnic->event_work);
+}
+
+static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb)
+{
+ struct fip_header *fiph;
+ int ret = 1;
+ u16 op;
+ u8 sub;
+
+ if (!skb || !(skb->data))
+ return -1;
+
+ if (skb_linearize(skb))
+ goto drop;
+
+ fiph = (struct fip_header *)skb->data;
+ op = ntohs(fiph->fip_op);
+ sub = fiph->fip_subcode;
+
+ if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
+ goto drop;
+
+ if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
+ goto drop;
+
+ if (op == FIP_OP_DISC && sub == FIP_SC_ADV) {
+ if (fnic_fcoe_vlan_check(fnic, ntohs(fiph->fip_flags)))
+ goto drop;
+ /* pass it on to fcoe */
+ ret = 1;
+ } else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_REP) {
+ /* set the vlan as used */
+ fnic_fcoe_process_vlan_resp(fnic, skb);
+ ret = 0;
+ } else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) {
+ /* received CVL request, restart vlan disc */
+ fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+ /* pass it on to fcoe */
+ ret = 1;
+ }
+drop:
+ return ret;
+}
+
+void fnic_handle_fip_frame(struct work_struct *work)
+{
+ struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);
+ unsigned long flags;
+ struct sk_buff *skb;
+ struct ethhdr *eh;
+
+ while ((skb = skb_dequeue(&fnic->fip_frame_queue))) {
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (fnic->stop_rx_link_events) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ dev_kfree_skb(skb);
+ return;
+ }
+ /*
+ * If we're in a transitional state, just re-queue and return.
+ * The queue will be serviced when we get to a stable state.
+ */
+ if (fnic->state != FNIC_IN_FC_MODE &&
+ fnic->state != FNIC_IN_ETH_MODE) {
+ skb_queue_head(&fnic->fip_frame_queue, skb);
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ eh = (struct ethhdr *)skb->data;
+ if (eh->h_proto == htons(ETH_P_FIP)) {
+ skb_pull(skb, sizeof(*eh));
+ if (fnic_fcoe_handle_fip_frame(fnic, skb) <= 0) {
+ dev_kfree_skb(skb);
+ continue;
+ }
+ /*
+ * If there's FLOGI rejects - clear all
+ * fcf's & restart from scratch
+ */
+ if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) {
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "Trigger a Link down - VLAN Disc\n");
+ fcoe_ctlr_link_down(&fnic->ctlr);
+ /* start FCoE VLAN discovery */
+ fnic_fcoe_send_vlan_req(fnic);
+ dev_kfree_skb(skb);
+ continue;
+ }
+ fcoe_ctlr_recv(&fnic->ctlr, skb);
+ continue;
+ }
+ }
+}
+
/**
* fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame.
* @fnic: fnic instance.
@@ -150,8 +603,14 @@ static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
skb_reset_mac_header(skb);
}
if (eh->h_proto == htons(ETH_P_FIP)) {
- skb_pull(skb, sizeof(*eh));
- fcoe_ctlr_recv(&fnic->ctlr, skb);
+ if (!(fnic->config.flags & VFCF_FIP_CAPABLE)) {
+ printk(KERN_ERR "Dropped FIP frame, as firmware "
+ "uses non-FIP mode, Enable FIP "
+ "using UCSM\n");
+ goto drop;
+ }
+ skb_queue_tail(&fnic->fip_frame_queue, skb);
+ queue_work(fnic_fip_queue, &fnic->fip_frame_work);
return 1; /* let caller know packet was used */
}
if (eh->h_proto != htons(ETH_P_FCOE))
@@ -495,7 +954,8 @@ void fnic_eth_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
}
fnic_queue_wq_eth_desc(wq, skb, pa, skb->len,
- fnic->vlan_hw_insert, fnic->vlan_id, 1);
+ 0 /* hw inserts cos value */,
+ fnic->vlan_id, 1);
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
}
@@ -563,7 +1023,8 @@ static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
}
fnic_queue_wq_desc(wq, skb, pa, tot_len, fr_eof(fp),
- fnic->vlan_hw_insert, fnic->vlan_id, 1, 1, 1);
+ 0 /* hw inserts cos value */,
+ fnic->vlan_id, 1, 1, 1);
fnic_send_frame_end:
spin_unlock_irqrestore(&fnic->wq_lock[0], flags);
@@ -718,3 +1179,104 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
dev_kfree_skb(fp_skb(fp));
buf->os_buf = NULL;
}
+
+void fnic_fcoe_reset_vlans(struct fnic *fnic)
+{
+ unsigned long flags;
+ struct fcoe_vlan *vlan;
+ struct fcoe_vlan *next;
+
+ /*
+ * indicate a link down to fcoe so that all fcf's are free'd
+ * might not be required since we did this before sending vlan
+ * discovery request
+ */
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ if (!list_empty(&fnic->vlans)) {
+ list_for_each_entry_safe(vlan, next, &fnic->vlans, list) {
+ list_del(&vlan->list);
+ kfree(vlan);
+ }
+ }
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+}
+
+void fnic_handle_fip_timer(struct fnic *fnic)
+{
+ unsigned long flags;
+ struct fcoe_vlan *vlan;
+ u64 sol_time;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (fnic->stop_rx_link_events) {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+ if (fnic->ctlr.mode == FIP_ST_NON_FIP)
+ return;
+
+ spin_lock_irqsave(&fnic->vlans_lock, flags);
+ if (list_empty(&fnic->vlans)) {
+ /* no vlans available, try again */
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ "Start VLAN Discovery\n");
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+ return;
+ }
+
+ vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+ shost_printk(KERN_DEBUG, fnic->lport->host,
+ "fip_timer: vlan %d state %d sol_count %d\n",
+ vlan->vid, vlan->state, vlan->sol_count);
+ switch (vlan->state) {
+ case FIP_VLAN_USED:
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ "FIP VLAN is selected for FC transaction\n");
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ break;
+ case FIP_VLAN_FAILED:
+ /* if all vlans are in failed state, restart vlan disc */
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ "Start VLAN Discovery\n");
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+ break;
+ case FIP_VLAN_SENT:
+ if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
+ /*
+ * no response on this vlan, remove from the list.
+ * Try the next vlan
+ */
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "Dequeue this VLAN ID %d from list\n",
+ vlan->vid);
+ list_del(&vlan->list);
+ kfree(vlan);
+ vlan = NULL;
+ if (list_empty(&fnic->vlans)) {
+ /* we exhausted all vlans, restart vlan disc */
+ spin_unlock_irqrestore(&fnic->vlans_lock,
+ flags);
+ shost_printk(KERN_INFO, fnic->lport->host,
+ "fip_timer: vlan list empty, "
+ "trigger vlan disc\n");
+ fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+ return;
+ }
+ /* check the next vlan */
+ vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan,
+ list);
+ fnic->set_vlan(fnic, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+ }
+ spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+ vlan->sol_count++;
+ sol_time = jiffies + msecs_to_jiffies
+ (FCOE_CTLR_START_DELAY);
+ mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
+ break;
+ }
+}
diff --git a/drivers/scsi/fnic/fnic_fip.h b/drivers/scsi/fnic/fnic_fip.h
new file mode 100644
index 0000000..87e74c2
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_fip.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc. All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _FNIC_FIP_H_
+#define _FNIC_FIP_H_
+
+
+#define FCOE_CTLR_START_DELAY 2000 /* ms after first adv. to choose FCF */
+#define FCOE_CTLR_FIPVLAN_TOV 2000 /* ms after FIP VLAN disc */
+#define FCOE_CTLR_MAX_SOL 8
+
+#define FINC_MAX_FLOGI_REJECTS 8
+
+/*
+ * FIP_DT_VLAN descriptor.
+ */
+struct fip_vlan_desc {
+ struct fip_desc fd_desc;
+ __be16 fd_vlan;
+} __attribute__((packed));
+
+struct vlan {
+ __be16 vid;
+ __be16 type;
+};
+
+/*
+ * VLAN entry.
+ */
+struct fcoe_vlan {
+ struct list_head list;
+ u16 vid; /* vlan ID */
+ u16 sol_count; /* no. of sols sent */
+ u16 state; /* state */
+};
+
+enum fip_vlan_state {
+ FIP_VLAN_AVAIL = 0, /* don't do anything */
+ FIP_VLAN_SENT = 1, /* sent */
+ FIP_VLAN_USED = 2, /* succeed */
+ FIP_VLAN_FAILED = 3, /* failed to response */
+};
+
+struct fip_vlan {
+ struct ethhdr eth;
+ struct fip_header fip;
+ struct {
+ struct fip_mac_desc mac;
+ struct fip_wwn_desc wwnn;
+ } desc;
+};
+
+#endif /* __FINC_FIP_H_ */
diff --git a/drivers/scsi/fnic/fnic_io.h b/drivers/scsi/fnic/fnic_io.h
index f0b8969..c35b8f1 100644
--- a/drivers/scsi/fnic/fnic_io.h
+++ b/drivers/scsi/fnic/fnic_io.h
@@ -21,7 +21,7 @@
#include <scsi/fc/fc_fcp.h>
#define FNIC_DFLT_SG_DESC_CNT 32
-#define FNIC_MAX_SG_DESC_CNT 1024 /* Maximum descriptors per sgl */
+#define FNIC_MAX_SG_DESC_CNT 256 /* Maximum descriptors per sgl */
#define FNIC_SG_DESC_ALIGN 16 /* Descriptor address alignment */
struct host_sg_desc {
@@ -45,7 +45,8 @@ enum fnic_sgl_list_type {
};
enum fnic_ioreq_state {
- FNIC_IOREQ_CMD_PENDING = 0,
+ FNIC_IOREQ_NOT_INITED = 0,
+ FNIC_IOREQ_CMD_PENDING,
FNIC_IOREQ_ABTS_PENDING,
FNIC_IOREQ_ABTS_COMPLETE,
FNIC_IOREQ_CMD_COMPLETE,
@@ -60,6 +61,7 @@ struct fnic_io_req {
u8 sgl_type; /* device DMA descriptor list type */
u8 io_completed:1; /* set to 1 when fw completes IO */
u32 port_id; /* remote port DID */
+ unsigned long start_time; /* in jiffies */
struct completion *abts_done; /* completion for abts */
struct completion *dr_done; /* completion for device reset */
};
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index fc98eb6..5f09d18 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -39,6 +39,7 @@
#include "vnic_intr.h"
#include "vnic_stats.h"
#include "fnic_io.h"
+#include "fnic_fip.h"
#include "fnic.h"
#define PCI_DEVICE_ID_CISCO_FNIC 0x0045
@@ -68,6 +69,10 @@ unsigned int fnic_log_level;
module_param(fnic_log_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(fnic_log_level, "bit mask of fnic logging levels");
+unsigned int fnic_trace_max_pages = 16;
+module_param(fnic_trace_max_pages, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(fnic_trace_max_pages, "Total allocated memory pages "
+ "for fnic trace buffer");
static struct libfc_function_template fnic_transport_template = {
.frame_send = fnic_send,
@@ -288,6 +293,13 @@ static void fnic_notify_timer(unsigned long data)
round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD));
}
+static void fnic_fip_notify_timer(unsigned long data)
+{
+ struct fnic *fnic = (struct fnic *)data;
+
+ fnic_handle_fip_timer(fnic);
+}
+
static void fnic_notify_timer_start(struct fnic *fnic)
{
switch (vnic_dev_get_intr_mode(fnic->vdev)) {
@@ -399,8 +411,13 @@ static u8 *fnic_get_mac(struct fc_lport *lport)
return fnic->data_src_addr;
}
-static int __devinit fnic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
+{
+ u16 old_vlan;
+ old_vlan = vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
+}
+
+static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct Scsi_Host *host;
struct fc_lport *lp;
@@ -617,7 +634,29 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0);
vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS);
vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
+ fnic->set_vlan = fnic_set_vlan;
fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO);
+ setup_timer(&fnic->fip_timer, fnic_fip_notify_timer,
+ (unsigned long)fnic);
+ spin_lock_init(&fnic->vlans_lock);
+ INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
+ INIT_WORK(&fnic->event_work, fnic_handle_event);
+ skb_queue_head_init(&fnic->fip_frame_queue);
+ spin_lock_irqsave(&fnic_list_lock, flags);
+ if (!fnic_fip_queue) {
+ fnic_fip_queue =
+ create_singlethread_workqueue("fnic_fip_q");
+ if (!fnic_fip_queue) {
+ spin_unlock_irqrestore(&fnic_list_lock, flags);
+ printk(KERN_ERR PFX "fnic FIP work queue "
+ "create failed\n");
+ err = -ENOMEM;
+ goto err_out_free_max_pool;
+ }
+ }
+ spin_unlock_irqrestore(&fnic_list_lock, flags);
+ INIT_LIST_HEAD(&fnic->evlist);
+ INIT_LIST_HEAD(&fnic->vlans);
} else {
shost_printk(KERN_INFO, fnic->lport->host,
"firmware uses non-FIP mode\n");
@@ -625,6 +664,9 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
}
fnic->state = FNIC_IN_FC_MODE;
+ atomic_set(&fnic->in_flight, 0);
+ fnic->state_flags = FNIC_FLAGS_NONE;
+
/* Enable hardware stripping of vlan header on ingress */
fnic_set_nic_config(fnic, 0, 0, 0, 0, 0, 0, 1);
@@ -774,7 +816,7 @@ err_out:
return err;
}
-static void __devexit fnic_remove(struct pci_dev *pdev)
+static void fnic_remove(struct pci_dev *pdev)
{
struct fnic *fnic = pci_get_drvdata(pdev);
struct fc_lport *lp = fnic->lport;
@@ -801,6 +843,13 @@ static void __devexit fnic_remove(struct pci_dev *pdev)
skb_queue_purge(&fnic->frame_queue);
skb_queue_purge(&fnic->tx_queue);
+ if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+ del_timer_sync(&fnic->fip_timer);
+ skb_queue_purge(&fnic->fip_frame_queue);
+ fnic_fcoe_reset_vlans(fnic);
+ fnic_fcoe_evlist_free(fnic);
+ }
+
/*
* Log off the fabric. This stops all remote ports, dns port,
* logs off the fabric. This flushes all rport, disc, lport work
@@ -849,7 +898,7 @@ static struct pci_driver fnic_driver = {
.name = DRV_NAME,
.id_table = fnic_id_table,
.probe = fnic_probe,
- .remove = __devexit_p(fnic_remove),
+ .remove = fnic_remove,
};
static int __init fnic_init_module(void)
@@ -859,6 +908,14 @@ static int __init fnic_init_module(void)
printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION);
+ /* Allocate memory for trace buffer */
+ err = fnic_trace_buf_init();
+ if (err < 0) {
+ printk(KERN_ERR PFX "Trace buffer initialization Failed "
+ "Fnic Tracing utility is disabled\n");
+ fnic_trace_free();
+ }
+
/* Create a cache for allocation of default size sgls */
len = sizeof(struct fnic_dflt_sgl_list);
fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create
@@ -875,8 +932,8 @@ static int __init fnic_init_module(void)
len = sizeof(struct fnic_sgl_list);
fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create
("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
- SLAB_HWCACHE_ALIGN,
- NULL);
+ SLAB_HWCACHE_ALIGN,
+ NULL);
if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) {
printk(KERN_ERR PFX "failed to create fnic max sgl slab\n");
err = -ENOMEM;
@@ -929,6 +986,7 @@ err_create_fnic_ioreq_slab:
err_create_fnic_sgl_slab_max:
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
err_create_fnic_sgl_slab_dflt:
+ fnic_trace_free();
return err;
}
@@ -936,10 +994,15 @@ static void __exit fnic_cleanup_module(void)
{
pci_unregister_driver(&fnic_driver);
destroy_workqueue(fnic_event_queue);
+ if (fnic_fip_queue) {
+ flush_workqueue(fnic_fip_queue);
+ destroy_workqueue(fnic_fip_queue);
+ }
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
kmem_cache_destroy(fnic_io_req_cache);
fc_release_transport(fnic_fc_transport);
+ fnic_trace_free();
}
module_init(fnic_init_module);
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index c40ce52..a97e6e5 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -47,6 +47,7 @@ const char *fnic_state_str[] = {
};
static const char *fnic_ioreq_state_str[] = {
+ [FNIC_IOREQ_NOT_INITED] = "FNIC_IOREQ_NOT_INITED",
[FNIC_IOREQ_CMD_PENDING] = "FNIC_IOREQ_CMD_PENDING",
[FNIC_IOREQ_ABTS_PENDING] = "FNIC_IOREQ_ABTS_PENDING",
[FNIC_IOREQ_ABTS_COMPLETE] = "FNIC_IOREQ_ABTS_COMPLETE",
@@ -165,6 +166,33 @@ static int free_wq_copy_descs(struct fnic *fnic, struct vnic_wq_copy *wq)
}
+/**
+ * __fnic_set_state_flags
+ * Sets/Clears bits in fnic's state_flags
+ **/
+void
+__fnic_set_state_flags(struct fnic *fnic, unsigned long st_flags,
+ unsigned long clearbits)
+{
+ struct Scsi_Host *host = fnic->lport->host;
+ int sh_locked = spin_is_locked(host->host_lock);
+ unsigned long flags = 0;
+
+ if (!sh_locked)
+ spin_lock_irqsave(host->host_lock, flags);
+
+ if (clearbits)
+ fnic->state_flags &= ~st_flags;
+ else
+ fnic->state_flags |= st_flags;
+
+ if (!sh_locked)
+ spin_unlock_irqrestore(host->host_lock, flags);
+
+ return;
+}
+
+
/*
* fnic_fw_reset_handler
* Routine to send reset msg to fw
@@ -175,9 +203,16 @@ int fnic_fw_reset_handler(struct fnic *fnic)
int ret = 0;
unsigned long flags;
+ /* indicate fwreset to io path */
+ fnic_set_state_flags(fnic, FNIC_FLAGS_FWRESET);
+
skb_queue_purge(&fnic->frame_queue);
skb_queue_purge(&fnic->tx_queue);
+ /* wait for io cmpl */
+ while (atomic_read(&fnic->in_flight))
+ schedule_timeout(msecs_to_jiffies(1));
+
spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);
if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
@@ -193,9 +228,12 @@ int fnic_fw_reset_handler(struct fnic *fnic)
if (!ret)
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"Issued fw reset\n");
- else
+ else {
+ fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"Failed to issue fw reset\n");
+ }
+
return ret;
}
@@ -312,6 +350,8 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
if (unlikely(!vnic_wq_copy_desc_avail(wq))) {
spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags);
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "fnic_queue_wq_copy_desc failure - no descriptors\n");
return SCSI_MLQUEUE_HOST_BUSY;
}
@@ -351,16 +391,20 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
*/
static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
{
- struct fc_lport *lp;
+ struct fc_lport *lp = shost_priv(sc->device->host);
struct fc_rport *rport;
- struct fnic_io_req *io_req;
- struct fnic *fnic;
+ struct fnic_io_req *io_req = NULL;
+ struct fnic *fnic = lport_priv(lp);
struct vnic_wq_copy *wq;
int ret;
- int sg_count;
+ u64 cmd_trace;
+ int sg_count = 0;
unsigned long flags;
unsigned long ptr;
+ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
rport = starget_to_rport(scsi_target(sc->device));
ret = fc_remote_port_chkready(rport);
if (ret) {
@@ -369,20 +413,21 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
return 0;
}
- lp = shost_priv(sc->device->host);
if (lp->state != LPORT_ST_READY || !(lp->link_up))
return SCSI_MLQUEUE_HOST_BUSY;
+ atomic_inc(&fnic->in_flight);
+
/*
* Release host lock, use driver resource specific locks from here.
* Don't re-enable interrupts in case they were disabled prior to the
* caller disabling them.
*/
spin_unlock(lp->host->host_lock);
+ CMD_STATE(sc) = FNIC_IOREQ_NOT_INITED;
+ CMD_FLAGS(sc) = FNIC_NO_FLAGS;
/* Get a new io_req for this SCSI IO */
- fnic = lport_priv(lp);
-
io_req = mempool_alloc(fnic->io_req_pool, GFP_ATOMIC);
if (!io_req) {
ret = SCSI_MLQUEUE_HOST_BUSY;
@@ -393,6 +438,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
/* Map the data buffer */
sg_count = scsi_dma_map(sc);
if (sg_count < 0) {
+ FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
+ sc->request->tag, sc, 0, sc->cmnd[0],
+ sg_count, CMD_STATE(sc));
mempool_free(io_req, fnic->io_req_pool);
goto out;
}
@@ -427,8 +475,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
/* initialize rest of io_req */
io_req->port_id = rport->port_id;
+ io_req->start_time = jiffies;
CMD_STATE(sc) = FNIC_IOREQ_CMD_PENDING;
CMD_SP(sc) = (char *)io_req;
+ CMD_FLAGS(sc) |= FNIC_IO_INITIALIZED;
sc->scsi_done = done;
/* create copy wq desc and enqueue it */
@@ -440,7 +490,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
* refetch the pointer under the lock.
*/
spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
-
+ FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
+ sc->request->tag, sc, 0, 0, 0,
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
CMD_SP(sc) = NULL;
@@ -450,8 +502,21 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
}
+ } else {
+ /* REVISIT: Use per IO lock in the final code */
+ CMD_FLAGS(sc) |= FNIC_IO_ISSUED;
}
out:
+ cmd_trace = ((u64)sc->cmnd[0] << 56 | (u64)sc->cmnd[7] << 40 |
+ (u64)sc->cmnd[8] << 32 | (u64)sc->cmnd[2] << 24 |
+ (u64)sc->cmnd[3] << 16 | (u64)sc->cmnd[4] << 8 |
+ sc->cmnd[5]);
+
+ FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
+ sc->request->tag, sc, io_req,
+ sg_count, cmd_trace,
+ (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
+ atomic_dec(&fnic->in_flight);
/* acquire host lock before returning to SCSI */
spin_lock(lp->host->host_lock);
return ret;
@@ -529,6 +594,8 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
fnic_flush_tx(fnic);
reset_cmpl_handler_end:
+ fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET);
+
return ret;
}
@@ -622,6 +689,7 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
struct vnic_wq_copy *wq;
u16 request_out = desc->u.ack.request_out;
unsigned long flags;
+ u64 *ox_id_tag = (u64 *)(void *)desc;
/* mark the ack state */
wq = &fnic->wq_copy[cq_index - fnic->raw_wq_count - fnic->rq_count];
@@ -632,6 +700,9 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic,
fnic->fw_ack_recd[0] = 1;
}
spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
+ FNIC_TRACE(fnic_fcpio_ack_handler,
+ fnic->lport->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3],
+ ox_id_tag[4], ox_id_tag[5]);
}
/*
@@ -651,27 +722,53 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
struct scsi_cmnd *sc;
unsigned long flags;
spinlock_t *io_lock;
+ u64 cmd_trace;
+ unsigned long start_time;
/* Decode the cmpl description to get the io_req id */
fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
fcpio_tag_id_dec(&tag, &id);
+ icmnd_cmpl = &desc->u.icmnd_cmpl;
- if (id >= FNIC_MAX_IO_REQ)
+ if (id >= FNIC_MAX_IO_REQ) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "Tag out of range tag %x hdr status = %s\n",
+ id, fnic_fcpio_status_to_str(hdr_status));
return;
+ }
sc = scsi_host_find_tag(fnic->lport->host, id);
WARN_ON_ONCE(!sc);
- if (!sc)
+ if (!sc) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "icmnd_cmpl sc is null - "
+ "hdr status = %s tag = 0x%x desc = 0x%p\n",
+ fnic_fcpio_status_to_str(hdr_status), id, desc);
+ FNIC_TRACE(fnic_fcpio_icmnd_cmpl_handler,
+ fnic->lport->host->host_no, id,
+ ((u64)icmnd_cmpl->_resvd0[1] << 16 |
+ (u64)icmnd_cmpl->_resvd0[0]),
+ ((u64)hdr_status << 16 |
+ (u64)icmnd_cmpl->scsi_status << 8 |
+ (u64)icmnd_cmpl->flags), desc,
+ (u64)icmnd_cmpl->residual, 0);
return;
+ }
io_lock = fnic_io_lock_hash(fnic, sc);
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
WARN_ON_ONCE(!io_req);
if (!io_req) {
+ CMD_FLAGS(sc) |= FNIC_IO_REQ_NULL;
spin_unlock_irqrestore(io_lock, flags);
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "icmnd_cmpl io_req is null - "
+ "hdr status = %s tag = 0x%x sc 0x%p\n",
+ fnic_fcpio_status_to_str(hdr_status), id, sc);
return;
}
+ start_time = io_req->start_time;
/* firmware completed the io */
io_req->io_completed = 1;
@@ -682,6 +779,28 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
*/
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
spin_unlock_irqrestore(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_IO_ABTS_PENDING;
+ switch (hdr_status) {
+ case FCPIO_SUCCESS:
+ CMD_FLAGS(sc) |= FNIC_IO_DONE;
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "icmnd_cmpl ABTS pending hdr status = %s "
+ "sc 0x%p scsi_status %x residual %d\n",
+ fnic_fcpio_status_to_str(hdr_status), sc,
+ icmnd_cmpl->scsi_status,
+ icmnd_cmpl->residual);
+ break;
+ case FCPIO_ABORTED:
+ CMD_FLAGS(sc) |= FNIC_IO_ABORTED;
+ break;
+ default:
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "icmnd_cmpl abts pending "
+ "hdr status = %s tag = 0x%x sc = 0x%p\n",
+ fnic_fcpio_status_to_str(hdr_status),
+ id, sc);
+ break;
+ }
return;
}
@@ -765,6 +884,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
/* Break link with the SCSI command */
CMD_SP(sc) = NULL;
+ CMD_FLAGS(sc) |= FNIC_IO_DONE;
spin_unlock_irqrestore(io_lock, flags);
@@ -772,6 +892,20 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
mempool_free(io_req, fnic->io_req_pool);
+ cmd_trace = ((u64)hdr_status << 56) |
+ (u64)icmnd_cmpl->scsi_status << 48 |
+ (u64)icmnd_cmpl->flags << 40 | (u64)sc->cmnd[0] << 32 |
+ (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
+ (u64)sc->cmnd[4] << 8 | sc->cmnd[5];
+
+ FNIC_TRACE(fnic_fcpio_icmnd_cmpl_handler,
+ sc->device->host->host_no, id, sc,
+ ((u64)icmnd_cmpl->_resvd0[1] << 56 |
+ (u64)icmnd_cmpl->_resvd0[0] << 48 |
+ jiffies_to_msecs(jiffies - start_time)),
+ desc, cmd_trace,
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+
if (sc->sc_data_direction == DMA_FROM_DEVICE) {
fnic->lport->host_stats.fcp_input_requests++;
fnic->fcp_input_bytes += xfer_len;
@@ -784,7 +918,6 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
/* Call SCSI completion function to complete the IO */
if (sc->scsi_done)
sc->scsi_done(sc);
-
}
/* fnic_fcpio_itmf_cmpl_handler
@@ -801,28 +934,54 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
struct fnic_io_req *io_req;
unsigned long flags;
spinlock_t *io_lock;
+ unsigned long start_time;
fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
fcpio_tag_id_dec(&tag, &id);
- if ((id & FNIC_TAG_MASK) >= FNIC_MAX_IO_REQ)
+ if ((id & FNIC_TAG_MASK) >= FNIC_MAX_IO_REQ) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "Tag out of range tag %x hdr status = %s\n",
+ id, fnic_fcpio_status_to_str(hdr_status));
return;
+ }
sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
WARN_ON_ONCE(!sc);
- if (!sc)
+ if (!sc) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
+ fnic_fcpio_status_to_str(hdr_status), id);
return;
-
+ }
io_lock = fnic_io_lock_hash(fnic, sc);
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
WARN_ON_ONCE(!io_req);
if (!io_req) {
spin_unlock_irqrestore(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL;
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "itmf_cmpl io_req is null - "
+ "hdr status = %s tag = 0x%x sc 0x%p\n",
+ fnic_fcpio_status_to_str(hdr_status), id, sc);
return;
}
+ start_time = io_req->start_time;
- if (id & FNIC_TAG_ABORT) {
+ if ((id & FNIC_TAG_ABORT) && (id & FNIC_TAG_DEV_RST)) {
+ /* Abort and terminate completion of device reset req */
+ /* REVISIT : Add asserts about various flags */
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "dev reset abts cmpl recd. id %x status %s\n",
+ id, fnic_fcpio_status_to_str(hdr_status));
+ CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE;
+ CMD_ABTS_STATUS(sc) = hdr_status;
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_DONE;
+ if (io_req->abts_done)
+ complete(io_req->abts_done);
+ spin_unlock_irqrestore(io_lock, flags);
+ } else if (id & FNIC_TAG_ABORT) {
/* Completion of abort cmd */
if (CMD_STATE(sc) != FNIC_IOREQ_ABTS_PENDING) {
/* This is a late completion. Ignore it */
@@ -832,6 +991,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE;
CMD_ABTS_STATUS(sc) = hdr_status;
+ CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"abts cmpl recd. id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
@@ -855,14 +1015,58 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
- if (sc->scsi_done)
+ if (sc->scsi_done) {
+ FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
+ sc->device->host->host_no, id,
+ sc,
+ jiffies_to_msecs(jiffies - start_time),
+ desc,
+ (((u64)hdr_status << 40) |
+ (u64)sc->cmnd[0] << 32 |
+ (u64)sc->cmnd[2] << 24 |
+ (u64)sc->cmnd[3] << 16 |
+ (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
+ (((u64)CMD_FLAGS(sc) << 32) |
+ CMD_STATE(sc)));
sc->scsi_done(sc);
+ }
}
} else if (id & FNIC_TAG_DEV_RST) {
/* Completion of device reset */
CMD_LR_STATUS(sc) = hdr_status;
+ if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
+ spin_unlock_irqrestore(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_ABTS_PENDING;
+ FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
+ sc->device->host->host_no, id, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ desc, 0,
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "Terminate pending "
+ "dev reset cmpl recd. id %d status %s\n",
+ (int)(id & FNIC_TAG_MASK),
+ fnic_fcpio_status_to_str(hdr_status));
+ return;
+ }
+ if (CMD_FLAGS(sc) & FNIC_DEV_RST_TIMED_OUT) {
+ /* Need to wait for terminate completion */
+ spin_unlock_irqrestore(io_lock, flags);
+ FNIC_TRACE(fnic_fcpio_itmf_cmpl_handler,
+ sc->device->host->host_no, id, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ desc, 0,
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "dev reset cmpl recd after time out. "
+ "id %d status %s\n",
+ (int)(id & FNIC_TAG_MASK),
+ fnic_fcpio_status_to_str(hdr_status));
+ return;
+ }
CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE;
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_DONE;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"dev reset cmpl recd. id %d status %s\n",
(int)(id & FNIC_TAG_MASK),
@@ -889,7 +1093,6 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
struct fcpio_fw_req *desc)
{
struct fnic *fnic = vnic_dev_priv(vdev);
- int ret = 0;
switch (desc->hdr.type) {
case FCPIO_ACK: /* fw copied copy wq desc to its queue */
@@ -906,11 +1109,11 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */
case FCPIO_FLOGI_FIP_REG_CMPL: /* fw completed flogi_fip_reg */
- ret = fnic_fcpio_flogi_reg_cmpl_handler(fnic, desc);
+ fnic_fcpio_flogi_reg_cmpl_handler(fnic, desc);
break;
case FCPIO_RESET_CMPL: /* fw completed reset */
- ret = fnic_fcpio_fw_reset_cmpl_handler(fnic, desc);
+ fnic_fcpio_fw_reset_cmpl_handler(fnic, desc);
break;
default:
@@ -920,7 +1123,7 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev,
break;
}
- return ret;
+ return 0;
}
/*
@@ -950,6 +1153,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
unsigned long flags = 0;
struct scsi_cmnd *sc;
spinlock_t *io_lock;
+ unsigned long start_time = 0;
for (i = 0; i < FNIC_MAX_IO_REQ; i++) {
if (i == exclude_id)
@@ -962,6 +1166,23 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
io_lock = fnic_io_lock_hash(fnic, sc);
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
+ if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
+ !(CMD_FLAGS(sc) & FNIC_DEV_RST_DONE)) {
+ /*
+ * We will be here only when FW completes reset
+ * without sending completions for outstanding ios.
+ */
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_DONE;
+ if (io_req && io_req->dr_done)
+ complete(io_req->dr_done);
+ else if (io_req && io_req->abts_done)
+ complete(io_req->abts_done);
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ } else if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ }
if (!io_req) {
spin_unlock_irqrestore(io_lock, flags);
goto cleanup_scsi_cmd;
@@ -975,6 +1196,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
* If there is a scsi_cmnd associated with this io_req, then
* free the corresponding state
*/
+ start_time = io_req->start_time;
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
@@ -984,8 +1206,18 @@ cleanup_scsi_cmd:
" DID_TRANSPORT_DISRUPTED\n");
/* Complete the command to SCSI */
- if (sc->scsi_done)
+ if (sc->scsi_done) {
+ FNIC_TRACE(fnic_cleanup_io,
+ sc->device->host->host_no, i, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ 0, ((u64)sc->cmnd[0] << 32 |
+ (u64)sc->cmnd[2] << 24 |
+ (u64)sc->cmnd[3] << 16 |
+ (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+
sc->scsi_done(sc);
+ }
}
}
@@ -998,6 +1230,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
struct scsi_cmnd *sc;
unsigned long flags;
spinlock_t *io_lock;
+ unsigned long start_time = 0;
/* get the tag reference */
fcpio_tag_id_dec(&desc->hdr.tag, &id);
@@ -1027,6 +1260,7 @@ void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
spin_unlock_irqrestore(io_lock, flags);
+ start_time = io_req->start_time;
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
@@ -1035,8 +1269,17 @@ wq_copy_cleanup_scsi_cmd:
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "wq_copy_cleanup_handler:"
" DID_NO_CONNECT\n");
- if (sc->scsi_done)
+ if (sc->scsi_done) {
+ FNIC_TRACE(fnic_wq_copy_cleanup_handler,
+ sc->device->host->host_no, id, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ 0, ((u64)sc->cmnd[0] << 32 |
+ (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
+ (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+
sc->scsi_done(sc);
+ }
}
static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
@@ -1044,8 +1287,18 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
struct fnic_io_req *io_req)
{
struct vnic_wq_copy *wq = &fnic->wq_copy[0];
+ struct Scsi_Host *host = fnic->lport->host;
unsigned long flags;
+ spin_lock_irqsave(host->host_lock, flags);
+ if (unlikely(fnic_chk_state_flags_locked(fnic,
+ FNIC_FLAGS_IO_BLOCKED))) {
+ spin_unlock_irqrestore(host->host_lock, flags);
+ return 1;
+ } else
+ atomic_inc(&fnic->in_flight);
+ spin_unlock_irqrestore(host->host_lock, flags);
+
spin_lock_irqsave(&fnic->wq_copy_lock[0], flags);
if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
@@ -1053,6 +1306,9 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
if (!vnic_wq_copy_desc_avail(wq)) {
spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
+ atomic_dec(&fnic->in_flight);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "fnic_queue_abort_io_req: failure: no descriptors\n");
return 1;
}
fnic_queue_wq_copy_desc_itmf(wq, tag | FNIC_TAG_ABORT,
@@ -1060,12 +1316,15 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
fnic->config.ra_tov, fnic->config.ed_tov);
spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags);
+ atomic_dec(&fnic->in_flight);
+
return 0;
}
-void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
+static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
{
int tag;
+ int abt_tag;
struct fnic_io_req *io_req;
spinlock_t *io_lock;
unsigned long flags;
@@ -1075,13 +1334,14 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
FNIC_SCSI_DBG(KERN_DEBUG,
fnic->lport->host,
- "fnic_rport_reset_exch called portid 0x%06x\n",
+ "fnic_rport_exch_reset called portid 0x%06x\n",
port_id);
if (fnic->in_remove)
return;
for (tag = 0; tag < FNIC_MAX_IO_REQ; tag++) {
+ abt_tag = tag;
sc = scsi_host_find_tag(fnic->lport->host, tag);
if (!sc)
continue;
@@ -1096,6 +1356,15 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
continue;
}
+ if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
+ (!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "fnic_rport_exch_reset dev rst not pending sc 0x%p\n",
+ sc);
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ }
+
/*
* Found IO that is still pending with firmware and
* belongs to rport that went away
@@ -1104,9 +1373,29 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
spin_unlock_irqrestore(io_lock, flags);
continue;
}
+ if (io_req->abts_done) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "fnic_rport_exch_reset: io_req->abts_done is set "
+ "state is %s\n",
+ fnic_ioreq_state_to_str(CMD_STATE(sc)));
+ }
+
+ if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED)) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "rport_exch_reset "
+ "IO not yet issued %p tag 0x%x flags "
+ "%x state %d\n",
+ sc, tag, CMD_FLAGS(sc), CMD_STATE(sc));
+ }
old_ioreq_state = CMD_STATE(sc);
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
+ if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
+ abt_tag = (tag | FNIC_TAG_DEV_RST);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "fnic_rport_exch_reset dev rst sc 0x%p\n",
+ sc);
+ }
BUG_ON(io_req->abts_done);
@@ -1118,7 +1407,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
- if (fnic_queue_abort_io_req(fnic, tag,
+ if (fnic_queue_abort_io_req(fnic, abt_tag,
FCPIO_ITMF_ABT_TASK_TERM,
fc_lun.scsi_lun, io_req)) {
/*
@@ -1127,12 +1416,17 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
* aborted later by scsi_eh, or cleaned up during
* lun reset
*/
- io_lock = fnic_io_lock_hash(fnic, sc);
-
spin_lock_irqsave(io_lock, flags);
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
CMD_STATE(sc) = old_ioreq_state;
spin_unlock_irqrestore(io_lock, flags);
+ } else {
+ spin_lock_irqsave(io_lock, flags);
+ if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
+ else
+ CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
+ spin_unlock_irqrestore(io_lock, flags);
}
}
@@ -1141,6 +1435,7 @@ void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
void fnic_terminate_rport_io(struct fc_rport *rport)
{
int tag;
+ int abt_tag;
struct fnic_io_req *io_req;
spinlock_t *io_lock;
unsigned long flags;
@@ -1154,14 +1449,15 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
FNIC_SCSI_DBG(KERN_DEBUG,
fnic->lport->host, "fnic_terminate_rport_io called"
- " wwpn 0x%llx, wwnn0x%llx, portid 0x%06x\n",
- rport->port_name, rport->node_name,
+ " wwpn 0x%llx, wwnn0x%llx, rport 0x%p, portid 0x%06x\n",
+ rport->port_name, rport->node_name, rport,
rport->port_id);
if (fnic->in_remove)
return;
for (tag = 0; tag < FNIC_MAX_IO_REQ; tag++) {
+ abt_tag = tag;
sc = scsi_host_find_tag(fnic->lport->host, tag);
if (!sc)
continue;
@@ -1180,6 +1476,14 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
continue;
}
+ if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
+ (!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "fnic_terminate_rport_io dev rst not pending sc 0x%p\n",
+ sc);
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ }
/*
* Found IO that is still pending with firmware and
* belongs to rport that went away
@@ -1188,9 +1492,27 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
spin_unlock_irqrestore(io_lock, flags);
continue;
}
+ if (io_req->abts_done) {
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "fnic_terminate_rport_io: io_req->abts_done is set "
+ "state is %s\n",
+ fnic_ioreq_state_to_str(CMD_STATE(sc)));
+ }
+ if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED)) {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "fnic_terminate_rport_io "
+ "IO not yet issued %p tag 0x%x flags "
+ "%x state %d\n",
+ sc, tag, CMD_FLAGS(sc), CMD_STATE(sc));
+ }
old_ioreq_state = CMD_STATE(sc);
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
+ if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
+ abt_tag = (tag | FNIC_TAG_DEV_RST);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "fnic_terminate_rport_io dev rst sc 0x%p\n", sc);
+ }
BUG_ON(io_req->abts_done);
@@ -1203,7 +1525,7 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
- if (fnic_queue_abort_io_req(fnic, tag,
+ if (fnic_queue_abort_io_req(fnic, abt_tag,
FCPIO_ITMF_ABT_TASK_TERM,
fc_lun.scsi_lun, io_req)) {
/*
@@ -1212,12 +1534,17 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
* aborted later by scsi_eh, or cleaned up during
* lun reset
*/
- io_lock = fnic_io_lock_hash(fnic, sc);
-
spin_lock_irqsave(io_lock, flags);
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
CMD_STATE(sc) = old_ioreq_state;
spin_unlock_irqrestore(io_lock, flags);
+ } else {
+ spin_lock_irqsave(io_lock, flags);
+ if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
+ else
+ CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
+ spin_unlock_irqrestore(io_lock, flags);
}
}
@@ -1232,13 +1559,15 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
{
struct fc_lport *lp;
struct fnic *fnic;
- struct fnic_io_req *io_req;
+ struct fnic_io_req *io_req = NULL;
struct fc_rport *rport;
spinlock_t *io_lock;
unsigned long flags;
+ unsigned long start_time = 0;
int ret = SUCCESS;
- u32 task_req;
+ u32 task_req = 0;
struct scsi_lun fc_lun;
+ int tag;
DECLARE_COMPLETION_ONSTACK(tm_done);
/* Wait for rport to unblock */
@@ -1249,9 +1578,13 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
fnic = lport_priv(lp);
rport = starget_to_rport(scsi_target(sc->device));
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Abort Cmd called FCID 0x%x, LUN 0x%x TAG %d\n",
- rport->port_id, sc->device->lun, sc->request->tag);
+ tag = sc->request->tag;
+ FNIC_SCSI_DBG(KERN_DEBUG,
+ fnic->lport->host,
+ "Abort Cmd called FCID 0x%x, LUN 0x%x TAG %x flags %x\n",
+ rport->port_id, sc->device->lun, tag, CMD_FLAGS(sc));
+
+ CMD_FLAGS(sc) = FNIC_NO_FLAGS;
if (lp->state != LPORT_ST_READY || !(lp->link_up)) {
ret = FAILED;
@@ -1318,6 +1651,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
ret = FAILED;
goto fnic_abort_cmd_end;
}
+ if (task_req == FCPIO_ITMF_ABT_TASK)
+ CMD_FLAGS(sc) |= FNIC_IO_ABTS_ISSUED;
+ else
+ CMD_FLAGS(sc) |= FNIC_IO_TERM_ISSUED;
/*
* We queued an abort IO, wait for its completion.
@@ -1336,6 +1673,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
io_req = (struct fnic_io_req *)CMD_SP(sc);
if (!io_req) {
spin_unlock_irqrestore(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL;
ret = FAILED;
goto fnic_abort_cmd_end;
}
@@ -1344,6 +1682,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
/* fw did not complete abort, timed out */
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
spin_unlock_irqrestore(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_TIMED_OUT;
ret = FAILED;
goto fnic_abort_cmd_end;
}
@@ -1359,12 +1698,21 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
spin_unlock_irqrestore(io_lock, flags);
+ start_time = io_req->start_time;
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
fnic_abort_cmd_end:
+ FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no,
+ sc->request->tag, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ 0, ((u64)sc->cmnd[0] << 32 |
+ (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
+ (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Returning from abort cmd %s\n",
+ "Returning from abort cmd type %x %s\n", task_req,
(ret == SUCCESS) ?
"SUCCESS" : "FAILED");
return ret;
@@ -1375,16 +1723,28 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
struct fnic_io_req *io_req)
{
struct vnic_wq_copy *wq = &fnic->wq_copy[0];
+ struct Scsi_Host *host = fnic->lport->host;
struct scsi_lun fc_lun;
int ret = 0;
unsigned long intr_flags;
+ spin_lock_irqsave(host->host_lock, intr_flags);
+ if (unlikely(fnic_chk_state_flags_locked(fnic,
+ FNIC_FLAGS_IO_BLOCKED))) {
+ spin_unlock_irqrestore(host->host_lock, intr_flags);
+ return FAILED;
+ } else
+ atomic_inc(&fnic->in_flight);
+ spin_unlock_irqrestore(host->host_lock, intr_flags);
+
spin_lock_irqsave(&fnic->wq_copy_lock[0], intr_flags);
if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[0])
free_wq_copy_descs(fnic, wq);
if (!vnic_wq_copy_desc_avail(wq)) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "queue_dr_io_req failure - no descriptors\n");
ret = -EAGAIN;
goto lr_io_req_end;
}
@@ -1399,6 +1759,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
lr_io_req_end:
spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags);
+ atomic_dec(&fnic->in_flight);
return ret;
}
@@ -1412,7 +1773,7 @@ lr_io_req_end:
static int fnic_clean_pending_aborts(struct fnic *fnic,
struct scsi_cmnd *lr_sc)
{
- int tag;
+ int tag, abt_tag;
struct fnic_io_req *io_req;
spinlock_t *io_lock;
unsigned long flags;
@@ -1421,6 +1782,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
struct scsi_lun fc_lun;
struct scsi_device *lun_dev = lr_sc->device;
DECLARE_COMPLETION_ONSTACK(tm_done);
+ enum fnic_ioreq_state old_ioreq_state;
for (tag = 0; tag < FNIC_MAX_IO_REQ; tag++) {
sc = scsi_host_find_tag(fnic->lport->host, tag);
@@ -1449,7 +1811,41 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
"Found IO in %s on lun\n",
fnic_ioreq_state_to_str(CMD_STATE(sc)));
- BUG_ON(CMD_STATE(sc) != FNIC_IOREQ_ABTS_PENDING);
+ if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ }
+ if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
+ (!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "%s dev rst not pending sc 0x%p\n", __func__,
+ sc);
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ }
+ old_ioreq_state = CMD_STATE(sc);
+ /*
+ * Any pending IO issued prior to reset is expected to be
+ * in abts pending state, if not we need to set
+ * FNIC_IOREQ_ABTS_PENDING to indicate the IO is abort pending.
+ * When IO is completed, the IO will be handed over and
+ * handled in this function.
+ */
+ CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
+
+ if (io_req->abts_done)
+ shost_printk(KERN_ERR, fnic->lport->host,
+ "%s: io_req->abts_done is set state is %s\n",
+ __func__, fnic_ioreq_state_to_str(CMD_STATE(sc)));
+
+ BUG_ON(io_req->abts_done);
+
+ abt_tag = tag;
+ if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
+ abt_tag |= FNIC_TAG_DEV_RST;
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "%s: dev rst sc 0x%p\n", __func__, sc);
+ }
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
io_req->abts_done = &tm_done;
@@ -1458,17 +1854,25 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
- if (fnic_queue_abort_io_req(fnic, tag,
+ if (fnic_queue_abort_io_req(fnic, abt_tag,
FCPIO_ITMF_ABT_TASK_TERM,
fc_lun.scsi_lun, io_req)) {
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
if (io_req)
io_req->abts_done = NULL;
+ if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
+ CMD_STATE(sc) = old_ioreq_state;
spin_unlock_irqrestore(io_lock, flags);
ret = 1;
goto clean_pending_aborts_end;
+ } else {
+ spin_lock_irqsave(io_lock, flags);
+ if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
+ spin_unlock_irqrestore(io_lock, flags);
}
+ CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
wait_for_completion_timeout(&tm_done,
msecs_to_jiffies
@@ -1479,8 +1883,8 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
io_req = (struct fnic_io_req *)CMD_SP(sc);
if (!io_req) {
spin_unlock_irqrestore(io_lock, flags);
- ret = 1;
- goto clean_pending_aborts_end;
+ CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL;
+ continue;
}
io_req->abts_done = NULL;
@@ -1488,6 +1892,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
/* if abort is still pending with fw, fail */
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
spin_unlock_irqrestore(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE;
ret = 1;
goto clean_pending_aborts_end;
}
@@ -1498,10 +1903,75 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
mempool_free(io_req, fnic->io_req_pool);
}
+ schedule_timeout(msecs_to_jiffies(2 * fnic->config.ed_tov));
+
+ /* walk again to check, if IOs are still pending in fw */
+ if (fnic_is_abts_pending(fnic, lr_sc))
+ ret = FAILED;
+
clean_pending_aborts_end:
return ret;
}
+/**
+ * fnic_scsi_host_start_tag
+ * Allocates tagid from host's tag list
+ **/
+static inline int
+fnic_scsi_host_start_tag(struct fnic *fnic, struct scsi_cmnd *sc)
+{
+ struct blk_queue_tag *bqt = fnic->lport->host->bqt;
+ int tag, ret = SCSI_NO_TAG;
+
+ BUG_ON(!bqt);
+ if (!bqt) {
+ pr_err("Tags are not supported\n");
+ goto end;
+ }
+
+ do {
+ tag = find_next_zero_bit(bqt->tag_map, bqt->max_depth, 1);
+ if (tag >= bqt->max_depth) {
+ pr_err("Tag allocation failure\n");
+ goto end;
+ }
+ } while (test_and_set_bit(tag, bqt->tag_map));
+
+ bqt->tag_index[tag] = sc->request;
+ sc->request->tag = tag;
+ sc->tag = tag;
+ if (!sc->request->special)
+ sc->request->special = sc;
+
+ ret = tag;
+
+end:
+ return ret;
+}
+
+/**
+ * fnic_scsi_host_end_tag
+ * frees tag allocated by fnic_scsi_host_start_tag.
+ **/
+static inline void
+fnic_scsi_host_end_tag(struct fnic *fnic, struct scsi_cmnd *sc)
+{
+ struct blk_queue_tag *bqt = fnic->lport->host->bqt;
+ int tag = sc->request->tag;
+
+ if (tag == SCSI_NO_TAG)
+ return;
+
+ BUG_ON(!bqt || !bqt->tag_index[tag]);
+ if (!bqt)
+ return;
+
+ bqt->tag_index[tag] = NULL;
+ clear_bit(tag, bqt->tag_map);
+
+ return;
+}
+
/*
* SCSI Eh thread issues a Lun Reset when one or more commands on a LUN
* fail to get aborted. It calls driver's eh_device_reset with a SCSI command
@@ -1511,13 +1981,17 @@ int fnic_device_reset(struct scsi_cmnd *sc)
{
struct fc_lport *lp;
struct fnic *fnic;
- struct fnic_io_req *io_req;
+ struct fnic_io_req *io_req = NULL;
struct fc_rport *rport;
int status;
int ret = FAILED;
spinlock_t *io_lock;
unsigned long flags;
+ unsigned long start_time = 0;
+ struct scsi_lun fc_lun;
+ int tag = 0;
DECLARE_COMPLETION_ONSTACK(tm_done);
+ int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/
/* Wait for rport to unblock */
fc_block_scsi_eh(sc);
@@ -1529,8 +2003,8 @@ int fnic_device_reset(struct scsi_cmnd *sc)
rport = starget_to_rport(scsi_target(sc->device));
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
- "Device reset called FCID 0x%x, LUN 0x%x\n",
- rport->port_id, sc->device->lun);
+ "Device reset called FCID 0x%x, LUN 0x%x sc 0x%p\n",
+ rport->port_id, sc->device->lun, sc);
if (lp->state != LPORT_ST_READY || !(lp->link_up))
goto fnic_device_reset_end;
@@ -1539,6 +2013,16 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if (fc_remote_port_chkready(rport))
goto fnic_device_reset_end;
+ CMD_FLAGS(sc) = FNIC_DEVICE_RESET;
+ /* Allocate tag if not present */
+
+ tag = sc->request->tag;
+ if (unlikely(tag < 0)) {
+ tag = fnic_scsi_host_start_tag(fnic, sc);
+ if (unlikely(tag == SCSI_NO_TAG))
+ goto fnic_device_reset_end;
+ tag_gen_flag = 1;
+ }
io_lock = fnic_io_lock_hash(fnic, sc);
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
@@ -1562,8 +2046,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
CMD_LR_STATUS(sc) = FCPIO_INVALID_CODE;
spin_unlock_irqrestore(io_lock, flags);
- FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "TAG %d\n",
- sc->request->tag);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "TAG %x\n", tag);
/*
* issue the device reset, if enqueue failed, clean up the ioreq
@@ -1576,6 +2059,9 @@ int fnic_device_reset(struct scsi_cmnd *sc)
io_req->dr_done = NULL;
goto fnic_device_reset_clean;
}
+ spin_lock_irqsave(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_ISSUED;
+ spin_unlock_irqrestore(io_lock, flags);
/*
* Wait on the local completion for LUN reset. The io_req may be
@@ -1588,12 +2074,13 @@ int fnic_device_reset(struct scsi_cmnd *sc)
io_req = (struct fnic_io_req *)CMD_SP(sc);
if (!io_req) {
spin_unlock_irqrestore(io_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "io_req is null tag 0x%x sc 0x%p\n", tag, sc);
goto fnic_device_reset_end;
}
io_req->dr_done = NULL;
status = CMD_LR_STATUS(sc);
- spin_unlock_irqrestore(io_lock, flags);
/*
* If lun reset not completed, bail out with failed. io_req
@@ -1602,7 +2089,53 @@ int fnic_device_reset(struct scsi_cmnd *sc)
if (status == FCPIO_INVALID_CODE) {
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"Device reset timed out\n");
- goto fnic_device_reset_end;
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_TIMED_OUT;
+ spin_unlock_irqrestore(io_lock, flags);
+ int_to_scsilun(sc->device->lun, &fc_lun);
+ /*
+ * Issue abort and terminate on the device reset request.
+ * If q'ing of the abort fails, retry issue it after a delay.
+ */
+ while (1) {
+ spin_lock_irqsave(io_lock, flags);
+ if (CMD_FLAGS(sc) & FNIC_DEV_RST_TERM_ISSUED) {
+ spin_unlock_irqrestore(io_lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(io_lock, flags);
+ if (fnic_queue_abort_io_req(fnic,
+ tag | FNIC_TAG_DEV_RST,
+ FCPIO_ITMF_ABT_TASK_TERM,
+ fc_lun.scsi_lun, io_req)) {
+ wait_for_completion_timeout(&tm_done,
+ msecs_to_jiffies(FNIC_ABT_TERM_DELAY_TIMEOUT));
+ } else {
+ spin_lock_irqsave(io_lock, flags);
+ CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
+ CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
+ io_req->abts_done = &tm_done;
+ spin_unlock_irqrestore(io_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "Abort and terminate issued on Device reset "
+ "tag 0x%x sc 0x%p\n", tag, sc);
+ break;
+ }
+ }
+ while (1) {
+ spin_lock_irqsave(io_lock, flags);
+ if (!(CMD_FLAGS(sc) & FNIC_DEV_RST_DONE)) {
+ spin_unlock_irqrestore(io_lock, flags);
+ wait_for_completion_timeout(&tm_done,
+ msecs_to_jiffies(FNIC_LUN_RESET_TIMEOUT));
+ break;
+ } else {
+ io_req = (struct fnic_io_req *)CMD_SP(sc);
+ io_req->abts_done = NULL;
+ goto fnic_device_reset_clean;
+ }
+ }
+ } else {
+ spin_unlock_irqrestore(io_lock, flags);
}
/* Completed, but not successful, clean up the io_req, return fail */
@@ -1645,11 +2178,24 @@ fnic_device_reset_clean:
spin_unlock_irqrestore(io_lock, flags);
if (io_req) {
+ start_time = io_req->start_time;
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
}
fnic_device_reset_end:
+ FNIC_TRACE(fnic_device_reset, sc->device->host->host_no,
+ sc->request->tag, sc,
+ jiffies_to_msecs(jiffies - start_time),
+ 0, ((u64)sc->cmnd[0] << 32 |
+ (u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
+ (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
+ (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
+
+ /* free tag if it is allocated */
+ if (unlikely(tag_gen_flag))
+ fnic_scsi_host_end_tag(fnic, sc);
+
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"Returning from device reset %s\n",
(ret == SUCCESS) ?
@@ -1735,7 +2281,15 @@ void fnic_scsi_abort_io(struct fc_lport *lp)
DECLARE_COMPLETION_ONSTACK(remove_wait);
/* Issue firmware reset for fnic, wait for reset to complete */
+retry_fw_reset:
spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)) {
+ /* fw reset is in progress, poll for its completion */
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ schedule_timeout(msecs_to_jiffies(100));
+ goto retry_fw_reset;
+ }
+
fnic->remove_wait = &remove_wait;
old_state = fnic->state;
fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
@@ -1776,7 +2330,14 @@ void fnic_scsi_cleanup(struct fc_lport *lp)
struct fnic *fnic = lport_priv(lp);
/* issue fw reset */
+retry_fw_reset:
spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)) {
+ /* fw reset is in progress, poll for its completion */
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ schedule_timeout(msecs_to_jiffies(100));
+ goto retry_fw_reset;
+ }
old_state = fnic->state;
fnic->state = FNIC_IN_FC_TRANS_ETH_MODE;
fnic_update_mac_locked(fnic, fnic->ctlr.ctl_src_addr);
@@ -1822,3 +2383,59 @@ call_fc_exch_mgr_reset:
fc_exch_mgr_reset(lp, sid, did);
}
+
+/*
+ * fnic_is_abts_pending() is a helper function that
+ * walks through tag map to check if there is any IOs pending,if there is one,
+ * then it returns 1 (true), otherwise 0 (false)
+ * if @lr_sc is non NULL, then it checks IOs specific to particular LUN,
+ * otherwise, it checks for all IOs.
+ */
+int fnic_is_abts_pending(struct fnic *fnic, struct scsi_cmnd *lr_sc)
+{
+ int tag;
+ struct fnic_io_req *io_req;
+ spinlock_t *io_lock;
+ unsigned long flags;
+ int ret = 0;
+ struct scsi_cmnd *sc;
+ struct scsi_device *lun_dev = NULL;
+
+ if (lr_sc)
+ lun_dev = lr_sc->device;
+
+ /* walk again to check, if IOs are still pending in fw */
+ for (tag = 0; tag < FNIC_MAX_IO_REQ; tag++) {
+ sc = scsi_host_find_tag(fnic->lport->host, tag);
+ /*
+ * ignore this lun reset cmd or cmds that do not belong to
+ * this lun
+ */
+ if (!sc || (lr_sc && (sc->device != lun_dev || sc == lr_sc)))
+ continue;
+
+ io_lock = fnic_io_lock_hash(fnic, sc);
+ spin_lock_irqsave(io_lock, flags);
+
+ io_req = (struct fnic_io_req *)CMD_SP(sc);
+
+ if (!io_req || sc->device != lun_dev) {
+ spin_unlock_irqrestore(io_lock, flags);
+ continue;
+ }
+
+ /*
+ * Found IO that is still pending with firmware and
+ * belongs to the LUN that we are resetting
+ */
+ FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+ "Found IO in %s on lun\n",
+ fnic_ioreq_state_to_str(CMD_STATE(sc)));
+
+ if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
+ ret = 1;
+ spin_unlock_irqrestore(io_lock, flags);
+ }
+
+ return ret;
+}
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
new file mode 100644
index 0000000..23a60e3
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2012 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/mempool.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include "fnic_io.h"
+#include "fnic.h"
+
+unsigned int trace_max_pages;
+static int fnic_max_trace_entries;
+
+static unsigned long fnic_trace_buf_p;
+static DEFINE_SPINLOCK(fnic_trace_lock);
+
+static fnic_trace_dbg_t fnic_trace_entries;
+int fnic_tracing_enabled = 1;
+
+/*
+ * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information
+ *
+ * Description:
+ * This routine gets next available trace buffer entry location @wr_idx
+ * from allocated trace buffer pages and give that memory location
+ * to user to store the trace information.
+ *
+ * Return Value:
+ * This routine returns pointer to next available trace entry
+ * @fnic_buf_head for user to fill trace information.
+ */
+fnic_trace_data_t *fnic_trace_get_buf(void)
+{
+ unsigned long fnic_buf_head;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic_trace_lock, flags);
+
+ /*
+ * Get next available memory location for writing trace information
+ * at @wr_idx and increment @wr_idx
+ */
+ fnic_buf_head =
+ fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx];
+ fnic_trace_entries.wr_idx++;
+
+ /*
+ * Verify if trace buffer is full then change wd_idx to
+ * start from zero
+ */
+ if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries)
+ fnic_trace_entries.wr_idx = 0;
+
+ /*
+ * Verify if write index @wr_idx and read index @rd_idx are same then
+ * increment @rd_idx to move to next entry in trace buffer
+ */
+ if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) {
+ fnic_trace_entries.rd_idx++;
+ if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries)
+ fnic_trace_entries.rd_idx = 0;
+ }
+ spin_unlock_irqrestore(&fnic_trace_lock, flags);
+ return (fnic_trace_data_t *)fnic_buf_head;
+}
+
+/*
+ * fnic_get_trace_data - Copy trace buffer to a memory file
+ * @fnic_dbgfs_t: pointer to debugfs trace buffer
+ *
+ * Description:
+ * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t
+ * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in
+ * the log and process the log until the end of the buffer. Then it will gather
+ * from the beginning of the log and process until the current entry @wr_idx.
+ *
+ * Return Value:
+ * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t
+ */
+int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
+{
+ int rd_idx;
+ int wr_idx;
+ int len = 0;
+ unsigned long flags;
+ char str[KSYM_SYMBOL_LEN];
+ struct timespec val;
+ fnic_trace_data_t *tbp;
+
+ spin_lock_irqsave(&fnic_trace_lock, flags);
+ rd_idx = fnic_trace_entries.rd_idx;
+ wr_idx = fnic_trace_entries.wr_idx;
+ if (wr_idx < rd_idx) {
+ while (1) {
+ /* Start from read index @rd_idx */
+ tbp = (fnic_trace_data_t *)
+ fnic_trace_entries.page_offset[rd_idx];
+ if (!tbp) {
+ spin_unlock_irqrestore(&fnic_trace_lock, flags);
+ return 0;
+ }
+ /* Convert function pointer to function name */
+ if (sizeof(unsigned long) < 8) {
+ sprint_symbol(str, tbp->fnaddr.low);
+ jiffies_to_timespec(tbp->timestamp.low, &val);
+ } else {
+ sprint_symbol(str, tbp->fnaddr.val);
+ jiffies_to_timespec(tbp->timestamp.val, &val);
+ }
+ /*
+ * Dump trace buffer entry to memory file
+ * and increment read index @rd_idx
+ */
+ len += snprintf(fnic_dbgfs_prt->buffer + len,
+ (trace_max_pages * PAGE_SIZE * 3) - len,
+ "%16lu.%16lu %-50s %8x %8x %16llx %16llx "
+ "%16llx %16llx %16llx\n", val.tv_sec,
+ val.tv_nsec, str, tbp->host_no, tbp->tag,
+ tbp->data[0], tbp->data[1], tbp->data[2],
+ tbp->data[3], tbp->data[4]);
+ rd_idx++;
+ /*
+ * If rd_idx is reached to maximum trace entries
+ * then move rd_idx to zero
+ */
+ if (rd_idx > (fnic_max_trace_entries-1))
+ rd_idx = 0;
+ /*
+ * Continure dumpping trace buffer entries into
+ * memory file till rd_idx reaches write index
+ */
+ if (rd_idx == wr_idx)
+ break;
+ }
+ } else if (wr_idx > rd_idx) {
+ while (1) {
+ /* Start from read index @rd_idx */
+ tbp = (fnic_trace_data_t *)
+ fnic_trace_entries.page_offset[rd_idx];
+ if (!tbp) {
+ spin_unlock_irqrestore(&fnic_trace_lock, flags);
+ return 0;
+ }
+ /* Convert function pointer to function name */
+ if (sizeof(unsigned long) < 8) {
+ sprint_symbol(str, tbp->fnaddr.low);
+ jiffies_to_timespec(tbp->timestamp.low, &val);
+ } else {
+ sprint_symbol(str, tbp->fnaddr.val);
+ jiffies_to_timespec(tbp->timestamp.val, &val);
+ }
+ /*
+ * Dump trace buffer entry to memory file
+ * and increment read index @rd_idx
+ */
+ len += snprintf(fnic_dbgfs_prt->buffer + len,
+ (trace_max_pages * PAGE_SIZE * 3) - len,
+ "%16lu.%16lu %-50s %8x %8x %16llx %16llx "
+ "%16llx %16llx %16llx\n", val.tv_sec,
+ val.tv_nsec, str, tbp->host_no, tbp->tag,
+ tbp->data[0], tbp->data[1], tbp->data[2],
+ tbp->data[3], tbp->data[4]);
+ rd_idx++;
+ /*
+ * Continue dumpping trace buffer entries into
+ * memory file till rd_idx reaches write index
+ */
+ if (rd_idx == wr_idx)
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&fnic_trace_lock, flags);
+ return len;
+}
+
+/*
+ * fnic_trace_buf_init - Initialize fnic trace buffer logging facility
+ *
+ * Description:
+ * Initialize trace buffer data structure by allocating required memory and
+ * setting page_offset information for every trace entry by adding trace entry
+ * length to previous page_offset value.
+ */
+int fnic_trace_buf_init(void)
+{
+ unsigned long fnic_buf_head;
+ int i;
+ int err = 0;
+
+ trace_max_pages = fnic_trace_max_pages;
+ fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
+ FNIC_ENTRY_SIZE_BYTES;
+
+ fnic_trace_buf_p = (unsigned long)vmalloc((trace_max_pages * PAGE_SIZE));
+ if (!fnic_trace_buf_p) {
+ printk(KERN_ERR PFX "Failed to allocate memory "
+ "for fnic_trace_buf_p\n");
+ err = -ENOMEM;
+ goto err_fnic_trace_buf_init;
+ }
+ memset((void *)fnic_trace_buf_p, 0, (trace_max_pages * PAGE_SIZE));
+
+ fnic_trace_entries.page_offset = vmalloc(fnic_max_trace_entries *
+ sizeof(unsigned long));
+ if (!fnic_trace_entries.page_offset) {
+ printk(KERN_ERR PFX "Failed to allocate memory for"
+ " page_offset\n");
+ if (fnic_trace_buf_p) {
+ vfree((void *)fnic_trace_buf_p);
+ fnic_trace_buf_p = 0;
+ }
+ err = -ENOMEM;
+ goto err_fnic_trace_buf_init;
+ }
+ memset((void *)fnic_trace_entries.page_offset, 0,
+ (fnic_max_trace_entries * sizeof(unsigned long)));
+ fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0;
+ fnic_buf_head = fnic_trace_buf_p;
+
+ /*
+ * Set page_offset field of fnic_trace_entries struct by
+ * calculating memory location for every trace entry using
+ * length of each trace entry
+ */
+ for (i = 0; i < fnic_max_trace_entries; i++) {
+ fnic_trace_entries.page_offset[i] = fnic_buf_head;
+ fnic_buf_head += FNIC_ENTRY_SIZE_BYTES;
+ }
+ err = fnic_trace_debugfs_init();
+ if (err < 0) {
+ printk(KERN_ERR PFX "Failed to initialize debugfs for tracing\n");
+ goto err_fnic_trace_debugfs_init;
+ }
+ printk(KERN_INFO PFX "Successfully Initialized Trace Buffer\n");
+ return err;
+err_fnic_trace_debugfs_init:
+ fnic_trace_free();
+err_fnic_trace_buf_init:
+ return err;
+}
+
+/*
+ * fnic_trace_free - Free memory of fnic trace data structures.
+ */
+void fnic_trace_free(void)
+{
+ fnic_tracing_enabled = 0;
+ fnic_trace_debugfs_terminate();
+ if (fnic_trace_entries.page_offset) {
+ vfree((void *)fnic_trace_entries.page_offset);
+ fnic_trace_entries.page_offset = NULL;
+ }
+ if (fnic_trace_buf_p) {
+ vfree((void *)fnic_trace_buf_p);
+ fnic_trace_buf_p = 0;
+ }
+ printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n");
+}
diff --git a/drivers/scsi/fnic/fnic_trace.h b/drivers/scsi/fnic/fnic_trace.h
new file mode 100644
index 0000000..cef42b4
--- /dev/null
+++ b/drivers/scsi/fnic/fnic_trace.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FNIC_TRACE_H__
+#define __FNIC_TRACE_H__
+
+#define FNIC_ENTRY_SIZE_BYTES 64
+
+extern ssize_t simple_read_from_buffer(void __user *to,
+ size_t count,
+ loff_t *ppos,
+ const void *from,
+ size_t available);
+
+extern unsigned int fnic_trace_max_pages;
+extern int fnic_tracing_enabled;
+extern unsigned int trace_max_pages;
+
+typedef struct fnic_trace_dbg {
+ int wr_idx;
+ int rd_idx;
+ unsigned long *page_offset;
+} fnic_trace_dbg_t;
+
+typedef struct fnic_dbgfs {
+ int buffer_len;
+ char *buffer;
+} fnic_dbgfs_t;
+
+struct fnic_trace_data {
+ union {
+ struct {
+ u32 low;
+ u32 high;
+ };
+ u64 val;
+ } timestamp, fnaddr;
+ u32 host_no;
+ u32 tag;
+ u64 data[5];
+} __attribute__((__packed__));
+
+typedef struct fnic_trace_data fnic_trace_data_t;
+
+#define FNIC_TRACE_ENTRY_SIZE \
+ (FNIC_ENTRY_SIZE_BYTES - sizeof(fnic_trace_data_t))
+
+#define FNIC_TRACE(_fn, _hn, _t, _a, _b, _c, _d, _e) \
+ if (unlikely(fnic_tracing_enabled)) { \
+ fnic_trace_data_t *trace_buf = fnic_trace_get_buf(); \
+ if (trace_buf) { \
+ if (sizeof(unsigned long) < 8) { \
+ trace_buf->timestamp.low = jiffies; \
+ trace_buf->fnaddr.low = (u32)(unsigned long)_fn; \
+ } else { \
+ trace_buf->timestamp.val = jiffies; \
+ trace_buf->fnaddr.val = (u64)(unsigned long)_fn; \
+ } \
+ trace_buf->host_no = _hn; \
+ trace_buf->tag = _t; \
+ trace_buf->data[0] = (u64)(unsigned long)_a; \
+ trace_buf->data[1] = (u64)(unsigned long)_b; \
+ trace_buf->data[2] = (u64)(unsigned long)_c; \
+ trace_buf->data[3] = (u64)(unsigned long)_d; \
+ trace_buf->data[4] = (u64)(unsigned long)_e; \
+ } \
+ }
+
+fnic_trace_data_t *fnic_trace_get_buf(void);
+int fnic_get_trace_data(fnic_dbgfs_t *);
+int fnic_trace_buf_init(void);
+void fnic_trace_free(void);
+int fnic_trace_debugfs_init(void);
+void fnic_trace_debugfs_terminate(void);
+
+#endif
diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c
index b576be7..9795d6f 100644
--- a/drivers/scsi/fnic/vnic_dev.c
+++ b/drivers/scsi/fnic/vnic_dev.c
@@ -584,6 +584,16 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
}
+u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev, u16 new_default_vlan)
+{
+ u64 a0 = new_default_vlan, a1 = 0;
+ int wait = 1000;
+ int old_vlan = 0;
+
+ old_vlan = vnic_dev_cmd(vdev, CMD_SET_DEFAULT_VLAN, &a0, &a1, wait);
+ return (u16)old_vlan;
+}
+
int vnic_dev_link_status(struct vnic_dev *vdev)
{
if (vdev->linkstatus)
diff --git a/drivers/scsi/fnic/vnic_dev.h b/drivers/scsi/fnic/vnic_dev.h
index f9935a8..40d4195 100644
--- a/drivers/scsi/fnic/vnic_dev.h
+++ b/drivers/scsi/fnic/vnic_dev.h
@@ -148,6 +148,8 @@ int vnic_dev_disable(struct vnic_dev *vdev);
int vnic_dev_open(struct vnic_dev *vdev, int arg);
int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
int vnic_dev_init(struct vnic_dev *vdev, int arg);
+u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev,
+ u16 new_default_vlan);
int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
diff --git a/drivers/scsi/fnic/vnic_devcmd.h b/drivers/scsi/fnic/vnic_devcmd.h
index 7c9ccbd..3e2fcbd 100644
--- a/drivers/scsi/fnic/vnic_devcmd.h
+++ b/drivers/scsi/fnic/vnic_devcmd.h
@@ -196,6 +196,73 @@ enum vnic_devcmd_cmd {
/* undo initialize of virtual link */
CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
+
+ /* check fw capability of a cmd:
+ * in: (u32)a0=cmd
+ * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
+ CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
+
+ /* persistent binding info
+ * in: (u64)a0=paddr of arg
+ * (u32)a1=CMD_PERBI_XXX */
+ CMD_PERBI = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37),
+
+ /* Interrupt Assert Register functionality
+ * in: (u16)a0=interrupt number to assert
+ */
+ CMD_IAR = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38),
+
+ /* initiate hangreset, like softreset after hang detected */
+ CMD_HANG_RESET = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39),
+
+ /* hangreset status:
+ * out: a0=0 reset complete, a0=1 reset in progress */
+ CMD_HANG_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40),
+
+ /*
+ * Set hw ingress packet vlan rewrite mode:
+ * in: (u32)a0=new vlan rewrite mode
+ * out: (u32)a0=old vlan rewrite mode */
+ CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41),
+
+ /*
+ * in: (u16)a0=bdf of target vnic
+ * (u32)a1=cmd to proxy
+ * a2-a15=args to cmd in a1
+ * out: (u32)a0=status of proxied cmd
+ * a1-a15=out args of proxied cmd */
+ CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42),
+
+ /*
+ * As for BY_BDF except a0 is index of hvnlink subordinate vnic
+ * or SR-IOV virtual vnic
+ */
+ CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43),
+
+ /*
+ * For HPP toggle:
+ * adapter-info-get
+ * in: (u64)a0=phsical address of buffer passed in from caller.
+ * (u16)a1=size of buffer specified in a0.
+ * out: (u64)a0=phsical address of buffer passed in from caller.
+ * (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or
+ * 0 if no VIF-CONFIG-INFO TLV was ever received. */
+ CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
+
+ /*
+ * INT13 API: (u64)a0=paddr to vnic_int13_params struct
+ * (u32)a1=INT13_CMD_xxx
+ */
+ CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45),
+
+ /*
+ * Set default vlan:
+ * in: (u16)a0=new default vlan
+ * (u16)a1=zero for overriding vlan with param a0,
+ * non-zero for resetting vlan to the default
+ * out: (u16)a0=old default vlan
+ */
+ CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46)
};
/* flags for CMD_OPEN */
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 1a5954f..5cec6c6 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -745,42 +745,36 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
#include "NCR5380.c"
-#define PRINTP(x) len += sprintf(buffer+len, x)
+#define PRINTP(x) seq_printf(m, x)
#define ANDP ,
-static int sprint_opcode(char *buffer, int len, int opcode)
+static void sprint_opcode(struct seq_file *m, int opcode)
{
- int start = len;
PRINTP("0x%02x " ANDP opcode);
- return len - start;
}
-static int sprint_command(char *buffer, int len, unsigned char *command)
+static void sprint_command(struct seq_file *m, unsigned char *command)
{
- int i, s, start = len;
- len += sprint_opcode(buffer, len, command[0]);
+ int i, s;
+ sprint_opcode(m, command[0]);
for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
PRINTP("%02x " ANDP command[i]);
PRINTP("\n");
- return len - start;
}
/**
* sprintf_Scsi_Cmnd - print a scsi command
- * @buffer: buffr to print into
- * @len: buffer length
+ * @m: seq_fil to print into
* @cmd: SCSI command block
*
* Print out the target and command data in hex
*/
-static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
+static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
{
- int start = len;
PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
PRINTP(" command = ");
- len += sprint_command(buffer, len, cmd->cmnd);
- return len - start;
+ sprint_command(m, cmd->cmnd);
}
/**
@@ -800,9 +794,8 @@ static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
* Locks: global cli/lock for queue walk
*/
-static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, char **start, off_t offset, int length, int inout)
+static int generic_NCR5380_show_info(struct seq_file *m, struct Scsi_Host *scsi_ptr)
{
- int len = 0;
NCR5380_local_declare();
unsigned long flags;
unsigned char status;
@@ -853,16 +846,16 @@ static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, c
PRINTP(" T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
for (i = 0; i < 8; i++)
if (dev->vendor[i] >= 0x20)
- *(buffer + (len++)) = dev->vendor[i];
- *(buffer + (len++)) = ' ';
+ seq_putc(m, dev->vendor[i]);
+ seq_putc(m, ' ');
for (i = 0; i < 16; i++)
if (dev->model[i] >= 0x20)
- *(buffer + (len++)) = dev->model[i];
- *(buffer + (len++)) = ' ';
+ seq_putc(m, dev->model[i]);
+ seq_putc(m, ' ');
for (i = 0; i < 4; i++)
if (dev->rev[i] >= 0x20)
- *(buffer + (len++)) = dev->rev[i];
- *(buffer + (len++)) = ' ';
+ seq_putc(m, dev->rev[i]);
+ seq_putc(m, ' ');
PRINTP("\n%10ld kb read in %5ld secs" ANDP br / 1024 ANDP tr);
if (tr)
@@ -886,32 +879,28 @@ static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, c
if (!hostdata->connected) {
PRINTP("No currently connected command\n");
} else {
- len += sprint_Scsi_Cmnd(buffer, len, (Scsi_Cmnd *) hostdata->connected);
+ sprint_Scsi_Cmnd(m, (Scsi_Cmnd *) hostdata->connected);
}
PRINTP("issue_queue\n");
for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
- len += sprint_Scsi_Cmnd(buffer, len, ptr);
+ sprint_Scsi_Cmnd(m, ptr);
PRINTP("disconnected_queue\n");
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
- len += sprint_Scsi_Cmnd(buffer, len, ptr);
+ sprint_Scsi_Cmnd(m, ptr);
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
- return len;
+ return 0;
}
#undef PRINTP
#undef ANDP
static struct scsi_host_template driver_template = {
- .proc_info = generic_NCR5380_proc_info,
+ .show_info = generic_NCR5380_show_info,
.name = "Generic NCR5380/NCR53C400 Scsi Driver",
.detect = generic_NCR5380_detect,
.release = generic_NCR5380_release_resources,
@@ -939,7 +928,7 @@ module_param(dtc_3181e, int, 0);
MODULE_LICENSE("GPL");
#ifndef SCSI_G_NCR5380_MEM
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
{
ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e),
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 5d72274..6d55b4e 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -590,7 +590,7 @@ static struct pci_driver gdth_pci_driver = {
.remove = gdth_pci_remove_one,
};
-static void __devexit gdth_pci_remove_one(struct pci_dev *pdev)
+static void gdth_pci_remove_one(struct pci_dev *pdev)
{
gdth_ha_str *ha = pci_get_drvdata(pdev);
@@ -602,8 +602,8 @@ static void __devexit gdth_pci_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static int __devinit gdth_pci_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int gdth_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
u16 vendor = pdev->vendor;
u16 device = pdev->device;
@@ -855,8 +855,8 @@ static int __init gdth_init_isa(u32 bios_adr,gdth_ha_str *ha)
#endif /* CONFIG_ISA */
#ifdef CONFIG_PCI
-static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
- gdth_ha_str *ha)
+static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+ gdth_ha_str *ha)
{
register gdt6_dpram_str __iomem *dp6_ptr;
register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -1107,14 +1107,8 @@ static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
pci_read_config_word(pdev, PCI_COMMAND, &command);
command |= 6;
pci_write_config_word(pdev, PCI_COMMAND, command);
- if (pci_resource_start(pdev, 8) == 1UL)
- pci_resource_start(pdev, 8) = 0UL;
- i = 0xFEFF0001UL;
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i);
- gdth_delay(1);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
- pci_resource_start(pdev, 8));
-
+ gdth_delay(1);
+
dp6m_ptr = ha->brd;
/* Ensure that it is safe to access the non HW portions of DPMEM.
@@ -1239,7 +1233,7 @@ static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
/* controller protocol functions */
-static void __devinit gdth_enable_int(gdth_ha_str *ha)
+static void gdth_enable_int(gdth_ha_str *ha)
{
unsigned long flags;
gdt2_dpram_str __iomem *dp2_ptr;
@@ -1555,7 +1549,7 @@ static int gdth_internal_cmd(gdth_ha_str *ha, u8 service, u16 opcode,
/* search for devices */
-static int __devinit gdth_search_drives(gdth_ha_str *ha)
+static int gdth_search_drives(gdth_ha_str *ha)
{
u16 cdev_cnt, i;
int ok;
@@ -4682,7 +4676,8 @@ static struct scsi_host_template gdth_template = {
.eh_bus_reset_handler = gdth_eh_bus_reset,
.slave_configure = gdth_slave_configure,
.bios_param = gdth_bios_param,
- .proc_info = gdth_proc_info,
+ .show_info = gdth_show_info,
+ .write_info = gdth_set_info,
.eh_timed_out = gdth_timed_out,
.proc_name = "gdth",
.can_queue = GDTH_MAXCMDS,
@@ -4959,8 +4954,7 @@ static int __init gdth_eisa_probe_one(u16 eisa_slot)
#endif /* CONFIG_EISA */
#ifdef CONFIG_PCI
-static int __devinit gdth_pci_probe_one(gdth_pci_str *pcistr,
- gdth_ha_str **ha_out)
+static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index fbf6f0f4..3fd8b83 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -1007,6 +1007,7 @@ typedef struct {
/* function prototyping */
-int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,int,int);
+int gdth_show_info(struct seq_file *, struct Scsi_Host *);
+int gdth_set_info(struct Scsi_Host *, char *, int);
#endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 6527543..9fb6326 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -5,23 +5,9 @@
#include <linux/completion.h>
#include <linux/slab.h>
-int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,
- int inout)
+int gdth_set_info(struct Scsi_Host *host, char *buffer, int length)
{
gdth_ha_str *ha = shost_priv(host);
-
- TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
- length,(int)offset,inout));
-
- if (inout)
- return(gdth_set_info(buffer,length,host,ha));
- else
- return(gdth_get_info(buffer,start,offset,length,host,ha));
-}
-
-static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
- gdth_ha_str *ha)
-{
int ret_val = -EINVAL;
TRACE2(("gdth_set_info() ha %d\n",ha->hanum,));
@@ -149,12 +135,10 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
return(-EINVAL);
}
-static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
- struct Scsi_Host *host, gdth_ha_str *ha)
+int gdth_show_info(struct seq_file *m, struct Scsi_Host *host)
{
- int size = 0,len = 0;
+ gdth_ha_str *ha = shost_priv(host);
int hlen;
- off_t begin = 0,pos = 0;
int id, i, j, k, sec, flag;
int no_mdrv = 0, drv_no, is_mirr;
u32 cnt;
@@ -189,8 +173,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* request is i.e. "cat /proc/scsi/gdth/0" */
/* format: %-15s\t%-10s\t%-15s\t%s */
/* driver parameters */
- size = sprintf(buffer+len,"Driver Parameters:\n");
- len += size; pos = begin + len;
+ seq_printf(m, "Driver Parameters:\n");
if (reserve_list[0] == 0xff)
strcpy(hrec, "--");
else {
@@ -201,69 +184,50 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]);
}
}
- size = sprintf(buffer+len,
+ seq_printf(m,
" reserve_mode: \t%d \treserve_list: \t%s\n",
reserve_mode, hrec);
- len += size; pos = begin + len;
- size = sprintf(buffer+len,
+ seq_printf(m,
" max_ids: \t%-3d \thdr_channel: \t%d\n",
max_ids, hdr_channel);
- len += size; pos = begin + len;
/* controller information */
- size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
- len += size; pos = begin + len;
- strcpy(hrec, ha->binfo.type_string);
- size = sprintf(buffer+len,
+ seq_printf(m,"\nDisk Array Controller Information:\n");
+ seq_printf(m,
" Number: \t%d \tName: \t%s\n",
- ha->hanum, hrec);
- len += size; pos = begin + len;
+ ha->hanum, ha->binfo.type_string);
+ seq_printf(m,
+ " Driver Ver.: \t%-10s\tFirmware Ver.: \t",
+ GDTH_VERSION_STR);
if (ha->more_proc)
- sprintf(hrec, "%d.%02d.%02d-%c%03X",
+ seq_printf(m, "%d.%02d.%02d-%c%03X\n",
(u8)(ha->binfo.upd_fw_ver>>24),
(u8)(ha->binfo.upd_fw_ver>>16),
(u8)(ha->binfo.upd_fw_ver),
ha->bfeat.raid ? 'R':'N',
ha->binfo.upd_revision);
else
- sprintf(hrec, "%d.%02d", (u8)(ha->cpar.version>>8),
+ seq_printf(m, "%d.%02d\n", (u8)(ha->cpar.version>>8),
(u8)(ha->cpar.version));
-
- size = sprintf(buffer+len,
- " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n",
- GDTH_VERSION_STR, hrec);
- len += size; pos = begin + len;
- if (ha->more_proc) {
+ if (ha->more_proc)
/* more information: 1. about controller */
- size = sprintf(buffer+len,
+ seq_printf(m,
" Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n",
ha->binfo.ser_no, ha->binfo.memsize / 1024);
- len += size; pos = begin + len;
- }
#ifdef GDTH_DMA_STATISTICS
/* controller statistics */
- size = sprintf(buffer+len,"\nController Statistics:\n");
- len += size; pos = begin + len;
- size = sprintf(buffer+len,
+ seq_printf(m,"\nController Statistics:\n");
+ seq_printf(m,
" 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
ha->dma32_cnt, ha->dma64_cnt);
- len += size; pos = begin + len;
#endif
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length)
- goto stop_output;
-
if (ha->more_proc) {
/* more information: 2. about physical devices */
- size = sprintf(buffer+len,"\nPhysical Devices:");
- len += size; pos = begin + len;
+ seq_printf(m, "\nPhysical Devices:");
flag = FALSE;
buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -309,21 +273,19 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
strncpy(hrec+8,pdi->product,16);
strncpy(hrec+24,pdi->revision,4);
hrec[28] = 0;
- size = sprintf(buffer+len,
+ seq_printf(m,
"\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n",
'A'+i,pdi->target_id,pdi->lun,hrec);
- len += size; pos = begin + len;
flag = TRUE;
pdi->no_ldrive &= 0xffff;
if (pdi->no_ldrive == 0xffff)
strcpy(hrec,"--");
else
sprintf(hrec,"%d",pdi->no_ldrive);
- size = sprintf(buffer+len,
+ seq_printf(m,
" Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n",
pdi->blkcnt/(1024*1024/pdi->blksize),
hrec);
- len += size; pos = begin + len;
} else {
pdi->devtype = 0xff;
}
@@ -333,11 +295,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
for (k = 0; k < pds->count; ++k) {
if (pds->list[k].tid == pdi->target_id &&
pds->list[k].lun == pdi->lun) {
- size = sprintf(buffer+len,
+ seq_printf(m,
" Retries: \t%-6d \tReassigns: \t%d\n",
pds->list[k].retries,
pds->list[k].reassigns);
- len += size; pos = begin + len;
break;
}
}
@@ -355,32 +316,20 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
pdef->sddc_type = 0x08;
if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
- size = sprintf(buffer+len,
+ seq_printf(m,
" Grown Defects:\t%d\n",
pdef->sddc_cnt);
- len += size; pos = begin + len;
}
}
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length) {
- gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- goto stop_output;
- }
}
}
gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- if (!flag) {
- size = sprintf(buffer+len, "\n --\n");
- len += size; pos = begin + len;
- }
+ if (!flag)
+ seq_printf(m, "\n --\n");
/* 3. about logical drives */
- size = sprintf(buffer+len,"\nLogical Drives:");
- len += size; pos = begin + len;
+ seq_printf(m,"\nLogical Drives:");
flag = FALSE;
buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -418,10 +367,9 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
}
if (drv_no == i) {
- size = sprintf(buffer+len,
+ seq_printf(m,
"\n Number: \t%-2d \tStatus: \t%s\n",
drv_no, hrec);
- len += size; pos = begin + len;
flag = TRUE;
no_mdrv = pcdi->cd_ldcnt;
if (no_mdrv > 1 || pcdi->ld_slave != -1) {
@@ -436,61 +384,37 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
} else {
strcpy(hrec, "???");
}
- size = sprintf(buffer+len,
+ seq_printf(m,
" Capacity [MB]:\t%-6d \tType: \t%s\n",
pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
hrec);
- len += size; pos = begin + len;
} else {
- size = sprintf(buffer+len,
+ seq_printf(m,
" Slave Number: \t%-2d \tStatus: \t%s\n",
drv_no & 0x7fff, hrec);
- len += size; pos = begin + len;
}
drv_no = pcdi->ld_slave;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length) {
- gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- goto stop_output;
- }
} while (drv_no != -1);
- if (is_mirr) {
- size = sprintf(buffer+len,
+ if (is_mirr)
+ seq_printf(m,
" Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n",
no_mdrv - j - k, k);
- len += size; pos = begin + len;
- }
-
+
if (!ha->hdr[i].is_arraydrv)
strcpy(hrec, "--");
else
sprintf(hrec, "%d", ha->hdr[i].master_no);
- size = sprintf(buffer+len,
+ seq_printf(m,
" To Array Drv.:\t%s\n", hrec);
- len += size; pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length) {
- gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- goto stop_output;
- }
}
gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- if (!flag) {
- size = sprintf(buffer+len, "\n --\n");
- len += size; pos = begin + len;
- }
+ if (!flag)
+ seq_printf(m, "\n --\n");
/* 4. about array drives */
- size = sprintf(buffer+len,"\nArray Drives:");
- len += size; pos = begin + len;
+ seq_printf(m,"\nArray Drives:");
flag = FALSE;
buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr);
@@ -525,10 +449,9 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
strcat(hrec, "/expand");
else if (pai->ai_ext_state & 0x1)
strcat(hrec, "/patch");
- size = sprintf(buffer+len,
+ seq_printf(m,
"\n Number: \t%-2d \tStatus: \t%s\n",
i,hrec);
- len += size; pos = begin + len;
flag = TRUE;
if (pai->ai_type == 0)
@@ -539,31 +462,19 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
strcpy(hrec, "RAID-5");
else
strcpy(hrec, "RAID-10");
- size = sprintf(buffer+len,
+ seq_printf(m,
" Capacity [MB]:\t%-6d \tType: \t%s\n",
pai->ai_size/(1024*1024/pai->ai_secsize),
hrec);
- len += size; pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length) {
- gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- goto stop_output;
- }
}
}
gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
- if (!flag) {
- size = sprintf(buffer+len, "\n --\n");
- len += size; pos = begin + len;
- }
+ if (!flag)
+ seq_printf(m, "\n --\n");
/* 5. about host drives */
- size = sprintf(buffer+len,"\nHost Drives:");
- len += size; pos = begin + len;
+ seq_printf(m,"\nHost Drives:");
flag = FALSE;
buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr);
@@ -605,33 +516,22 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
if (!(ha->hdr[i].present))
continue;
- size = sprintf(buffer+len,
+ seq_printf(m,
"\n Number: \t%-2d \tArr/Log. Drive:\t%d\n",
i, ha->hdr[i].ldr_no);
- len += size; pos = begin + len;
flag = TRUE;
- size = sprintf(buffer+len,
+ seq_printf(m,
" Capacity [MB]:\t%-6d \tStart Sector: \t%d\n",
(u32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec);
- len += size; pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length)
- goto stop_output;
}
- if (!flag) {
- size = sprintf(buffer+len, "\n --\n");
- len += size; pos = begin + len;
- }
+ if (!flag)
+ seq_printf(m, "\n --\n");
}
/* controller events */
- size = sprintf(buffer+len,"\nController Events:\n");
- len += size; pos = begin + len;
+ seq_printf(m,"\nController Events:\n");
for (id = -1;;) {
id = gdth_read_event(ha, id, estr);
@@ -643,29 +543,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
do_gettimeofday(&tv);
sec = (int)(tv.tv_sec - estr->first_stamp);
if (sec < 0) sec = 0;
- size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
+ seq_printf(m," date- %02d:%02d:%02d\t%s\n",
sec/3600, sec%3600/60, sec%60, hrec);
- len += size; pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length)
- goto stop_output;
}
if (id == -1)
break;
}
-
stop_output:
- *start = buffer +(offset-begin);
- len -= (offset-begin);
- if (len > length)
- len = length;
- TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
- len,(int)pos,(int)begin,(int)offset,length,size));
- rc = len;
-
+ rc = 0;
free_fail:
kfree(gdtcmd);
kfree(estr);
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index dab15f5..aaa6181 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -8,11 +8,6 @@
int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
int timeout, u32 *info);
-static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
- gdth_ha_str *ha);
-static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
- struct Scsi_Host *host, gdth_ha_str *ha);
-
static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
int length, gdth_ha_str *ha);
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 488fbc6..2203ac2 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -191,7 +191,8 @@ static int gvp11_bus_reset(struct scsi_cmnd *cmd)
static struct scsi_host_template gvp11_scsi_template = {
.module = THIS_MODULE,
.name = "GVP Series II SCSI",
- .proc_info = wd33c93_proc_info,
+ .show_info = wd33c93_show_info,
+ .write_info = wd33c93_write_info,
.proc_name = "GVP11",
.queuecommand = wd33c93_queuecommand,
.eh_abort_handler = wd33c93_abort,
@@ -204,7 +205,7 @@ static struct scsi_host_template gvp11_scsi_template = {
.use_clustering = DISABLE_CLUSTERING
};
-static int __devinit check_wd33c93(struct gvp11_scsiregs *regs)
+static int check_wd33c93(struct gvp11_scsiregs *regs)
{
#ifdef CHECK_WD33C93
volatile unsigned char *sasr_3393, *scmd_3393;
@@ -284,8 +285,7 @@ static int __devinit check_wd33c93(struct gvp11_scsiregs *regs)
return 0;
}
-static int __devinit gvp11_probe(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
{
struct Scsi_Host *instance;
unsigned long address;
@@ -380,7 +380,7 @@ fail_check_or_alloc:
return error;
}
-static void __devexit gvp11_remove(struct zorro_dev *z)
+static void gvp11_remove(struct zorro_dev *z)
{
struct Scsi_Host *instance = zorro_get_drvdata(z);
struct gvp11_hostdata *hdata = shost_priv(instance);
@@ -398,7 +398,7 @@ static void __devexit gvp11_remove(struct zorro_dev *z)
* SERIES I though).
*/
-static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id gvp11_zorro_tbl[] = {
{ ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff },
{ ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff },
{ ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff },
@@ -414,7 +414,7 @@ static struct zorro_driver gvp11_driver = {
.name = "gvp11",
.id_table = gvp11_zorro_tbl,
.probe = gvp11_probe,
- .remove = __devexit_p(gvp11_remove),
+ .remove = gvp11_remove,
};
static int __init gvp11_init(void)
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 593085a..df0c3c7 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -468,10 +468,10 @@ void scsi_unregister(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(scsi_unregister);
-static int __scsi_host_match(struct device *dev, void *data)
+static int __scsi_host_match(struct device *dev, const void *data)
{
struct Scsi_Host *p;
- unsigned short *hostnum = (unsigned short *)data;
+ const unsigned short *hostnum = data;
p = class_to_shost(dev);
return p->host_no == *hostnum;
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 4217e49..7f4f790 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -165,7 +165,7 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c);
static void cmd_special_free(struct ctlr_info *h, struct CommandList *c);
static struct CommandList *cmd_alloc(struct ctlr_info *h);
static struct CommandList *cmd_special_alloc(struct ctlr_info *h);
-static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
+static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
void *buff, size_t size, u8 page_code, unsigned char *scsi3addr,
int cmd_type);
@@ -189,16 +189,16 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
/* performant mode helper functions */
static void calc_bucket_map(int *bucket, int num_buckets,
int nsgs, int *bucket_map);
-static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
+static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
static inline u32 next_command(struct ctlr_info *h, u8 q);
-static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
- void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
- u64 *cfg_offset);
-static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
- unsigned long *memory_bar);
-static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
-static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
- void __iomem *vaddr, int wait_for_ready);
+static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
+ u32 *cfg_base_addr, u64 *cfg_base_addr_index,
+ u64 *cfg_offset);
+static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
+ unsigned long *memory_bar);
+static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
+static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr,
+ int wait_for_ready);
static inline void finish_cmd(struct CommandList *c);
#define BOARD_NOT_READY 0
#define BOARD_READY 1
@@ -1131,7 +1131,7 @@ clean:
return -ENOMEM;
}
-static void hpsa_map_sg_chain_block(struct ctlr_info *h,
+static int hpsa_map_sg_chain_block(struct ctlr_info *h,
struct CommandList *c)
{
struct SGDescriptor *chain_sg, *chain_block;
@@ -1144,8 +1144,15 @@ static void hpsa_map_sg_chain_block(struct ctlr_info *h,
(c->Header.SGTotal - h->max_cmd_sg_entries);
temp64 = pci_map_single(h->pdev, chain_block, chain_sg->Len,
PCI_DMA_TODEVICE);
+ if (dma_mapping_error(&h->pdev->dev, temp64)) {
+ /* prevent subsequent unmapping */
+ chain_sg->Addr.lower = 0;
+ chain_sg->Addr.upper = 0;
+ return -1;
+ }
chain_sg->Addr.lower = (u32) (temp64 & 0x0FFFFFFFFULL);
chain_sg->Addr.upper = (u32) ((temp64 >> 32) & 0x0FFFFFFFFULL);
+ return 0;
}
static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
@@ -1390,7 +1397,7 @@ static void hpsa_pci_unmap(struct pci_dev *pdev,
}
}
-static void hpsa_map_one(struct pci_dev *pdev,
+static int hpsa_map_one(struct pci_dev *pdev,
struct CommandList *cp,
unsigned char *buf,
size_t buflen,
@@ -1401,10 +1408,16 @@ static void hpsa_map_one(struct pci_dev *pdev,
if (buflen == 0 || data_direction == PCI_DMA_NONE) {
cp->Header.SGList = 0;
cp->Header.SGTotal = 0;
- return;
+ return 0;
}
addr64 = (u64) pci_map_single(pdev, buf, buflen, data_direction);
+ if (dma_mapping_error(&pdev->dev, addr64)) {
+ /* Prevent subsequent unmap of something never mapped */
+ cp->Header.SGList = 0;
+ cp->Header.SGTotal = 0;
+ return -1;
+ }
cp->SG[0].Addr.lower =
(u32) (addr64 & (u64) 0x00000000FFFFFFFF);
cp->SG[0].Addr.upper =
@@ -1412,6 +1425,7 @@ static void hpsa_map_one(struct pci_dev *pdev,
cp->SG[0].Len = buflen;
cp->Header.SGList = (u8) 1; /* no. SGs contig in this cmd */
cp->Header.SGTotal = (u16) 1; /* total sgs in this cmd list */
+ return 0;
}
static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h,
@@ -1540,13 +1554,18 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
return -ENOMEM;
}
- fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD);
+ if (fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize,
+ page, scsi3addr, TYPE_CMD)) {
+ rc = -1;
+ goto out;
+ }
hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
ei = c->err_info;
if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
hpsa_scsi_interpret_error(c);
rc = -1;
}
+out:
cmd_special_free(h, c);
return rc;
}
@@ -1564,7 +1583,9 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr)
return -ENOMEM;
}
- fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, scsi3addr, TYPE_MSG);
+ /* fill_cmd can't fail here, no data buffer to map. */
+ (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h,
+ NULL, 0, 0, scsi3addr, TYPE_MSG);
hpsa_scsi_do_simple_cmd_core(h, c);
/* no unmap needed here because no data xfer. */
@@ -1631,8 +1652,11 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
}
/* address the controller */
memset(scsi3addr, 0, sizeof(scsi3addr));
- fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h,
- buf, bufsize, 0, scsi3addr, TYPE_CMD);
+ if (fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h,
+ buf, bufsize, 0, scsi3addr, TYPE_CMD)) {
+ rc = -1;
+ goto out;
+ }
if (extended_response)
c->Request.CDB[1] = extended_response;
hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
@@ -1642,6 +1666,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
hpsa_scsi_interpret_error(c);
rc = -1;
}
+out:
cmd_special_free(h, c);
return rc;
}
@@ -2105,7 +2130,10 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
if (chained) {
cp->Header.SGList = h->max_cmd_sg_entries;
cp->Header.SGTotal = (u16) (use_sg + 1);
- hpsa_map_sg_chain_block(h, cp);
+ if (hpsa_map_sg_chain_block(h, cp)) {
+ scsi_dma_unmap(cmd);
+ return -1;
+ }
return 0;
}
@@ -2353,8 +2381,9 @@ static int wait_for_device_to_become_ready(struct ctlr_info *h,
if (waittime < HPSA_MAX_WAIT_INTERVAL_SECS)
waittime = waittime * 2;
- /* Send the Test Unit Ready */
- fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, lunaddr, TYPE_CMD);
+ /* Send the Test Unit Ready, fill_cmd can't fail, no mapping */
+ (void) fill_cmd(c, TEST_UNIT_READY, h,
+ NULL, 0, 0, lunaddr, TYPE_CMD);
hpsa_scsi_do_simple_cmd_core(h, c);
/* no unmap needed here because no data xfer. */
@@ -2439,7 +2468,9 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
return -ENOMEM;
}
- fill_cmd(c, HPSA_ABORT_MSG, h, abort, 0, 0, scsi3addr, TYPE_MSG);
+ /* fill_cmd can't fail here, no buffer to map */
+ (void) fill_cmd(c, HPSA_ABORT_MSG, h, abort,
+ 0, 0, scsi3addr, TYPE_MSG);
if (swizzle)
swizzle_abort_tag(&c->Request.CDB[4]);
hpsa_scsi_do_simple_cmd_core(h, c);
@@ -2928,6 +2959,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
struct CommandList *c;
char *buff = NULL;
union u64bit temp64;
+ int rc = 0;
if (!argp)
return -EINVAL;
@@ -2947,8 +2979,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
/* Copy the data into the buffer we created */
if (copy_from_user(buff, iocommand.buf,
iocommand.buf_size)) {
- kfree(buff);
- return -EFAULT;
+ rc = -EFAULT;
+ goto out_kfree;
}
} else {
memset(buff, 0, iocommand.buf_size);
@@ -2956,8 +2988,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
}
c = cmd_special_alloc(h);
if (c == NULL) {
- kfree(buff);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_kfree;
}
/* Fill in the command type */
c->cmd_type = CMD_IOCTL_PEND;
@@ -2982,6 +3014,13 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
if (iocommand.buf_size > 0) {
temp64.val = pci_map_single(h->pdev, buff,
iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
+ c->SG[0].Addr.lower = 0;
+ c->SG[0].Addr.upper = 0;
+ c->SG[0].Len = 0;
+ rc = -ENOMEM;
+ goto out;
+ }
c->SG[0].Addr.lower = temp64.val32.lower;
c->SG[0].Addr.upper = temp64.val32.upper;
c->SG[0].Len = iocommand.buf_size;
@@ -2996,22 +3035,22 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
memcpy(&iocommand.error_info, c->err_info,
sizeof(iocommand.error_info));
if (copy_to_user(argp, &iocommand, sizeof(iocommand))) {
- kfree(buff);
- cmd_special_free(h, c);
- return -EFAULT;
+ rc = -EFAULT;
+ goto out;
}
if (iocommand.Request.Type.Direction == XFER_READ &&
iocommand.buf_size > 0) {
/* Copy the data out of the buffer we created */
if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
- kfree(buff);
- cmd_special_free(h, c);
- return -EFAULT;
+ rc = -EFAULT;
+ goto out;
}
}
- kfree(buff);
+out:
cmd_special_free(h, c);
- return 0;
+out_kfree:
+ kfree(buff);
+ return rc;
}
static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
@@ -3103,6 +3142,15 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
for (i = 0; i < sg_used; i++) {
temp64.val = pci_map_single(h->pdev, buff[i],
buff_size[i], PCI_DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
+ c->SG[i].Addr.lower = 0;
+ c->SG[i].Addr.upper = 0;
+ c->SG[i].Len = 0;
+ hpsa_pci_unmap(h->pdev, c, i,
+ PCI_DMA_BIDIRECTIONAL);
+ status = -ENOMEM;
+ goto cleanup1;
+ }
c->SG[i].Addr.lower = temp64.val32.lower;
c->SG[i].Addr.upper = temp64.val32.upper;
c->SG[i].Len = buff_size[i];
@@ -3182,15 +3230,16 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
}
}
-static int __devinit hpsa_send_host_reset(struct ctlr_info *h,
- unsigned char *scsi3addr, u8 reset_type)
+static int hpsa_send_host_reset(struct ctlr_info *h, unsigned char *scsi3addr,
+ u8 reset_type)
{
struct CommandList *c;
c = cmd_alloc(h);
if (!c)
return -ENOMEM;
- fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
+ /* fill_cmd can't fail here, no data buffer to map */
+ (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
RAID_CTLR_LUNID, TYPE_MSG);
c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */
c->waiting = NULL;
@@ -3202,7 +3251,7 @@ static int __devinit hpsa_send_host_reset(struct ctlr_info *h,
return 0;
}
-static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
+static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
void *buff, size_t size, u8 page_code, unsigned char *scsi3addr,
int cmd_type)
{
@@ -3271,7 +3320,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
default:
dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
BUG();
- return;
+ return -1;
}
} else if (cmd_type == TYPE_MSG) {
switch (cmd) {
@@ -3343,10 +3392,9 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
default:
pci_dir = PCI_DMA_BIDIRECTIONAL;
}
-
- hpsa_map_one(h->pdev, c, buff, size, pci_dir);
-
- return;
+ if (hpsa_map_one(h->pdev, c, buff, size, pci_dir))
+ return -1;
+ return 0;
}
/*
@@ -3606,8 +3654,8 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *queue)
* in simple mode, not performant mode due to the tag lookup.
* We only ever use this immediately after a controller reset.
*/
-static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
- unsigned char type)
+static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
+ unsigned char type)
{
struct Command {
struct CommandListHeader CommandHeader;
@@ -3756,14 +3804,13 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
return 0;
}
-static __devinit void init_driver_version(char *driver_version, int len)
+static void init_driver_version(char *driver_version, int len)
{
memset(driver_version, 0, len);
strncpy(driver_version, HPSA " " HPSA_DRIVER_VERSION, len - 1);
}
-static __devinit int write_driver_ver_to_cfgtable(
- struct CfgTable __iomem *cfgtable)
+static int write_driver_ver_to_cfgtable(struct CfgTable __iomem *cfgtable)
{
char *driver_version;
int i, size = sizeof(cfgtable->driver_version);
@@ -3779,8 +3826,8 @@ static __devinit int write_driver_ver_to_cfgtable(
return 0;
}
-static __devinit void read_driver_ver_from_cfgtable(
- struct CfgTable __iomem *cfgtable, unsigned char *driver_ver)
+static void read_driver_ver_from_cfgtable(struct CfgTable __iomem *cfgtable,
+ unsigned char *driver_ver)
{
int i;
@@ -3788,8 +3835,7 @@ static __devinit void read_driver_ver_from_cfgtable(
driver_ver[i] = readb(&cfgtable->driver_version[i]);
}
-static __devinit int controller_reset_failed(
- struct CfgTable __iomem *cfgtable)
+static int controller_reset_failed(struct CfgTable __iomem *cfgtable)
{
char *driver_ver, *old_driver_ver;
@@ -3812,7 +3858,7 @@ static __devinit int controller_reset_failed(
/* This does a hard reset of the controller using PCI power management
* states or the using the doorbell register.
*/
-static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
+static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
{
u64 cfg_offset;
u32 cfg_base_addr;
@@ -4029,7 +4075,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
* controllers that are capable. If not, we use IO-APIC mode.
*/
-static void __devinit hpsa_interrupt_mode(struct ctlr_info *h)
+static void hpsa_interrupt_mode(struct ctlr_info *h)
{
#ifdef CONFIG_PCI_MSI
int err, i;
@@ -4077,7 +4123,7 @@ default_int_mode:
h->intr[h->intr_mode] = h->pdev->irq;
}
-static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
+static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
{
int i;
u32 subsystem_vendor_id, subsystem_device_id;
@@ -4101,8 +4147,8 @@ static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
return ARRAY_SIZE(products) - 1; /* generic unknown smart array */
}
-static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
- unsigned long *memory_bar)
+static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
+ unsigned long *memory_bar)
{
int i;
@@ -4118,8 +4164,8 @@ static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
return -ENODEV;
}
-static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
- void __iomem *vaddr, int wait_for_ready)
+static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr,
+ int wait_for_ready)
{
int i, iterations;
u32 scratchpad;
@@ -4143,9 +4189,9 @@ static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
return -ENODEV;
}
-static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
- void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
- u64 *cfg_offset)
+static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
+ u32 *cfg_base_addr, u64 *cfg_base_addr_index,
+ u64 *cfg_offset)
{
*cfg_base_addr = readl(vaddr + SA5_CTCFG_OFFSET);
*cfg_offset = readl(vaddr + SA5_CTMEM_OFFSET);
@@ -4158,7 +4204,7 @@ static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
return 0;
}
-static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
+static int hpsa_find_cfgtables(struct ctlr_info *h)
{
u64 cfg_offset;
u32 cfg_base_addr;
@@ -4187,7 +4233,7 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
return 0;
}
-static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
+static void hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
{
h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
@@ -4208,7 +4254,7 @@ static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
* max commands, max SG elements without chaining, and with chaining,
* SG chain block size, etc.
*/
-static void __devinit hpsa_find_board_params(struct ctlr_info *h)
+static void hpsa_find_board_params(struct ctlr_info *h)
{
hpsa_get_max_perf_mode_cmds(h);
h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */
@@ -4266,7 +4312,7 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)
writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG);
}
-static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
+static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
{
int i;
u32 doorbell_value;
@@ -4287,7 +4333,7 @@ static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
}
}
-static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)
+static int hpsa_enter_simple_mode(struct ctlr_info *h)
{
u32 trans_support;
@@ -4310,7 +4356,7 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)
return 0;
}
-static int __devinit hpsa_pci_init(struct ctlr_info *h)
+static int hpsa_pci_init(struct ctlr_info *h)
{
int prod_index, err;
@@ -4378,7 +4424,7 @@ err_out_free_res:
return err;
}
-static void __devinit hpsa_hba_inquiry(struct ctlr_info *h)
+static void hpsa_hba_inquiry(struct ctlr_info *h)
{
int rc;
@@ -4394,7 +4440,7 @@ static void __devinit hpsa_hba_inquiry(struct ctlr_info *h)
}
}
-static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
+static int hpsa_init_reset_devices(struct pci_dev *pdev)
{
int rc, i;
@@ -4426,7 +4472,7 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
return 0;
}
-static __devinit int hpsa_allocate_cmd_pool(struct ctlr_info *h)
+static int hpsa_allocate_cmd_pool(struct ctlr_info *h)
{
h->cmd_pool_bits = kzalloc(
DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
@@ -4499,7 +4545,7 @@ static int hpsa_request_irq(struct ctlr_info *h,
return 0;
}
-static int __devinit hpsa_kdump_soft_reset(struct ctlr_info *h)
+static int hpsa_kdump_soft_reset(struct ctlr_info *h)
{
if (hpsa_send_host_reset(h, RAID_CTLR_LUNID,
HPSA_RESET_TYPE_CONTROLLER)) {
@@ -4713,8 +4759,7 @@ static void stop_controller_lockup_detector(struct ctlr_info *h)
spin_unlock_irqrestore(&lockup_detector_lock, flags);
}
-static int __devinit hpsa_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int dac, rc;
struct ctlr_info *h;
@@ -4885,10 +4930,13 @@ static void hpsa_flush_cache(struct ctlr_info *h)
dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
goto out_of_memory;
}
- fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0,
- RAID_CTLR_LUNID, TYPE_CMD);
+ if (fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0,
+ RAID_CTLR_LUNID, TYPE_CMD)) {
+ goto out;
+ }
hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_TODEVICE);
if (c->err_info->CommandStatus != 0)
+out:
dev_warn(&h->pdev->dev,
"error flushing cache on controller\n");
cmd_special_free(h, c);
@@ -4910,7 +4958,7 @@ static void hpsa_shutdown(struct pci_dev *pdev)
hpsa_free_irqs_and_disable_msix(h);
}
-static void __devexit hpsa_free_device_info(struct ctlr_info *h)
+static void hpsa_free_device_info(struct ctlr_info *h)
{
int i;
@@ -4918,7 +4966,7 @@ static void __devexit hpsa_free_device_info(struct ctlr_info *h)
kfree(h->dev[i]);
}
-static void __devexit hpsa_remove_one(struct pci_dev *pdev)
+static void hpsa_remove_one(struct pci_dev *pdev)
{
struct ctlr_info *h;
@@ -4966,7 +5014,7 @@ static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev)
static struct pci_driver hpsa_pci_driver = {
.name = HPSA,
.probe = hpsa_init_one,
- .remove = __devexit_p(hpsa_remove_one),
+ .remove = hpsa_remove_one,
.id_table = hpsa_pci_device_id, /* id_table */
.shutdown = hpsa_shutdown,
.suspend = hpsa_suspend,
@@ -5010,8 +5058,7 @@ static void calc_bucket_map(int bucket[], int num_buckets,
}
}
-static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
- u32 use_short_tags)
+static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 use_short_tags)
{
int i;
unsigned long register_value;
@@ -5079,7 +5126,7 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
h->transMethod = CFGTBL_Trans_Performant;
}
-static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
+static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
{
u32 trans_support;
int i;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 138e573..ee196b3 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -1282,8 +1282,7 @@ static int hptiop_internal_memfree_mvfrey(struct hptiop_hba *hba)
return -1;
}
-static int __devinit hptiop_probe(struct pci_dev *pcidev,
- const struct pci_device_id *id)
+static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
{
struct Scsi_Host *host = NULL;
struct hptiop_hba *hba;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 5e8d51b..4e31caa 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2179,7 +2179,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
return 0;
}
- if (vhost->state == IBMVFC_ACTIVE) {
+ if (vhost->logged_in) {
evt = ibmvfc_get_event(vhost);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
@@ -2190,7 +2190,12 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
tmf->common.length = sizeof(*tmf);
tmf->scsi_id = rport->port_id;
int_to_scsilun(sdev->lun, &tmf->lun);
- tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+ if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS))
+ type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
+ if (vhost->state == IBMVFC_ACTIVE)
+ tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+ else
+ tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID);
tmf->cancel_key = (unsigned long)sdev->hostdata;
tmf->my_cancel_key = (unsigned long)starget->hostdata;
@@ -2327,7 +2332,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
timeout = wait_for_completion_timeout(&evt->comp, timeout);
if (!timeout) {
- rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
+ rc = ibmvfc_cancel_all(sdev, 0);
if (!rc) {
rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key);
if (rc == SUCCESS)
@@ -2383,24 +2388,30 @@ out:
* @cmd: scsi command to abort
*
* Returns:
- * SUCCESS / FAILED
+ * SUCCESS / FAST_IO_FAIL / FAILED
**/
static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
struct ibmvfc_host *vhost = shost_priv(sdev->host);
- int cancel_rc, abort_rc;
+ int cancel_rc, block_rc;
int rc = FAILED;
ENTER;
- fc_block_scsi_eh(cmd);
+ block_rc = fc_block_scsi_eh(cmd);
ibmvfc_wait_while_resetting(vhost);
- cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
- abort_rc = ibmvfc_abort_task_set(sdev);
+ if (block_rc != FAST_IO_FAIL) {
+ cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
+ ibmvfc_abort_task_set(sdev);
+ } else
+ cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
- if (!cancel_rc && !abort_rc)
+ if (!cancel_rc)
rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
+ if (block_rc == FAST_IO_FAIL && rc != FAILED)
+ rc = FAST_IO_FAIL;
+
LEAVE;
return rc;
}
@@ -2410,29 +2421,47 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
* @cmd: scsi command struct
*
* Returns:
- * SUCCESS / FAILED
+ * SUCCESS / FAST_IO_FAIL / FAILED
**/
static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
struct ibmvfc_host *vhost = shost_priv(sdev->host);
- int cancel_rc, reset_rc;
+ int cancel_rc, block_rc, reset_rc = 0;
int rc = FAILED;
ENTER;
- fc_block_scsi_eh(cmd);
+ block_rc = fc_block_scsi_eh(cmd);
ibmvfc_wait_while_resetting(vhost);
- cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
- reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
+ if (block_rc != FAST_IO_FAIL) {
+ cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
+ reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
+ } else
+ cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
if (!cancel_rc && !reset_rc)
rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
+ if (block_rc == FAST_IO_FAIL && rc != FAILED)
+ rc = FAST_IO_FAIL;
+
LEAVE;
return rc;
}
/**
+ * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function
+ * @sdev: scsi device struct
+ * @data: return code
+ *
+ **/
+static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data)
+{
+ unsigned long *rc = data;
+ *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
+}
+
+/**
* ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
* @sdev: scsi device struct
* @data: return code
@@ -2449,26 +2478,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
* @cmd: scsi command struct
*
* Returns:
- * SUCCESS / FAILED
+ * SUCCESS / FAST_IO_FAIL / FAILED
**/
static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
struct ibmvfc_host *vhost = shost_priv(sdev->host);
struct scsi_target *starget = scsi_target(sdev);
- int reset_rc;
+ int block_rc;
+ int reset_rc = 0;
int rc = FAILED;
unsigned long cancel_rc = 0;
ENTER;
- fc_block_scsi_eh(cmd);
+ block_rc = fc_block_scsi_eh(cmd);
ibmvfc_wait_while_resetting(vhost);
- starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
- reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
+ if (block_rc != FAST_IO_FAIL) {
+ starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
+ reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
+ } else
+ starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset);
if (!cancel_rc && !reset_rc)
rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
+ if (block_rc == FAST_IO_FAIL && rc != FAILED)
+ rc = FAST_IO_FAIL;
+
LEAVE;
return rc;
}
@@ -2480,12 +2516,16 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
**/
static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
+ int rc, block_rc;
struct ibmvfc_host *vhost = shost_priv(cmd->device->host);
- fc_block_scsi_eh(cmd);
+ block_rc = fc_block_scsi_eh(cmd);
dev_err(vhost->dev, "Resetting connection due to error recovery\n");
rc = ibmvfc_issue_fc_host_lip(vhost->host);
+
+ if (block_rc == FAST_IO_FAIL)
+ return FAST_IO_FAIL;
+
return rc ? FAILED : SUCCESS;
}
@@ -2509,8 +2549,7 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
dev_rport = starget_to_rport(scsi_target(sdev));
if (dev_rport != rport)
continue;
- ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
- ibmvfc_abort_task_set(sdev);
+ ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
}
rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport);
@@ -4905,7 +4944,7 @@ static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev)
return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun);
}
-static struct vio_device_id ibmvfc_device_table[] __devinitdata = {
+static struct vio_device_id ibmvfc_device_table[] = {
{"fcp", "IBM,vfc-client"},
{ "", "" }
};
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 3be8af6..017a529 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -29,8 +29,8 @@
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
-#define IBMVFC_DRIVER_VERSION "1.0.10"
-#define IBMVFC_DRIVER_DATE "(August 24, 2012)"
+#define IBMVFC_DRIVER_VERSION "1.0.11"
+#define IBMVFC_DRIVER_DATE "(April 12, 2013)"
#define IBMVFC_DEFAULT_TIMEOUT 60
#define IBMVFC_ADISC_CANCEL_TIMEOUT 45
@@ -208,10 +208,10 @@ struct ibmvfc_npiv_login_resp {
u16 error;
u32 flags;
#define IBMVFC_NATIVE_FC 0x01
-#define IBMVFC_CAN_FLUSH_ON_HALT 0x08
u32 reserved;
u64 capabilities;
#define IBMVFC_CAN_FLUSH_ON_HALT 0x08
+#define IBMVFC_CAN_SUPPRESS_ABTS 0x10
u32 max_cmds;
u32 scsi_id_sz;
u64 max_dma_len;
@@ -351,6 +351,7 @@ struct ibmvfc_tmf {
#define IBMVFC_TMF_LUN_RESET 0x10
#define IBMVFC_TMF_TGT_RESET 0x20
#define IBMVFC_TMF_LUA_VALID 0x40
+#define IBMVFC_TMF_SUPPRESS_ABTS 0x80
u32 cancel_key;
u32 my_cancel_key;
u32 pad;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index ef9a54c..d0fa4b6 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1899,8 +1899,8 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
sdev->allow_restart = 1;
blk_queue_rq_timeout(sdev->request_queue, 120 * HZ);
}
- scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
return 0;
}
@@ -2362,7 +2362,7 @@ static int ibmvscsi_resume(struct device *dev)
* ibmvscsi_device_table: Used by vio.c to match devices in the device tree we
* support.
*/
-static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
+static struct vio_device_id ibmvscsi_device_table[] = {
{"vscsi", "IBM,v-scsi"},
{ "", "" }
};
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index aa7ed81..bf9eca8 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -907,7 +907,7 @@ static int ibmvstgt_remove(struct vio_dev *dev)
return 0;
}
-static struct vio_device_id ibmvstgt_device_table[] __devinitdata = {
+static struct vio_device_id ibmvstgt_device_table[] = {
{"v-scsi-host", "IBM,v-scsi-host"},
{"",""}
};
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 26cd9d1..89a8266 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -121,45 +121,26 @@ static inline void imm_pb_release(imm_struct *dev)
* testing...
* Also gives a method to use a script to obtain optimum timings (TODO)
*/
-static inline int imm_proc_write(imm_struct *dev, char *buffer, int length)
+static int imm_write_info(struct Scsi_Host *host, char *buffer, int length)
{
- unsigned long x;
+ imm_struct *dev = imm_dev(host);
if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
- x = simple_strtoul(buffer + 5, NULL, 0);
- dev->mode = x;
+ dev->mode = simple_strtoul(buffer + 5, NULL, 0);
return length;
}
printk("imm /proc: invalid variable\n");
- return (-EINVAL);
+ return -EINVAL;
}
-static int imm_proc_info(struct Scsi_Host *host, char *buffer, char **start,
- off_t offset, int length, int inout)
+static int imm_show_info(struct seq_file *m, struct Scsi_Host *host)
{
imm_struct *dev = imm_dev(host);
- int len = 0;
-
- if (inout)
- return imm_proc_write(dev, buffer, length);
-
- len += sprintf(buffer + len, "Version : %s\n", IMM_VERSION);
- len +=
- sprintf(buffer + len, "Parport : %s\n",
- dev->dev->port->name);
- len +=
- sprintf(buffer + len, "Mode : %s\n",
- IMM_MODE_STRING[dev->mode]);
- /* Request for beyond end of buffer */
- if (offset > len)
- return 0;
-
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- return len;
+ seq_printf(m, "Version : %s\n", IMM_VERSION);
+ seq_printf(m, "Parport : %s\n", dev->dev->port->name);
+ seq_printf(m, "Mode : %s\n", IMM_MODE_STRING[dev->mode]);
+ return 0;
}
#if IMM_DEBUG > 0
@@ -1118,7 +1099,8 @@ static int imm_adjust_queue(struct scsi_device *device)
static struct scsi_host_template imm_template = {
.module = THIS_MODULE,
.proc_name = "imm",
- .proc_info = imm_proc_info,
+ .show_info = imm_show_info,
+ .write_info = imm_write_info,
.name = "Iomega VPI2 (imm) interface",
.queuecommand = imm_queuecommand,
.eh_abort_handler = imm_abort,
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index deb5b6d..bf02821 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -2166,152 +2166,117 @@ static int in2000_biosparam(struct scsi_device *sdev, struct block_device *bdev,
}
-static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
+static int in2000_write_info(struct Scsi_Host *instance, char *buf, int len)
{
#ifdef PROC_INTERFACE
char *bp;
- char tbuf[128];
- unsigned long flags;
struct IN2000_hostdata *hd;
- Scsi_Cmnd *cmd;
int x, i;
- static int stop = 0;
hd = (struct IN2000_hostdata *) instance->hostdata;
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
- * keywords (same format as command-line, but only ONE per read):
- * debug
- * disconnect
- * period
- * resync
- * proc
- */
-
- if (in) {
- buf[len] = '\0';
- bp = buf;
- if (!strncmp(bp, "debug:", 6)) {
- bp += 6;
- hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
- } else if (!strncmp(bp, "disconnect:", 11)) {
- bp += 11;
- x = simple_strtoul(bp, NULL, 0);
- if (x < DIS_NEVER || x > DIS_ALWAYS)
- x = DIS_ADAPTIVE;
- hd->disconnect = x;
- } else if (!strncmp(bp, "period:", 7)) {
- bp += 7;
- x = simple_strtoul(bp, NULL, 0);
- hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
- } else if (!strncmp(bp, "resync:", 7)) {
- bp += 7;
- x = simple_strtoul(bp, NULL, 0);
- for (i = 0; i < 7; i++)
- if (x & (1 << i))
- hd->sync_stat[i] = SS_UNSET;
- } else if (!strncmp(bp, "proc:", 5)) {
- bp += 5;
- hd->proc = simple_strtoul(bp, NULL, 0);
- } else if (!strncmp(bp, "level2:", 7)) {
- bp += 7;
- hd->level2 = simple_strtoul(bp, NULL, 0);
- }
- return len;
+ buf[len] = '\0';
+ bp = buf;
+ if (!strncmp(bp, "debug:", 6)) {
+ bp += 6;
+ hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
+ } else if (!strncmp(bp, "disconnect:", 11)) {
+ bp += 11;
+ x = simple_strtoul(bp, NULL, 0);
+ if (x < DIS_NEVER || x > DIS_ALWAYS)
+ x = DIS_ADAPTIVE;
+ hd->disconnect = x;
+ } else if (!strncmp(bp, "period:", 7)) {
+ bp += 7;
+ x = simple_strtoul(bp, NULL, 0);
+ hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
+ } else if (!strncmp(bp, "resync:", 7)) {
+ bp += 7;
+ x = simple_strtoul(bp, NULL, 0);
+ for (i = 0; i < 7; i++)
+ if (x & (1 << i))
+ hd->sync_stat[i] = SS_UNSET;
+ } else if (!strncmp(bp, "proc:", 5)) {
+ bp += 5;
+ hd->proc = simple_strtoul(bp, NULL, 0);
+ } else if (!strncmp(bp, "level2:", 7)) {
+ bp += 7;
+ hd->level2 = simple_strtoul(bp, NULL, 0);
}
+#endif
+ return len;
+}
+
+static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+
+#ifdef PROC_INTERFACE
+ unsigned long flags;
+ struct IN2000_hostdata *hd;
+ Scsi_Cmnd *cmd;
+ int x;
+
+ hd = (struct IN2000_hostdata *) instance->hostdata;
spin_lock_irqsave(instance->host_lock, flags);
- bp = buf;
- *bp = '\0';
- if (hd->proc & PR_VERSION) {
- sprintf(tbuf, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
- strcat(bp, tbuf);
- }
+ if (hd->proc & PR_VERSION)
+ seq_printf(m, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
+
if (hd->proc & PR_INFO) {
- sprintf(tbuf, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
- strcat(bp, tbuf);
- strcat(bp, "\nsync_xfer[] = ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
- strcat(bp, tbuf);
- }
- strcat(bp, "\nsync_stat[] = ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
- strcat(bp, tbuf);
- }
+ seq_printf(m, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
+ seq_printf(m, "\nsync_xfer[] = ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%02x", hd->sync_xfer[x]);
+ seq_printf(m, "\nsync_stat[] = ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%02x", hd->sync_stat[x]);
}
#ifdef PROC_STATISTICS
if (hd->proc & PR_STATISTICS) {
- strcat(bp, "\ncommands issued: ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
- strcat(bp, tbuf);
- }
- strcat(bp, "\ndisconnects allowed:");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
- strcat(bp, tbuf);
- }
- strcat(bp, "\ndisconnects done: ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
- strcat(bp, tbuf);
- }
- sprintf(tbuf, "\ninterrupts: \t%ld", hd->int_cnt);
- strcat(bp, tbuf);
+ seq_printf(m, "\ncommands issued: ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
+ seq_printf(m, "\ndisconnects allowed:");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
+ seq_printf(m, "\ndisconnects done: ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
+ seq_printf(m, "\ninterrupts: \t%ld", hd->int_cnt);
}
#endif
if (hd->proc & PR_CONNECTED) {
- strcat(bp, "\nconnected: ");
+ seq_printf(m, "\nconnected: ");
if (hd->connected) {
cmd = (Scsi_Cmnd *) hd->connected;
- sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
- strcat(bp, tbuf);
+ seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
}
}
if (hd->proc & PR_INPUTQ) {
- strcat(bp, "\ninput_Q: ");
+ seq_printf(m, "\ninput_Q: ");
cmd = (Scsi_Cmnd *) hd->input_Q;
while (cmd) {
- sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
- strcat(bp, tbuf);
+ seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
}
if (hd->proc & PR_DISCQ) {
- strcat(bp, "\ndisconnected_Q:");
+ seq_printf(m, "\ndisconnected_Q:");
cmd = (Scsi_Cmnd *) hd->disconnected_Q;
while (cmd) {
- sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
- strcat(bp, tbuf);
+ seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
}
if (hd->proc & PR_TEST) {
; /* insert your own custom function here */
}
- strcat(bp, "\n");
+ seq_printf(m, "\n");
spin_unlock_irqrestore(instance->host_lock, flags);
- *start = buf;
- if (stop) {
- stop = 0;
- return 0; /* return 0 to signal end-of-file */
- }
- if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */
- stop = 1;
- if (hd->proc & PR_STOP) /* stop every other time */
- stop = 1;
- return strlen(bp);
-
-#else /* PROC_INTERFACE */
-
- return 0;
-
#endif /* PROC_INTERFACE */
-
+ return 0;
}
MODULE_LICENSE("GPL");
@@ -2319,7 +2284,8 @@ MODULE_LICENSE("GPL");
static struct scsi_host_template driver_template = {
.proc_name = "in2000",
- .proc_info = in2000_proc_info,
+ .write_info = in2000_write_info,
+ .show_info = in2000_show_info,
.name = "Always IN2000",
.detect = in2000_detect,
.release = in2000_release,
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index dd741bc..280d5af 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2992,7 +2992,7 @@ static struct pci_driver initio_pci_driver = {
.name = "initio",
.id_table = initio_pci_tbl,
.probe = initio_probe_one,
- .remove = __devexit_p(initio_remove_one),
+ .remove = initio_remove_one,
};
static int __init initio_init_driver(void)
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fe6029f..6601e03 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -98,6 +98,7 @@ static unsigned int ipr_transop_timeout = 0;
static unsigned int ipr_debug = 0;
static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS;
static unsigned int ipr_dual_ioa_raid = 1;
+static unsigned int ipr_number_of_msix = 2;
static DEFINE_SPINLOCK(ipr_driver_lock);
/* This table describes the differences between DMA controller chips */
@@ -107,6 +108,7 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
.max_cmds = 100,
.cache_line_size = 0x20,
.clear_isr = 1,
+ .iopoll_weight = 0,
{
.set_interrupt_mask_reg = 0x0022C,
.clr_interrupt_mask_reg = 0x00230,
@@ -131,6 +133,7 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
.max_cmds = 100,
.cache_line_size = 0x20,
.clear_isr = 1,
+ .iopoll_weight = 0,
{
.set_interrupt_mask_reg = 0x00288,
.clr_interrupt_mask_reg = 0x0028C,
@@ -155,6 +158,7 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
.max_cmds = 1000,
.cache_line_size = 0x20,
.clear_isr = 0,
+ .iopoll_weight = 64,
{
.set_interrupt_mask_reg = 0x00010,
.clr_interrupt_mask_reg = 0x00018,
@@ -215,6 +219,8 @@ MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to e
module_param_named(max_devs, ipr_max_devs, int, 0);
MODULE_PARM_DESC(max_devs, "Specify the maximum number of physical devices. "
"[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]");
+module_param_named(number_of_msix, ipr_number_of_msix, int, 0);
+MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 5). (default:2)");
MODULE_LICENSE("GPL");
MODULE_VERSION(IPR_DRIVER_VERSION);
@@ -275,12 +281,22 @@ struct ipr_error_table_t ipr_error_table[] = {
"FFF6: Failure prediction threshold exceeded"},
{0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL,
"8009: Impending cache battery pack failure"},
+ {0x02040100, 0, 0,
+ "Logical Unit in process of becoming ready"},
+ {0x02040200, 0, 0,
+ "Initializing command required"},
{0x02040400, 0, 0,
"34FF: Disk device format in progress"},
+ {0x02040C00, 0, 0,
+ "Logical unit not accessible, target port in unavailable state"},
{0x02048000, 0, IPR_DEFAULT_LOG_LEVEL,
"9070: IOA requested reset"},
{0x023F0000, 0, 0,
"Synchronization required"},
+ {0x02408500, 0, 0,
+ "IOA microcode download required"},
+ {0x02408600, 0, 0,
+ "Device bus connection is prohibited by host"},
{0x024E0000, 0, 0,
"No ready, IOA shutdown"},
{0x025A0000, 0, 0,
@@ -379,6 +395,8 @@ struct ipr_error_table_t ipr_error_table[] = {
"4030: Incorrect multipath connection"},
{0x04679000, 0, IPR_DEFAULT_LOG_LEVEL,
"4110: Unsupported enclosure function"},
+ {0x04679800, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4120: SAS cable VPD cannot be read"},
{0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF4: Command to logical unit failed"},
{0x05240000, 1, 0,
@@ -401,10 +419,18 @@ struct ipr_error_table_t ipr_error_table[] = {
"Illegal request, command sequence error"},
{0x052C8000, 1, 0,
"Illegal request, dual adapter support not enabled"},
+ {0x052C8100, 1, 0,
+ "Illegal request, another cable connector was physically disabled"},
+ {0x054E8000, 1, 0,
+ "Illegal request, inconsistent group id/group count"},
{0x06040500, 0, IPR_DEFAULT_LOG_LEVEL,
"9031: Array protection temporarily suspended, protection resuming"},
{0x06040600, 0, IPR_DEFAULT_LOG_LEVEL,
"9040: Array protection temporarily suspended, protection resuming"},
+ {0x060B0100, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4080: IOA exceeded maximum operating temperature"},
+ {0x060B8000, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4085: Service required"},
{0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
"3140: Device bus not ready to ready transition"},
{0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
@@ -417,6 +443,8 @@ struct ipr_error_table_t ipr_error_table[] = {
"FFFB: SCSI bus was reset by another initiator"},
{0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL,
"3029: A device replacement has occurred"},
+ {0x063F8300, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4102: Device bus fabric performance degradation"},
{0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL,
"9051: IOA cache data exists for a missing or failed device"},
{0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL,
@@ -439,6 +467,14 @@ struct ipr_error_table_t ipr_error_table[] = {
"9076: Configuration error, missing remote IOA"},
{0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
"4050: Enclosure does not support a required multipath function"},
+ {0x06679800, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4121: Configuration error, required cable is missing"},
+ {0x06679900, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4122: Cable is not plugged into the correct location on remote IOA"},
+ {0x06679A00, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4123: Configuration error, invalid cable vital product data"},
+ {0x06679B00, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4124: Configuration error, both cable ends are plugged into the same IOA"},
{0x06690000, 0, IPR_DEFAULT_LOG_LEVEL,
"4070: Logically bad block written on device"},
{0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
@@ -501,10 +537,18 @@ struct ipr_error_table_t ipr_error_table[] = {
"9062: One or more disks are missing from an array"},
{0x07279900, 0, IPR_DEFAULT_LOG_LEVEL,
"9063: Maximum number of functional arrays has been exceeded"},
+ {0x07279A00, 0, 0,
+ "Data protect, other volume set problem"},
{0x0B260000, 0, 0,
"Aborted command, invalid descriptor"},
+ {0x0B3F9000, 0, 0,
+ "Target operating conditions have changed, dual adapter takeover"},
+ {0x0B530200, 0, 0,
+ "Aborted command, medium removal prevented"},
{0x0B5A0000, 0, 0,
- "Command terminated by host"}
+ "Command terminated by host"},
+ {0x0B5B8000, 0, 0,
+ "Aborted command, command terminated by host"}
};
static const struct ipr_ses_table_entry ipr_ses_table[] = {
@@ -549,7 +593,8 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
struct ipr_trace_entry *trace_entry;
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
- trace_entry = &ioa_cfg->trace[ioa_cfg->trace_index++];
+ trace_entry = &ioa_cfg->trace[atomic_add_return
+ (1, &ioa_cfg->trace_index)%IPR_NUM_TRACE_ENTRIES];
trace_entry->time = jiffies;
trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];
trace_entry->type = type;
@@ -560,6 +605,7 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
trace_entry->cmd_index = ipr_cmd->cmd_index & 0xff;
trace_entry->res_handle = ipr_cmd->ioarcb.res_handle;
trace_entry->u.add_data = add_data;
+ wmb();
}
#else
#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while (0)
@@ -595,8 +641,11 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64;
dma_addr_t dma_addr = ipr_cmd->dma_addr;
+ int hrrq_id;
+ hrrq_id = ioarcb->cmd_pkt.hrrq_id;
memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
+ ioarcb->cmd_pkt.hrrq_id = hrrq_id;
ioarcb->data_transfer_length = 0;
ioarcb->read_data_transfer_length = 0;
ioarcb->ioadl_len = 0;
@@ -646,12 +695,16 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd,
* pointer to ipr command struct
**/
static
-struct ipr_cmnd *__ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg)
+struct ipr_cmnd *__ipr_get_free_ipr_cmnd(struct ipr_hrr_queue *hrrq)
{
- struct ipr_cmnd *ipr_cmd;
+ struct ipr_cmnd *ipr_cmd = NULL;
+
+ if (likely(!list_empty(&hrrq->hrrq_free_q))) {
+ ipr_cmd = list_entry(hrrq->hrrq_free_q.next,
+ struct ipr_cmnd, queue);
+ list_del(&ipr_cmd->queue);
+ }
- ipr_cmd = list_entry(ioa_cfg->free_q.next, struct ipr_cmnd, queue);
- list_del(&ipr_cmd->queue);
return ipr_cmd;
}
@@ -666,7 +719,8 @@ struct ipr_cmnd *__ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg)
static
struct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg)
{
- struct ipr_cmnd *ipr_cmd = __ipr_get_free_ipr_cmnd(ioa_cfg);
+ struct ipr_cmnd *ipr_cmd =
+ __ipr_get_free_ipr_cmnd(&ioa_cfg->hrrq[IPR_INIT_HRRQ]);
ipr_init_ipr_cmnd(ipr_cmd, ipr_lock_and_done);
return ipr_cmd;
}
@@ -686,9 +740,15 @@ static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,
u32 clr_ints)
{
volatile u32 int_reg;
+ int i;
/* Stop new interrupts */
- ioa_cfg->allow_interrupts = 0;
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].allow_interrupts = 0;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
/* Set interrupt mask to stop all new interrupts */
if (ioa_cfg->sis64)
@@ -761,13 +821,12 @@ static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
**/
static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
{
- struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct ata_queued_cmd *qc = ipr_cmd->qc;
struct ipr_sata_port *sata_port = qc->ap->private_data;
qc->err_mask |= AC_ERR_OTHER;
sata_port->ioasa.status |= ATA_BUSY;
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
ata_qc_complete(qc);
}
@@ -783,14 +842,13 @@ static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
**/
static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
{
- struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
scsi_cmd->result |= (DID_ERROR << 16);
scsi_dma_unmap(ipr_cmd->scsi_cmd);
scsi_cmd->scsi_done(scsi_cmd);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
}
/**
@@ -805,24 +863,32 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg)
{
struct ipr_cmnd *ipr_cmd, *temp;
+ struct ipr_hrr_queue *hrrq;
ENTER;
- list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) {
- list_del(&ipr_cmd->queue);
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock(&hrrq->_lock);
+ list_for_each_entry_safe(ipr_cmd,
+ temp, &hrrq->hrrq_pending_q, queue) {
+ list_del(&ipr_cmd->queue);
- ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
- ipr_cmd->s.ioasa.hdr.ilid = cpu_to_be32(IPR_DRIVER_ILID);
+ ipr_cmd->s.ioasa.hdr.ioasc =
+ cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
+ ipr_cmd->s.ioasa.hdr.ilid =
+ cpu_to_be32(IPR_DRIVER_ILID);
- if (ipr_cmd->scsi_cmd)
- ipr_cmd->done = ipr_scsi_eh_done;
- else if (ipr_cmd->qc)
- ipr_cmd->done = ipr_sata_eh_done;
+ if (ipr_cmd->scsi_cmd)
+ ipr_cmd->done = ipr_scsi_eh_done;
+ else if (ipr_cmd->qc)
+ ipr_cmd->done = ipr_sata_eh_done;
- ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, IPR_IOASC_IOA_WAS_RESET);
- del_timer(&ipr_cmd->timer);
- ipr_cmd->done(ipr_cmd);
+ ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH,
+ IPR_IOASC_IOA_WAS_RESET);
+ del_timer(&ipr_cmd->timer);
+ ipr_cmd->done(ipr_cmd);
+ }
+ spin_unlock(&hrrq->_lock);
}
-
LEAVE;
}
@@ -872,9 +938,7 @@ static void ipr_do_req(struct ipr_cmnd *ipr_cmd,
void (*done) (struct ipr_cmnd *),
void (*timeout_func) (struct ipr_cmnd *), u32 timeout)
{
- struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
ipr_cmd->done = done;
@@ -975,6 +1039,14 @@ static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd,
spin_lock_irq(ioa_cfg->host->host_lock);
}
+static int ipr_get_hrrq_index(struct ipr_ioa_cfg *ioa_cfg)
+{
+ if (ioa_cfg->hrrq_num == 1)
+ return 0;
+ else
+ return (atomic_add_return(1, &ioa_cfg->hrrq_index) % (ioa_cfg->hrrq_num - 1)) + 1;
+}
+
/**
* ipr_send_hcam - Send an HCAM to the adapter.
* @ioa_cfg: ioa config struct
@@ -994,9 +1066,9 @@ static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type,
struct ipr_cmnd *ipr_cmd;
struct ipr_ioarcb *ioarcb;
- if (ioa_cfg->allow_cmds) {
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_pending_q);
ipr_cmd->u.hostrcb = hostrcb;
@@ -1166,14 +1238,15 @@ static int ipr_is_same_device(struct ipr_resource_entry *res,
}
/**
- * ipr_format_res_path - Format the resource path for printing.
+ * __ipr_format_res_path - Format the resource path for printing.
* @res_path: resource path
* @buf: buffer
+ * @len: length of buffer provided
*
* Return value:
* pointer to buffer
**/
-static char *ipr_format_res_path(u8 *res_path, char *buffer, int len)
+static char *__ipr_format_res_path(u8 *res_path, char *buffer, int len)
{
int i;
char *p = buffer;
@@ -1187,6 +1260,27 @@ static char *ipr_format_res_path(u8 *res_path, char *buffer, int len)
}
/**
+ * ipr_format_res_path - Format the resource path for printing.
+ * @ioa_cfg: ioa config struct
+ * @res_path: resource path
+ * @buf: buffer
+ * @len: length of buffer provided
+ *
+ * Return value:
+ * pointer to buffer
+ **/
+static char *ipr_format_res_path(struct ipr_ioa_cfg *ioa_cfg,
+ u8 *res_path, char *buffer, int len)
+{
+ char *p = buffer;
+
+ *p = '\0';
+ p += snprintf(p, buffer + len - p, "%d/", ioa_cfg->host->host_no);
+ __ipr_format_res_path(res_path, p, len - (buffer - p));
+ return buffer;
+}
+
+/**
* ipr_update_res_entry - Update the resource entry.
* @res: resource entry struct
* @cfgtew: config table entry wrapper struct
@@ -1226,8 +1320,8 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res,
if (res->sdev && new_path)
sdev_printk(KERN_INFO, res->sdev, "Resource path: %s\n",
- ipr_format_res_path(res->res_path, buffer,
- sizeof(buffer)));
+ ipr_format_res_path(res->ioa_cfg,
+ res->res_path, buffer, sizeof(buffer)));
} else {
res->flags = cfgtew->u.cfgte->flags;
if (res->flags & IPR_IS_IOA_RESOURCE)
@@ -1363,7 +1457,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
list_del(&hostrcb->queue);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
if (ioasc) {
if (ioasc != IPR_IOASC_IOA_WAS_RESET)
@@ -1613,8 +1707,8 @@ static void ipr_log_sis64_config_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err_separator;
ipr_err("Device %d : %s", i + 1,
- ipr_format_res_path(dev_entry->res_path, buffer,
- sizeof(buffer)));
+ __ipr_format_res_path(dev_entry->res_path,
+ buffer, sizeof(buffer)));
ipr_log_ext_vpd(&dev_entry->vpd);
ipr_err("-----New Device Information-----\n");
@@ -1960,14 +2054,16 @@ static void ipr_log64_fabric_path(struct ipr_hostrcb *hostrcb,
ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s\n",
path_active_desc[i].desc, path_state_desc[j].desc,
- ipr_format_res_path(fabric->res_path, buffer,
- sizeof(buffer)));
+ ipr_format_res_path(hostrcb->ioa_cfg,
+ fabric->res_path,
+ buffer, sizeof(buffer)));
return;
}
}
ipr_err("Path state=%02X Resource Path=%s\n", path_state,
- ipr_format_res_path(fabric->res_path, buffer, sizeof(buffer)));
+ ipr_format_res_path(hostrcb->ioa_cfg, fabric->res_path,
+ buffer, sizeof(buffer)));
}
static const struct {
@@ -2108,18 +2204,20 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,
ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s, Link rate=%s, WWN=%08X%08X\n",
path_status_desc[j].desc, path_type_desc[i].desc,
- ipr_format_res_path(cfg->res_path, buffer,
- sizeof(buffer)),
- link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
- be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
+ ipr_format_res_path(hostrcb->ioa_cfg,
+ cfg->res_path, buffer, sizeof(buffer)),
+ link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
+ be32_to_cpu(cfg->wwid[0]),
+ be32_to_cpu(cfg->wwid[1]));
return;
}
}
ipr_hcam_err(hostrcb, "Path element=%02X: Resource Path=%s, Link rate=%s "
"WWN=%08X%08X\n", cfg->type_status,
- ipr_format_res_path(cfg->res_path, buffer, sizeof(buffer)),
- link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
- be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
+ ipr_format_res_path(hostrcb->ioa_cfg,
+ cfg->res_path, buffer, sizeof(buffer)),
+ link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
+ be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
}
/**
@@ -2182,7 +2280,8 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("RAID %s Array Configuration: %s\n",
error->protection_level,
- ipr_format_res_path(error->last_res_path, buffer, sizeof(buffer)));
+ ipr_format_res_path(ioa_cfg, error->last_res_path,
+ buffer, sizeof(buffer)));
ipr_err_separator;
@@ -2203,11 +2302,12 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("Array Member %d:\n", i);
ipr_log_ext_vpd(&array_entry->vpd);
ipr_err("Current Location: %s\n",
- ipr_format_res_path(array_entry->res_path, buffer,
- sizeof(buffer)));
+ ipr_format_res_path(ioa_cfg, array_entry->res_path,
+ buffer, sizeof(buffer)));
ipr_err("Expected Location: %s\n",
- ipr_format_res_path(array_entry->expected_res_path,
- buffer, sizeof(buffer)));
+ ipr_format_res_path(ioa_cfg,
+ array_entry->expected_res_path,
+ buffer, sizeof(buffer)));
ipr_err_separator;
}
@@ -2409,7 +2509,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc);
list_del(&hostrcb->queue);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
if (!ioasc) {
ipr_handle_log_data(ioa_cfg, hostrcb);
@@ -2491,36 +2591,6 @@ static void ipr_oper_timeout(struct ipr_cmnd *ipr_cmd)
}
/**
- * ipr_reset_reload - Reset/Reload the IOA
- * @ioa_cfg: ioa config struct
- * @shutdown_type: shutdown type
- *
- * This function resets the adapter and re-initializes it.
- * This function assumes that all new host commands have been stopped.
- * Return value:
- * SUCCESS / FAILED
- **/
-static int ipr_reset_reload(struct ipr_ioa_cfg *ioa_cfg,
- enum ipr_shutdown_type shutdown_type)
-{
- if (!ioa_cfg->in_reset_reload)
- ipr_initiate_ioa_reset(ioa_cfg, shutdown_type);
-
- spin_unlock_irq(ioa_cfg->host->host_lock);
- wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
- spin_lock_irq(ioa_cfg->host->host_lock);
-
- /* If we got hit with a host reset while we were already resetting
- the adapter for some reason, and the reset failed. */
- if (ioa_cfg->ioa_is_dead) {
- ipr_trace;
- return FAILED;
- }
-
- return SUCCESS;
-}
-
-/**
* ipr_find_ses_entry - Find matching SES in SES table
* @res: resource entry struct of SES
*
@@ -3153,7 +3223,8 @@ static void ipr_worker_thread(struct work_struct *work)
restart:
do {
did_work = 0;
- if (!ioa_cfg->allow_cmds || !ioa_cfg->allow_ml_add_del) {
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds ||
+ !ioa_cfg->allow_ml_add_del) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return;
}
@@ -3401,7 +3472,7 @@ static ssize_t ipr_show_adapter_state(struct device *dev,
int len;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- if (ioa_cfg->ioa_is_dead)
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead)
len = snprintf(buf, PAGE_SIZE, "offline\n");
else
len = snprintf(buf, PAGE_SIZE, "online\n");
@@ -3427,14 +3498,20 @@ static ssize_t ipr_store_adapter_state(struct device *dev,
struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags;
- int result = count;
+ int result = count, i;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- if (ioa_cfg->ioa_is_dead && !strncmp(buf, "online", 6)) {
- ioa_cfg->ioa_is_dead = 0;
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead &&
+ !strncmp(buf, "online", 6)) {
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].ioa_is_dead = 0;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
ioa_cfg->reset_retries = 0;
ioa_cfg->in_ioa_bringdown = 0;
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
@@ -3494,6 +3571,95 @@ static struct device_attribute ipr_ioa_reset_attr = {
.store = ipr_store_reset_adapter
};
+static int ipr_iopoll(struct blk_iopoll *iop, int budget);
+ /**
+ * ipr_show_iopoll_weight - Show ipr polling mode
+ * @dev: class device struct
+ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_iopoll_weight(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ int len;
+
+ spin_lock_irqsave(shost->host_lock, lock_flags);
+ len = snprintf(buf, PAGE_SIZE, "%d\n", ioa_cfg->iopoll_weight);
+ spin_unlock_irqrestore(shost->host_lock, lock_flags);
+
+ return len;
+}
+
+/**
+ * ipr_store_iopoll_weight - Change the adapter's polling mode
+ * @dev: class device struct
+ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+static ssize_t ipr_store_iopoll_weight(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long user_iopoll_weight;
+ unsigned long lock_flags = 0;
+ int i;
+
+ if (!ioa_cfg->sis64) {
+ dev_info(&ioa_cfg->pdev->dev, "blk-iopoll not supported on this adapter\n");
+ return -EINVAL;
+ }
+ if (kstrtoul(buf, 10, &user_iopoll_weight))
+ return -EINVAL;
+
+ if (user_iopoll_weight > 256) {
+ dev_info(&ioa_cfg->pdev->dev, "Invalid blk-iopoll weight. It must be less than 256\n");
+ return -EINVAL;
+ }
+
+ if (user_iopoll_weight == ioa_cfg->iopoll_weight) {
+ dev_info(&ioa_cfg->pdev->dev, "Current blk-iopoll weight has the same weight\n");
+ return strlen(buf);
+ }
+
+ if (blk_iopoll_enabled && ioa_cfg->iopoll_weight &&
+ ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
+ for (i = 1; i < ioa_cfg->hrrq_num; i++)
+ blk_iopoll_disable(&ioa_cfg->hrrq[i].iopoll);
+ }
+
+ spin_lock_irqsave(shost->host_lock, lock_flags);
+ ioa_cfg->iopoll_weight = user_iopoll_weight;
+ if (blk_iopoll_enabled && ioa_cfg->iopoll_weight &&
+ ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
+ for (i = 1; i < ioa_cfg->hrrq_num; i++) {
+ blk_iopoll_init(&ioa_cfg->hrrq[i].iopoll,
+ ioa_cfg->iopoll_weight, ipr_iopoll);
+ blk_iopoll_enable(&ioa_cfg->hrrq[i].iopoll);
+ }
+ }
+ spin_unlock_irqrestore(shost->host_lock, lock_flags);
+
+ return strlen(buf);
+}
+
+static struct device_attribute ipr_iopoll_weight_attr = {
+ .attr = {
+ .name = "iopoll_weight",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .show = ipr_show_iopoll_weight,
+ .store = ipr_store_iopoll_weight
+};
+
/**
* ipr_alloc_ucode_buffer - Allocates a microcode download buffer
* @buf_len: buffer length
@@ -3862,6 +4028,7 @@ static struct device_attribute *ipr_ioa_attrs[] = {
&ipr_ioa_reset_attr,
&ipr_update_fw_attr,
&ipr_ioa_fw_type_attr,
+ &ipr_iopoll_weight_attr,
NULL,
};
@@ -4014,7 +4181,7 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
ioa_cfg->dump = dump;
ioa_cfg->sdt_state = WAIT_FOR_DUMP;
- if (ioa_cfg->ioa_is_dead && !ioa_cfg->dump_taken) {
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead && !ioa_cfg->dump_taken) {
ioa_cfg->dump_taken = 1;
schedule_work(&ioa_cfg->work_q);
}
@@ -4227,8 +4394,8 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut
res = (struct ipr_resource_entry *)sdev->hostdata;
if (res && ioa_cfg->sis64)
len = snprintf(buf, PAGE_SIZE, "%s\n",
- ipr_format_res_path(res->res_path, buffer,
- sizeof(buffer)));
+ __ipr_format_res_path(res->res_path, buffer,
+ sizeof(buffer)));
else if (res)
len = snprintf(buf, PAGE_SIZE, "%d:%d:%d:%d\n", ioa_cfg->host->host_no,
res->bus, res->target, res->lun);
@@ -4556,8 +4723,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
if (ioa_cfg->sis64)
sdev_printk(KERN_INFO, sdev, "Resource path: %s\n",
- ipr_format_res_path(res->res_path, buffer,
- sizeof(buffer)));
+ ipr_format_res_path(ioa_cfg,
+ res->res_path, buffer, sizeof(buffer)));
return 0;
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -4638,22 +4805,18 @@ static int ipr_slave_alloc(struct scsi_device *sdev)
return rc;
}
-/**
- * ipr_eh_host_reset - Reset the host adapter
- * @scsi_cmd: scsi command struct
- *
- * Return value:
- * SUCCESS / FAILED
- **/
-static int __ipr_eh_host_reset(struct scsi_cmnd *scsi_cmd)
+static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
{
struct ipr_ioa_cfg *ioa_cfg;
- int rc;
+ unsigned long lock_flags = 0;
+ int rc = SUCCESS;
ENTER;
- ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
+ ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- if (!ioa_cfg->in_reset_reload) {
+ if (!ioa_cfg->in_reset_reload && !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) {
+ ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV);
dev_err(&ioa_cfg->pdev->dev,
"Adapter being reset as a result of error recovery.\n");
@@ -4661,20 +4824,19 @@ static int __ipr_eh_host_reset(struct scsi_cmnd *scsi_cmd)
ioa_cfg->sdt_state = GET_DUMP;
}
- rc = ipr_reset_reload(ioa_cfg, IPR_SHUTDOWN_ABBREV);
-
- LEAVE;
- return rc;
-}
-
-static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
-{
- int rc;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- spin_lock_irq(cmd->device->host->host_lock);
- rc = __ipr_eh_host_reset(cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
+ /* If we got hit with a host reset while we were already resetting
+ the adapter for some reason, and the reset failed. */
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) {
+ ipr_trace;
+ rc = FAILED;
+ }
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ LEAVE;
return rc;
}
@@ -4723,7 +4885,7 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) {
if (ipr_cmd->ioa_cfg->sis64)
memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata,
@@ -4793,6 +4955,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
struct ipr_resource_entry *res;
struct ata_port *ap;
int rc = 0;
+ struct ipr_hrr_queue *hrrq;
ENTER;
ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
@@ -4808,22 +4971,26 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
*/
if (ioa_cfg->in_reset_reload)
return FAILED;
- if (ioa_cfg->ioa_is_dead)
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead)
return FAILED;
- list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
- if (ipr_cmd->ioarcb.res_handle == res->res_handle) {
- if (ipr_cmd->scsi_cmd)
- ipr_cmd->done = ipr_scsi_eh_done;
- if (ipr_cmd->qc)
- ipr_cmd->done = ipr_sata_eh_done;
- if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
- ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
- ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock(&hrrq->_lock);
+ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+ if (ipr_cmd->ioarcb.res_handle == res->res_handle) {
+ if (ipr_cmd->scsi_cmd)
+ ipr_cmd->done = ipr_scsi_eh_done;
+ if (ipr_cmd->qc)
+ ipr_cmd->done = ipr_sata_eh_done;
+ if (ipr_cmd->qc &&
+ !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
+ ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
+ ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
+ }
}
}
+ spin_unlock(&hrrq->_lock);
}
-
res->resetting_device = 1;
scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n");
@@ -4833,11 +5000,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
ata_std_error_handler(ap);
spin_lock_irq(scsi_cmd->device->host->host_lock);
- list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
- if (ipr_cmd->ioarcb.res_handle == res->res_handle) {
- rc = -EIO;
- break;
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock(&hrrq->_lock);
+ list_for_each_entry(ipr_cmd,
+ &hrrq->hrrq_pending_q, queue) {
+ if (ipr_cmd->ioarcb.res_handle ==
+ res->res_handle) {
+ rc = -EIO;
+ break;
+ }
}
+ spin_unlock(&hrrq->_lock);
}
} else
rc = ipr_device_reset(ioa_cfg, res);
@@ -4890,7 +5063,7 @@ static void ipr_bus_reset_done(struct ipr_cmnd *ipr_cmd)
else
ipr_cmd->sibling->done(ipr_cmd->sibling);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
LEAVE;
}
@@ -4951,6 +5124,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
struct ipr_cmd_pkt *cmd_pkt;
u32 ioasc, int_reg;
int op_found = 0;
+ struct ipr_hrr_queue *hrrq;
ENTER;
ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
@@ -4960,7 +5134,8 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
* This will force the mid-layer to call ipr_eh_host_reset,
* which will then go to sleep and wait for the reset to complete
*/
- if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
+ if (ioa_cfg->in_reset_reload ||
+ ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead)
return FAILED;
if (!res)
return FAILED;
@@ -4975,12 +5150,16 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
if (!ipr_is_gscsi(res))
return FAILED;
- list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
- if (ipr_cmd->scsi_cmd == scsi_cmd) {
- ipr_cmd->done = ipr_scsi_eh_done;
- op_found = 1;
- break;
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock(&hrrq->_lock);
+ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+ if (ipr_cmd->scsi_cmd == scsi_cmd) {
+ ipr_cmd->done = ipr_scsi_eh_done;
+ op_found = 1;
+ break;
+ }
}
+ spin_unlock(&hrrq->_lock);
}
if (!op_found)
@@ -5007,7 +5186,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
ipr_trace;
}
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
if (!ipr_is_naca_model(res))
res->needs_sync_complete = 1;
@@ -5099,6 +5278,9 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
} else {
if (int_reg & IPR_PCII_IOA_UNIT_CHECKED)
ioa_cfg->ioa_unit_checked = 1;
+ else if (int_reg & IPR_PCII_NO_HOST_RRQ)
+ dev_err(&ioa_cfg->pdev->dev,
+ "No Host RRQ. 0x%08X\n", int_reg);
else
dev_err(&ioa_cfg->pdev->dev,
"Permanent IOA failure. 0x%08X\n", int_reg);
@@ -5121,10 +5303,10 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
* Return value:
* none
**/
-static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg)
+static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg, u16 number)
{
ioa_cfg->errors_logged++;
- dev_err(&ioa_cfg->pdev->dev, "%s\n", msg);
+ dev_err(&ioa_cfg->pdev->dev, "%s %d\n", msg, number);
if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
ioa_cfg->sdt_state = GET_DUMP;
@@ -5132,6 +5314,83 @@ static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg)
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
}
+static int ipr_process_hrrq(struct ipr_hrr_queue *hrr_queue, int budget,
+ struct list_head *doneq)
+{
+ u32 ioasc;
+ u16 cmd_index;
+ struct ipr_cmnd *ipr_cmd;
+ struct ipr_ioa_cfg *ioa_cfg = hrr_queue->ioa_cfg;
+ int num_hrrq = 0;
+
+ /* If interrupts are disabled, ignore the interrupt */
+ if (!hrr_queue->allow_interrupts)
+ return 0;
+
+ while ((be32_to_cpu(*hrr_queue->hrrq_curr) & IPR_HRRQ_TOGGLE_BIT) ==
+ hrr_queue->toggle_bit) {
+
+ cmd_index = (be32_to_cpu(*hrr_queue->hrrq_curr) &
+ IPR_HRRQ_REQ_RESP_HANDLE_MASK) >>
+ IPR_HRRQ_REQ_RESP_HANDLE_SHIFT;
+
+ if (unlikely(cmd_index > hrr_queue->max_cmd_id ||
+ cmd_index < hrr_queue->min_cmd_id)) {
+ ipr_isr_eh(ioa_cfg,
+ "Invalid response handle from IOA: ",
+ cmd_index);
+ break;
+ }
+
+ ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index];
+ ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
+
+ ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);
+
+ list_move_tail(&ipr_cmd->queue, doneq);
+
+ if (hrr_queue->hrrq_curr < hrr_queue->hrrq_end) {
+ hrr_queue->hrrq_curr++;
+ } else {
+ hrr_queue->hrrq_curr = hrr_queue->hrrq_start;
+ hrr_queue->toggle_bit ^= 1u;
+ }
+ num_hrrq++;
+ if (budget > 0 && num_hrrq >= budget)
+ break;
+ }
+
+ return num_hrrq;
+}
+
+static int ipr_iopoll(struct blk_iopoll *iop, int budget)
+{
+ struct ipr_ioa_cfg *ioa_cfg;
+ struct ipr_hrr_queue *hrrq;
+ struct ipr_cmnd *ipr_cmd, *temp;
+ unsigned long hrrq_flags;
+ int completed_ops;
+ LIST_HEAD(doneq);
+
+ hrrq = container_of(iop, struct ipr_hrr_queue, iopoll);
+ ioa_cfg = hrrq->ioa_cfg;
+
+ spin_lock_irqsave(hrrq->lock, hrrq_flags);
+ completed_ops = ipr_process_hrrq(hrrq, budget, &doneq);
+
+ if (completed_ops < budget)
+ blk_iopoll_complete(iop);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
+
+ list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) {
+ list_del(&ipr_cmd->queue);
+ del_timer(&ipr_cmd->timer);
+ ipr_cmd->fast_done(ipr_cmd);
+ }
+
+ return completed_ops;
+}
+
/**
* ipr_isr - Interrupt service routine
* @irq: irq number
@@ -5142,78 +5401,48 @@ static void ipr_isr_eh(struct ipr_ioa_cfg *ioa_cfg, char *msg)
**/
static irqreturn_t ipr_isr(int irq, void *devp)
{
- struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
- unsigned long lock_flags = 0;
+ struct ipr_hrr_queue *hrrq = (struct ipr_hrr_queue *)devp;
+ struct ipr_ioa_cfg *ioa_cfg = hrrq->ioa_cfg;
+ unsigned long hrrq_flags = 0;
u32 int_reg = 0;
- u32 ioasc;
- u16 cmd_index;
int num_hrrq = 0;
int irq_none = 0;
struct ipr_cmnd *ipr_cmd, *temp;
irqreturn_t rc = IRQ_NONE;
LIST_HEAD(doneq);
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
-
+ spin_lock_irqsave(hrrq->lock, hrrq_flags);
/* If interrupts are disabled, ignore the interrupt */
- if (!ioa_cfg->allow_interrupts) {
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ if (!hrrq->allow_interrupts) {
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
return IRQ_NONE;
}
while (1) {
- ipr_cmd = NULL;
-
- while ((be32_to_cpu(*ioa_cfg->hrrq_curr) & IPR_HRRQ_TOGGLE_BIT) ==
- ioa_cfg->toggle_bit) {
+ if (ipr_process_hrrq(hrrq, -1, &doneq)) {
+ rc = IRQ_HANDLED;
- cmd_index = (be32_to_cpu(*ioa_cfg->hrrq_curr) &
- IPR_HRRQ_REQ_RESP_HANDLE_MASK) >> IPR_HRRQ_REQ_RESP_HANDLE_SHIFT;
-
- if (unlikely(cmd_index >= IPR_NUM_CMD_BLKS)) {
- ipr_isr_eh(ioa_cfg, "Invalid response handle from IOA");
- rc = IRQ_HANDLED;
- goto unlock_out;
- }
-
- ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index];
-
- ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
-
- ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);
-
- list_move_tail(&ipr_cmd->queue, &doneq);
-
- rc = IRQ_HANDLED;
-
- if (ioa_cfg->hrrq_curr < ioa_cfg->hrrq_end) {
- ioa_cfg->hrrq_curr++;
- } else {
- ioa_cfg->hrrq_curr = ioa_cfg->hrrq_start;
- ioa_cfg->toggle_bit ^= 1u;
- }
- }
-
- if (ipr_cmd && !ioa_cfg->clear_isr)
- break;
+ if (!ioa_cfg->clear_isr)
+ break;
- if (ipr_cmd != NULL) {
/* Clear the PCI interrupt */
num_hrrq = 0;
do {
- writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
+ writel(IPR_PCII_HRRQ_UPDATED,
+ ioa_cfg->regs.clr_interrupt_reg32);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
} while (int_reg & IPR_PCII_HRRQ_UPDATED &&
- num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
+ num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
} else if (rc == IRQ_NONE && irq_none == 0) {
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
irq_none++;
} else if (num_hrrq == IPR_MAX_HRRQ_RETRIES &&
int_reg & IPR_PCII_HRRQ_UPDATED) {
- ipr_isr_eh(ioa_cfg, "Error clearing HRRQ");
+ ipr_isr_eh(ioa_cfg,
+ "Error clearing HRRQ: ", num_hrrq);
rc = IRQ_HANDLED;
- goto unlock_out;
+ break;
} else
break;
}
@@ -5221,14 +5450,64 @@ static irqreturn_t ipr_isr(int irq, void *devp)
if (unlikely(rc == IRQ_NONE))
rc = ipr_handle_other_interrupt(ioa_cfg, int_reg);
-unlock_out:
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) {
list_del(&ipr_cmd->queue);
del_timer(&ipr_cmd->timer);
ipr_cmd->fast_done(ipr_cmd);
}
+ return rc;
+}
+
+/**
+ * ipr_isr_mhrrq - Interrupt service routine
+ * @irq: irq number
+ * @devp: pointer to ioa config struct
+ *
+ * Return value:
+ * IRQ_NONE / IRQ_HANDLED
+ **/
+static irqreturn_t ipr_isr_mhrrq(int irq, void *devp)
+{
+ struct ipr_hrr_queue *hrrq = (struct ipr_hrr_queue *)devp;
+ struct ipr_ioa_cfg *ioa_cfg = hrrq->ioa_cfg;
+ unsigned long hrrq_flags = 0;
+ struct ipr_cmnd *ipr_cmd, *temp;
+ irqreturn_t rc = IRQ_NONE;
+ LIST_HEAD(doneq);
+ spin_lock_irqsave(hrrq->lock, hrrq_flags);
+
+ /* If interrupts are disabled, ignore the interrupt */
+ if (!hrrq->allow_interrupts) {
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
+ return IRQ_NONE;
+ }
+
+ if (blk_iopoll_enabled && ioa_cfg->iopoll_weight &&
+ ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
+ if ((be32_to_cpu(*hrrq->hrrq_curr) & IPR_HRRQ_TOGGLE_BIT) ==
+ hrrq->toggle_bit) {
+ if (!blk_iopoll_sched_prep(&hrrq->iopoll))
+ blk_iopoll_sched(&hrrq->iopoll);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
+ return IRQ_HANDLED;
+ }
+ } else {
+ if ((be32_to_cpu(*hrrq->hrrq_curr) & IPR_HRRQ_TOGGLE_BIT) ==
+ hrrq->toggle_bit)
+
+ if (ipr_process_hrrq(hrrq, -1, &doneq))
+ rc = IRQ_HANDLED;
+ }
+
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
+
+ list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) {
+ list_del(&ipr_cmd->queue);
+ del_timer(&ipr_cmd->timer);
+ ipr_cmd->fast_done(ipr_cmd);
+ }
return rc;
}
@@ -5388,7 +5667,6 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
{
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
- struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
@@ -5406,7 +5684,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
res->in_erp = 0;
}
scsi_dma_unmap(ipr_cmd->scsi_cmd);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
scsi_cmd->scsi_done(scsi_cmd);
}
@@ -5790,7 +6068,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
}
scsi_dma_unmap(ipr_cmd->scsi_cmd);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
scsi_cmd->scsi_done(scsi_cmd);
}
@@ -5809,21 +6087,21 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
- unsigned long lock_flags;
+ unsigned long hrrq_flags;
scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len));
if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
scsi_dma_unmap(scsi_cmd);
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
scsi_cmd->scsi_done(scsi_cmd);
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags);
} else {
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags);
ipr_erp_start(ioa_cfg, ipr_cmd);
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags);
}
}
@@ -5846,22 +6124,34 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
struct ipr_resource_entry *res;
struct ipr_ioarcb *ioarcb;
struct ipr_cmnd *ipr_cmd;
- unsigned long lock_flags;
+ unsigned long hrrq_flags, lock_flags;
int rc;
+ struct ipr_hrr_queue *hrrq;
+ int hrrq_id;
ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
- spin_lock_irqsave(shost->host_lock, lock_flags);
scsi_cmd->result = (DID_OK << 16);
res = scsi_cmd->device->hostdata;
+ if (ipr_is_gata(res) && res->sata_port) {
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ rc = ata_sas_queuecmd(scsi_cmd, res->sata_port->ap);
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return rc;
+ }
+
+ hrrq_id = ipr_get_hrrq_index(ioa_cfg);
+ hrrq = &ioa_cfg->hrrq[hrrq_id];
+
+ spin_lock_irqsave(hrrq->lock, hrrq_flags);
/*
* We are currently blocking all devices due to a host reset
* We have told the host to stop giving us new requests, but
* ERP ops don't count. FIXME
*/
- if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead)) {
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ if (unlikely(!hrrq->allow_cmds && !hrrq->ioa_is_dead && !hrrq->removing_ioa)) {
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
return SCSI_MLQUEUE_HOST_BUSY;
}
@@ -5869,19 +6159,17 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
* FIXME - Create scsi_set_host_offline interface
* and the ioa_is_dead check can be removed
*/
- if (unlikely(ioa_cfg->ioa_is_dead || !res)) {
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ if (unlikely(hrrq->ioa_is_dead || hrrq->removing_ioa || !res)) {
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
goto err_nodev;
}
- if (ipr_is_gata(res) && res->sata_port) {
- rc = ata_sas_queuecmd(scsi_cmd, res->sata_port->ap);
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
- return rc;
+ ipr_cmd = __ipr_get_free_ipr_cmnd(hrrq);
+ if (ipr_cmd == NULL) {
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
+ return SCSI_MLQUEUE_HOST_BUSY;
}
-
- ipr_cmd = __ipr_get_free_ipr_cmnd(ioa_cfg);
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
ipr_init_ipr_cmnd(ipr_cmd, ipr_scsi_done);
ioarcb = &ipr_cmd->ioarcb;
@@ -5902,26 +6190,27 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
}
if (scsi_cmd->cmnd[0] >= 0xC0 &&
- (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE))
+ (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) {
ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
+ }
if (ioa_cfg->sis64)
rc = ipr_build_ioadl64(ioa_cfg, ipr_cmd);
else
rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
- spin_lock_irqsave(shost->host_lock, lock_flags);
- if (unlikely(rc || (!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))) {
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ spin_lock_irqsave(hrrq->lock, hrrq_flags);
+ if (unlikely(rc || (!hrrq->allow_cmds && !hrrq->ioa_is_dead))) {
+ list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
if (!rc)
scsi_dma_unmap(scsi_cmd);
return SCSI_MLQUEUE_HOST_BUSY;
}
- if (unlikely(ioa_cfg->ioa_is_dead)) {
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ if (unlikely(hrrq->ioa_is_dead)) {
+ list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
scsi_dma_unmap(scsi_cmd);
goto err_nodev;
}
@@ -5931,18 +6220,18 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_SYNC_COMPLETE;
res->needs_sync_complete = 0;
}
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+ list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_pending_q);
ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_GET_RES_PHYS_LOC(res));
ipr_send_command(ipr_cmd);
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
return 0;
err_nodev:
- spin_lock_irqsave(shost->host_lock, lock_flags);
+ spin_lock_irqsave(hrrq->lock, hrrq_flags);
memset(scsi_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
scsi_cmd->result = (DID_NO_CONNECT << 16);
scsi_cmd->scsi_done(scsi_cmd);
- spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
return 0;
}
@@ -6040,7 +6329,7 @@ static void ipr_ata_phy_reset(struct ata_port *ap)
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
}
- if (!ioa_cfg->allow_cmds)
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds)
goto out_unlock;
rc = ipr_device_reset(ioa_cfg, res);
@@ -6071,6 +6360,7 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc)
struct ipr_sata_port *sata_port = qc->ap->private_data;
struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
struct ipr_cmnd *ipr_cmd;
+ struct ipr_hrr_queue *hrrq;
unsigned long flags;
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
@@ -6080,11 +6370,15 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc)
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
}
- list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
- if (ipr_cmd->qc == qc) {
- ipr_device_reset(ioa_cfg, sata_port->res);
- break;
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock(&hrrq->_lock);
+ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
+ if (ipr_cmd->qc == qc) {
+ ipr_device_reset(ioa_cfg, sata_port->res);
+ break;
+ }
}
+ spin_unlock(&hrrq->_lock);
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
}
@@ -6133,6 +6427,7 @@ static void ipr_sata_done(struct ipr_cmnd *ipr_cmd)
struct ipr_resource_entry *res = sata_port->res;
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
+ spin_lock(&ipr_cmd->hrrq->_lock);
if (ipr_cmd->ioa_cfg->sis64)
memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata,
sizeof(struct ipr_ioasa_gata));
@@ -6148,7 +6443,8 @@ static void ipr_sata_done(struct ipr_cmnd *ipr_cmd)
qc->err_mask |= __ac_err_mask(sata_port->ioasa.status);
else
qc->err_mask |= ac_err_mask(sata_port->ioasa.status);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
+ spin_unlock(&ipr_cmd->hrrq->_lock);
ata_qc_complete(qc);
}
@@ -6163,7 +6459,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd,
{
u32 ioadl_flags = 0;
struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
- struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ioadl64;
+ struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ata_ioadl.ioadl64;
struct ipr_ioadl64_desc *last_ioadl64 = NULL;
int len = qc->nbytes;
struct scatterlist *sg;
@@ -6183,7 +6479,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd,
ioarcb->ioadl_len =
cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg);
ioarcb->u.sis64_addr_data.data_ioadl_addr =
- cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl));
+ cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl.ioadl64));
for_each_sg(qc->sg, sg, qc->n_elem, si) {
ioadl64->flags = cpu_to_be32(ioadl_flags);
@@ -6244,6 +6540,48 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd,
}
/**
+ * ipr_qc_defer - Get a free ipr_cmd
+ * @qc: queued command
+ *
+ * Return value:
+ * 0 if success
+ **/
+static int ipr_qc_defer(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ipr_sata_port *sata_port = ap->private_data;
+ struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
+ struct ipr_cmnd *ipr_cmd;
+ struct ipr_hrr_queue *hrrq;
+ int hrrq_id;
+
+ hrrq_id = ipr_get_hrrq_index(ioa_cfg);
+ hrrq = &ioa_cfg->hrrq[hrrq_id];
+
+ qc->lldd_task = NULL;
+ spin_lock(&hrrq->_lock);
+ if (unlikely(hrrq->ioa_is_dead)) {
+ spin_unlock(&hrrq->_lock);
+ return 0;
+ }
+
+ if (unlikely(!hrrq->allow_cmds)) {
+ spin_unlock(&hrrq->_lock);
+ return ATA_DEFER_LINK;
+ }
+
+ ipr_cmd = __ipr_get_free_ipr_cmnd(hrrq);
+ if (ipr_cmd == NULL) {
+ spin_unlock(&hrrq->_lock);
+ return ATA_DEFER_LINK;
+ }
+
+ qc->lldd_task = ipr_cmd;
+ spin_unlock(&hrrq->_lock);
+ return 0;
+}
+
+/**
* ipr_qc_issue - Issue a SATA qc to a device
* @qc: queued command
*
@@ -6260,10 +6598,23 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
struct ipr_ioarcb *ioarcb;
struct ipr_ioarcb_ata_regs *regs;
- if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead))
+ if (qc->lldd_task == NULL)
+ ipr_qc_defer(qc);
+
+ ipr_cmd = qc->lldd_task;
+ if (ipr_cmd == NULL)
return AC_ERR_SYSTEM;
- ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
+ qc->lldd_task = NULL;
+ spin_lock(&ipr_cmd->hrrq->_lock);
+ if (unlikely(!ipr_cmd->hrrq->allow_cmds ||
+ ipr_cmd->hrrq->ioa_is_dead)) {
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
+ spin_unlock(&ipr_cmd->hrrq->_lock);
+ return AC_ERR_SYSTEM;
+ }
+
+ ipr_init_ipr_cmnd(ipr_cmd, ipr_lock_and_done);
ioarcb = &ipr_cmd->ioarcb;
if (ioa_cfg->sis64) {
@@ -6275,7 +6626,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
memset(regs, 0, sizeof(*regs));
ioarcb->add_cmd_parms_len = cpu_to_be16(sizeof(*regs));
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
ipr_cmd->qc = qc;
ipr_cmd->done = ipr_sata_done;
ipr_cmd->ioarcb.res_handle = res->res_handle;
@@ -6315,10 +6666,12 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
default:
WARN_ON(1);
+ spin_unlock(&ipr_cmd->hrrq->_lock);
return AC_ERR_INVALID;
}
ipr_send_command(ipr_cmd);
+ spin_unlock(&ipr_cmd->hrrq->_lock);
return 0;
}
@@ -6347,7 +6700,6 @@ static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc)
tf->hob_lbal = g->hob_lbal;
tf->hob_lbam = g->hob_lbam;
tf->hob_lbah = g->hob_lbah;
- tf->ctl = g->alt_status;
return true;
}
@@ -6357,6 +6709,7 @@ static struct ata_port_operations ipr_sata_ops = {
.hardreset = ipr_sata_reset,
.post_internal_cmd = ipr_ata_post_internal,
.qc_prep = ata_noop_qc_prep,
+ .qc_defer = ipr_qc_defer,
.qc_issue = ipr_qc_issue,
.qc_fill_rtf = ipr_qc_fill_rtf,
.port_start = ata_sas_port_start,
@@ -6423,16 +6776,27 @@ static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd)
{
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ int i;
ENTER;
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) {
+ ipr_trace;
+ spin_unlock_irq(ioa_cfg->host->host_lock);
+ scsi_unblock_requests(ioa_cfg->host);
+ spin_lock_irq(ioa_cfg->host->host_lock);
+ }
+
ioa_cfg->in_reset_reload = 0;
ioa_cfg->reset_retries = 0;
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
- wake_up_all(&ioa_cfg->reset_wait_q);
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].ioa_is_dead = 1;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
- spin_unlock_irq(ioa_cfg->host->host_lock);
- scsi_unblock_requests(ioa_cfg->host);
- spin_lock_irq(ioa_cfg->host->host_lock);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
+ wake_up_all(&ioa_cfg->reset_wait_q);
LEAVE;
return IPR_RC_JOB_RETURN;
@@ -6454,11 +6818,16 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct ipr_resource_entry *res;
struct ipr_hostrcb *hostrcb, *temp;
- int i = 0;
+ int i = 0, j;
ENTER;
ioa_cfg->in_reset_reload = 0;
- ioa_cfg->allow_cmds = 1;
+ for (j = 0; j < ioa_cfg->hrrq_num; j++) {
+ spin_lock(&ioa_cfg->hrrq[j]._lock);
+ ioa_cfg->hrrq[j].allow_cmds = 1;
+ spin_unlock(&ioa_cfg->hrrq[j]._lock);
+ }
+ wmb();
ioa_cfg->reset_cmd = NULL;
ioa_cfg->doorbell |= IPR_RUNTIME_RESET;
@@ -6482,14 +6851,14 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
dev_info(&ioa_cfg->pdev->dev, "IOA initialized.\n");
ioa_cfg->reset_retries = 0;
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
wake_up_all(&ioa_cfg->reset_wait_q);
spin_unlock(ioa_cfg->host->host_lock);
scsi_unblock_requests(ioa_cfg->host);
spin_lock(ioa_cfg->host->host_lock);
- if (!ioa_cfg->allow_cmds)
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds)
scsi_block_requests(ioa_cfg->host);
LEAVE;
@@ -6560,9 +6929,11 @@ static int ipr_set_supported_devs(struct ipr_cmnd *ipr_cmd)
if (!ioa_cfg->sis64)
ipr_cmd->job_step = ipr_set_supported_devs;
+ LEAVE;
return IPR_RC_JOB_RETURN;
}
+ LEAVE;
return IPR_RC_JOB_CONTINUE;
}
@@ -6820,7 +7191,7 @@ static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd)
ipr_cmd->ioarcb.cmd_pkt.cdb[0], ioasc);
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
return IPR_RC_JOB_RETURN;
}
@@ -7278,46 +7649,71 @@ static int ipr_ioafp_identify_hrrq(struct ipr_cmnd *ipr_cmd)
{
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+ struct ipr_hrr_queue *hrrq;
ENTER;
+ ipr_cmd->job_step = ipr_ioafp_std_inquiry;
dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n");
- ioarcb->cmd_pkt.cdb[0] = IPR_ID_HOST_RR_Q;
- ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);
+ if (ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num) {
+ hrrq = &ioa_cfg->hrrq[ioa_cfg->identify_hrrq_index];
- ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
- if (ioa_cfg->sis64)
- ioarcb->cmd_pkt.cdb[1] = 0x1;
- ioarcb->cmd_pkt.cdb[2] =
- ((u64) ioa_cfg->host_rrq_dma >> 24) & 0xff;
- ioarcb->cmd_pkt.cdb[3] =
- ((u64) ioa_cfg->host_rrq_dma >> 16) & 0xff;
- ioarcb->cmd_pkt.cdb[4] =
- ((u64) ioa_cfg->host_rrq_dma >> 8) & 0xff;
- ioarcb->cmd_pkt.cdb[5] =
- ((u64) ioa_cfg->host_rrq_dma) & 0xff;
- ioarcb->cmd_pkt.cdb[7] =
- ((sizeof(u32) * IPR_NUM_CMD_BLKS) >> 8) & 0xff;
- ioarcb->cmd_pkt.cdb[8] =
- (sizeof(u32) * IPR_NUM_CMD_BLKS) & 0xff;
+ ioarcb->cmd_pkt.cdb[0] = IPR_ID_HOST_RR_Q;
+ ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);
- if (ioa_cfg->sis64) {
- ioarcb->cmd_pkt.cdb[10] =
- ((u64) ioa_cfg->host_rrq_dma >> 56) & 0xff;
- ioarcb->cmd_pkt.cdb[11] =
- ((u64) ioa_cfg->host_rrq_dma >> 48) & 0xff;
- ioarcb->cmd_pkt.cdb[12] =
- ((u64) ioa_cfg->host_rrq_dma >> 40) & 0xff;
- ioarcb->cmd_pkt.cdb[13] =
- ((u64) ioa_cfg->host_rrq_dma >> 32) & 0xff;
- }
+ ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
+ if (ioa_cfg->sis64)
+ ioarcb->cmd_pkt.cdb[1] = 0x1;
- ipr_cmd->job_step = ipr_ioafp_std_inquiry;
+ if (ioa_cfg->nvectors == 1)
+ ioarcb->cmd_pkt.cdb[1] &= ~IPR_ID_HRRQ_SELE_ENABLE;
+ else
+ ioarcb->cmd_pkt.cdb[1] |= IPR_ID_HRRQ_SELE_ENABLE;
+
+ ioarcb->cmd_pkt.cdb[2] =
+ ((u64) hrrq->host_rrq_dma >> 24) & 0xff;
+ ioarcb->cmd_pkt.cdb[3] =
+ ((u64) hrrq->host_rrq_dma >> 16) & 0xff;
+ ioarcb->cmd_pkt.cdb[4] =
+ ((u64) hrrq->host_rrq_dma >> 8) & 0xff;
+ ioarcb->cmd_pkt.cdb[5] =
+ ((u64) hrrq->host_rrq_dma) & 0xff;
+ ioarcb->cmd_pkt.cdb[7] =
+ ((sizeof(u32) * hrrq->size) >> 8) & 0xff;
+ ioarcb->cmd_pkt.cdb[8] =
+ (sizeof(u32) * hrrq->size) & 0xff;
+
+ if (ioarcb->cmd_pkt.cdb[1] & IPR_ID_HRRQ_SELE_ENABLE)
+ ioarcb->cmd_pkt.cdb[9] =
+ ioa_cfg->identify_hrrq_index;
- ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT);
+ if (ioa_cfg->sis64) {
+ ioarcb->cmd_pkt.cdb[10] =
+ ((u64) hrrq->host_rrq_dma >> 56) & 0xff;
+ ioarcb->cmd_pkt.cdb[11] =
+ ((u64) hrrq->host_rrq_dma >> 48) & 0xff;
+ ioarcb->cmd_pkt.cdb[12] =
+ ((u64) hrrq->host_rrq_dma >> 40) & 0xff;
+ ioarcb->cmd_pkt.cdb[13] =
+ ((u64) hrrq->host_rrq_dma >> 32) & 0xff;
+ }
+
+ if (ioarcb->cmd_pkt.cdb[1] & IPR_ID_HRRQ_SELE_ENABLE)
+ ioarcb->cmd_pkt.cdb[14] =
+ ioa_cfg->identify_hrrq_index;
+
+ ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout,
+ IPR_INTERNAL_TIMEOUT);
+
+ if (++ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num)
+ ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
+
+ LEAVE;
+ return IPR_RC_JOB_RETURN;
+ }
LEAVE;
- return IPR_RC_JOB_RETURN;
+ return IPR_RC_JOB_CONTINUE;
}
/**
@@ -7365,7 +7761,9 @@ static void ipr_reset_timer_done(struct ipr_cmnd *ipr_cmd)
static void ipr_reset_start_timer(struct ipr_cmnd *ipr_cmd,
unsigned long timeout)
{
- list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q);
+
+ ENTER;
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
ipr_cmd->done = ipr_reset_ioa_job;
ipr_cmd->timer.data = (unsigned long) ipr_cmd;
@@ -7383,13 +7781,26 @@ static void ipr_reset_start_timer(struct ipr_cmnd *ipr_cmd,
**/
static void ipr_init_ioa_mem(struct ipr_ioa_cfg *ioa_cfg)
{
- memset(ioa_cfg->host_rrq, 0, sizeof(u32) * IPR_NUM_CMD_BLKS);
+ struct ipr_hrr_queue *hrrq;
- /* Initialize Host RRQ pointers */
- ioa_cfg->hrrq_start = ioa_cfg->host_rrq;
- ioa_cfg->hrrq_end = &ioa_cfg->host_rrq[IPR_NUM_CMD_BLKS - 1];
- ioa_cfg->hrrq_curr = ioa_cfg->hrrq_start;
- ioa_cfg->toggle_bit = 1;
+ for_each_hrrq(hrrq, ioa_cfg) {
+ spin_lock(&hrrq->_lock);
+ memset(hrrq->host_rrq, 0, sizeof(u32) * hrrq->size);
+
+ /* Initialize Host RRQ pointers */
+ hrrq->hrrq_start = hrrq->host_rrq;
+ hrrq->hrrq_end = &hrrq->host_rrq[hrrq->size - 1];
+ hrrq->hrrq_curr = hrrq->hrrq_start;
+ hrrq->toggle_bit = 1;
+ spin_unlock(&hrrq->_lock);
+ }
+ wmb();
+
+ ioa_cfg->identify_hrrq_index = 0;
+ if (ioa_cfg->hrrq_num == 1)
+ atomic_set(&ioa_cfg->hrrq_index, 0);
+ else
+ atomic_set(&ioa_cfg->hrrq_index, 1);
/* Zero out config table */
memset(ioa_cfg->u.cfg_table, 0, ioa_cfg->cfg_table_size);
@@ -7446,7 +7857,8 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd)
ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
ipr_cmd->done = ipr_reset_ioa_job;
add_timer(&ipr_cmd->timer);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
return IPR_RC_JOB_RETURN;
}
@@ -7466,12 +7878,18 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
volatile u32 int_reg;
volatile u64 maskval;
+ int i;
ENTER;
ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
ipr_init_ioa_mem(ioa_cfg);
- ioa_cfg->allow_interrupts = 1;
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].allow_interrupts = 1;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
if (ioa_cfg->sis64) {
/* Set the adapter to the correct endian mode. */
writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg);
@@ -7511,7 +7929,7 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
ipr_cmd->done = ipr_reset_ioa_job;
add_timer(&ipr_cmd->timer);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
LEAVE;
return IPR_RC_JOB_RETURN;
@@ -8030,7 +8448,8 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd)
int rc = IPR_RC_JOB_CONTINUE;
ENTER;
- if (shutdown_type != IPR_SHUTDOWN_NONE && !ioa_cfg->ioa_is_dead) {
+ if (shutdown_type != IPR_SHUTDOWN_NONE &&
+ !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) {
ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);
ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
ipr_cmd->ioarcb.cmd_pkt.cdb[0] = IPR_IOA_SHUTDOWN;
@@ -8078,7 +8497,8 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd)
* We are doing nested adapter resets and this is
* not the current reset job.
*/
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue,
+ &ipr_cmd->hrrq->hrrq_free_q);
return;
}
@@ -8113,10 +8533,17 @@ static void _ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
enum ipr_shutdown_type shutdown_type)
{
struct ipr_cmnd *ipr_cmd;
+ int i;
ioa_cfg->in_reset_reload = 1;
- ioa_cfg->allow_cmds = 0;
- scsi_block_requests(ioa_cfg->host);
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].allow_cmds = 0;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa)
+ scsi_block_requests(ioa_cfg->host);
ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
ioa_cfg->reset_cmd = ipr_cmd;
@@ -8141,7 +8568,9 @@ static void _ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
enum ipr_shutdown_type shutdown_type)
{
- if (ioa_cfg->ioa_is_dead)
+ int i;
+
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead)
return;
if (ioa_cfg->in_reset_reload) {
@@ -8156,7 +8585,12 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
"IOA taken offline - error recovery failed\n");
ioa_cfg->reset_retries = 0;
- ioa_cfg->ioa_is_dead = 1;
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].ioa_is_dead = 1;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
if (ioa_cfg->in_ioa_bringdown) {
ioa_cfg->reset_cmd = NULL;
@@ -8164,9 +8598,11 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
ipr_fail_all_ops(ioa_cfg);
wake_up_all(&ioa_cfg->reset_wait_q);
- spin_unlock_irq(ioa_cfg->host->host_lock);
- scsi_unblock_requests(ioa_cfg->host);
- spin_lock_irq(ioa_cfg->host->host_lock);
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) {
+ spin_unlock_irq(ioa_cfg->host->host_lock);
+ scsi_unblock_requests(ioa_cfg->host);
+ spin_lock_irq(ioa_cfg->host->host_lock);
+ }
return;
} else {
ioa_cfg->in_ioa_bringdown = 1;
@@ -8188,9 +8624,17 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
*/
static int ipr_reset_freeze(struct ipr_cmnd *ipr_cmd)
{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ int i;
+
/* Disallow new interrupts, avoid loop */
- ipr_cmd->ioa_cfg->allow_interrupts = 0;
- list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q);
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].allow_interrupts = 0;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
ipr_cmd->done = ipr_reset_ioa_job;
return IPR_RC_JOB_RETURN;
}
@@ -8247,13 +8691,19 @@ static void ipr_pci_perm_failure(struct pci_dev *pdev)
{
unsigned long flags = 0;
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
+ int i;
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
if (ioa_cfg->sdt_state == WAIT_FOR_DUMP)
ioa_cfg->sdt_state = ABORT_DUMP;
- ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES;
+ ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES - 1;
ioa_cfg->in_ioa_bringdown = 1;
- ioa_cfg->allow_cmds = 0;
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].allow_cmds = 0;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
}
@@ -8296,7 +8746,7 @@ static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev,
* Return value:
* 0 on success / -EIO on failure
**/
-static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
+static int ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
{
int rc = 0;
unsigned long host_lock_flags = 0;
@@ -8310,12 +8760,11 @@ static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
} else
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa,
IPR_SHUTDOWN_NONE);
-
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
- if (ioa_cfg->ioa_is_dead) {
+ if (ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) {
rc = -EIO;
} else if (ipr_invalid_adapter(ioa_cfg)) {
if (!ipr_testmode)
@@ -8376,8 +8825,13 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
pci_free_consistent(ioa_cfg->pdev, sizeof(struct ipr_misc_cbs),
ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
ipr_free_cmd_blks(ioa_cfg);
- pci_free_consistent(ioa_cfg->pdev, sizeof(u32) * IPR_NUM_CMD_BLKS,
- ioa_cfg->host_rrq, ioa_cfg->host_rrq_dma);
+
+ for (i = 0; i < ioa_cfg->hrrq_num; i++)
+ pci_free_consistent(ioa_cfg->pdev,
+ sizeof(u32) * ioa_cfg->hrrq[i].size,
+ ioa_cfg->hrrq[i].host_rrq,
+ ioa_cfg->hrrq[i].host_rrq_dma);
+
pci_free_consistent(ioa_cfg->pdev, ioa_cfg->cfg_table_size,
ioa_cfg->u.cfg_table,
ioa_cfg->cfg_table_dma);
@@ -8408,8 +8862,23 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
struct pci_dev *pdev = ioa_cfg->pdev;
ENTER;
- free_irq(pdev->irq, ioa_cfg);
- pci_disable_msi(pdev);
+ if (ioa_cfg->intr_flag == IPR_USE_MSI ||
+ ioa_cfg->intr_flag == IPR_USE_MSIX) {
+ int i;
+ for (i = 0; i < ioa_cfg->nvectors; i++)
+ free_irq(ioa_cfg->vectors_info[i].vec,
+ &ioa_cfg->hrrq[i]);
+ } else
+ free_irq(pdev->irq, &ioa_cfg->hrrq[0]);
+
+ if (ioa_cfg->intr_flag == IPR_USE_MSI) {
+ pci_disable_msi(pdev);
+ ioa_cfg->intr_flag &= ~IPR_USE_MSI;
+ } else if (ioa_cfg->intr_flag == IPR_USE_MSIX) {
+ pci_disable_msix(pdev);
+ ioa_cfg->intr_flag &= ~IPR_USE_MSIX;
+ }
+
iounmap(ioa_cfg->hdw_dma_regs);
pci_release_regions(pdev);
ipr_free_mem(ioa_cfg);
@@ -8425,12 +8894,12 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
* Return value:
* 0 on success / -ENOMEM on allocation failure
**/
-static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
+static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
{
struct ipr_cmnd *ipr_cmd;
struct ipr_ioarcb *ioarcb;
dma_addr_t dma_addr;
- int i;
+ int i, entries_each_hrrq, hrrq_id = 0;
ioa_cfg->ipr_cmd_pool = pci_pool_create(IPR_NAME, ioa_cfg->pdev,
sizeof(struct ipr_cmnd), 512, 0);
@@ -8446,6 +8915,41 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
return -ENOMEM;
}
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ if (ioa_cfg->hrrq_num > 1) {
+ if (i == 0) {
+ entries_each_hrrq = IPR_NUM_INTERNAL_CMD_BLKS;
+ ioa_cfg->hrrq[i].min_cmd_id = 0;
+ ioa_cfg->hrrq[i].max_cmd_id =
+ (entries_each_hrrq - 1);
+ } else {
+ entries_each_hrrq =
+ IPR_NUM_BASE_CMD_BLKS/
+ (ioa_cfg->hrrq_num - 1);
+ ioa_cfg->hrrq[i].min_cmd_id =
+ IPR_NUM_INTERNAL_CMD_BLKS +
+ (i - 1) * entries_each_hrrq;
+ ioa_cfg->hrrq[i].max_cmd_id =
+ (IPR_NUM_INTERNAL_CMD_BLKS +
+ i * entries_each_hrrq - 1);
+ }
+ } else {
+ entries_each_hrrq = IPR_NUM_CMD_BLKS;
+ ioa_cfg->hrrq[i].min_cmd_id = 0;
+ ioa_cfg->hrrq[i].max_cmd_id = (entries_each_hrrq - 1);
+ }
+ ioa_cfg->hrrq[i].size = entries_each_hrrq;
+ }
+
+ BUG_ON(ioa_cfg->hrrq_num == 0);
+
+ i = IPR_NUM_CMD_BLKS -
+ ioa_cfg->hrrq[ioa_cfg->hrrq_num - 1].max_cmd_id - 1;
+ if (i > 0) {
+ ioa_cfg->hrrq[ioa_cfg->hrrq_num - 1].size += i;
+ ioa_cfg->hrrq[ioa_cfg->hrrq_num - 1].max_cmd_id += i;
+ }
+
for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
ipr_cmd = pci_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
@@ -8484,7 +8988,11 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
ipr_cmd->sense_buffer_dma = dma_addr +
offsetof(struct ipr_cmnd, sense_buffer);
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ ipr_cmd->ioarcb.cmd_pkt.hrrq_id = hrrq_id;
+ ipr_cmd->hrrq = &ioa_cfg->hrrq[hrrq_id];
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
+ if (i >= ioa_cfg->hrrq[hrrq_id].max_cmd_id)
+ hrrq_id++;
}
return 0;
@@ -8497,7 +9005,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
* Return value:
* 0 on success / non-zero for error
**/
-static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
+static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
{
struct pci_dev *pdev = ioa_cfg->pdev;
int i, rc = -ENOMEM;
@@ -8509,15 +9017,6 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
if (!ioa_cfg->res_entries)
goto out;
- if (ioa_cfg->sis64) {
- ioa_cfg->target_ids = kzalloc(sizeof(unsigned long) *
- BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL);
- ioa_cfg->array_ids = kzalloc(sizeof(unsigned long) *
- BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL);
- ioa_cfg->vset_ids = kzalloc(sizeof(unsigned long) *
- BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL);
- }
-
for (i = 0; i < ioa_cfg->max_devs_supported; i++) {
list_add_tail(&ioa_cfg->res_entries[i].queue, &ioa_cfg->free_res_q);
ioa_cfg->res_entries[i].ioa_cfg = ioa_cfg;
@@ -8530,15 +9029,34 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
if (!ioa_cfg->vpd_cbs)
goto out_free_res_entries;
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ INIT_LIST_HEAD(&ioa_cfg->hrrq[i].hrrq_free_q);
+ INIT_LIST_HEAD(&ioa_cfg->hrrq[i].hrrq_pending_q);
+ spin_lock_init(&ioa_cfg->hrrq[i]._lock);
+ if (i == 0)
+ ioa_cfg->hrrq[i].lock = ioa_cfg->host->host_lock;
+ else
+ ioa_cfg->hrrq[i].lock = &ioa_cfg->hrrq[i]._lock;
+ }
+
if (ipr_alloc_cmd_blks(ioa_cfg))
goto out_free_vpd_cbs;
- ioa_cfg->host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
- sizeof(u32) * IPR_NUM_CMD_BLKS,
- &ioa_cfg->host_rrq_dma);
-
- if (!ioa_cfg->host_rrq)
- goto out_ipr_free_cmd_blocks;
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ ioa_cfg->hrrq[i].host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
+ sizeof(u32) * ioa_cfg->hrrq[i].size,
+ &ioa_cfg->hrrq[i].host_rrq_dma);
+
+ if (!ioa_cfg->hrrq[i].host_rrq) {
+ while (--i > 0)
+ pci_free_consistent(pdev,
+ sizeof(u32) * ioa_cfg->hrrq[i].size,
+ ioa_cfg->hrrq[i].host_rrq,
+ ioa_cfg->hrrq[i].host_rrq_dma);
+ goto out_ipr_free_cmd_blocks;
+ }
+ ioa_cfg->hrrq[i].ioa_cfg = ioa_cfg;
+ }
ioa_cfg->u.cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
ioa_cfg->cfg_table_size,
@@ -8582,8 +9100,12 @@ out_free_hostrcb_dma:
ioa_cfg->u.cfg_table,
ioa_cfg->cfg_table_dma);
out_free_host_rrq:
- pci_free_consistent(pdev, sizeof(u32) * IPR_NUM_CMD_BLKS,
- ioa_cfg->host_rrq, ioa_cfg->host_rrq_dma);
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ pci_free_consistent(pdev,
+ sizeof(u32) * ioa_cfg->hrrq[i].size,
+ ioa_cfg->hrrq[i].host_rrq,
+ ioa_cfg->hrrq[i].host_rrq_dma);
+ }
out_ipr_free_cmd_blocks:
ipr_free_cmd_blks(ioa_cfg);
out_free_vpd_cbs:
@@ -8601,7 +9123,7 @@ out_free_res_entries:
* Return value:
* none
**/
-static void __devinit ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg)
+static void ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg)
{
int i;
@@ -8625,8 +9147,8 @@ static void __devinit ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg)
* Return value:
* none
**/
-static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
- struct Scsi_Host *host, struct pci_dev *pdev)
+static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
+ struct Scsi_Host *host, struct pci_dev *pdev)
{
const struct ipr_interrupt_offsets *p;
struct ipr_interrupts *t;
@@ -8638,15 +9160,11 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
ioa_cfg->doorbell = IPR_DOORBELL;
sprintf(ioa_cfg->eye_catcher, IPR_EYECATCHER);
sprintf(ioa_cfg->trace_start, IPR_TRACE_START_LABEL);
- sprintf(ioa_cfg->ipr_free_label, IPR_FREEQ_LABEL);
- sprintf(ioa_cfg->ipr_pending_label, IPR_PENDQ_LABEL);
sprintf(ioa_cfg->cfg_table_start, IPR_CFG_TBL_START);
sprintf(ioa_cfg->resource_table_label, IPR_RES_TABLE_LABEL);
sprintf(ioa_cfg->ipr_hcam_label, IPR_HCAM_LABEL);
sprintf(ioa_cfg->ipr_cmd_label, IPR_CMD_LABEL);
- INIT_LIST_HEAD(&ioa_cfg->free_q);
- INIT_LIST_HEAD(&ioa_cfg->pending_q);
INIT_LIST_HEAD(&ioa_cfg->hostrcb_free_q);
INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q);
INIT_LIST_HEAD(&ioa_cfg->free_res_q);
@@ -8712,7 +9230,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
* Return value:
* ptr to chip information on success / NULL on failure
**/
-static const struct ipr_chip_t * __devinit
+static const struct ipr_chip_t *
ipr_get_chip_info(const struct pci_device_id *dev_id)
{
int i;
@@ -8724,6 +9242,88 @@ ipr_get_chip_info(const struct pci_device_id *dev_id)
return NULL;
}
+static int ipr_enable_msix(struct ipr_ioa_cfg *ioa_cfg)
+{
+ struct msix_entry entries[IPR_MAX_MSIX_VECTORS];
+ int i, err, vectors;
+
+ for (i = 0; i < ARRAY_SIZE(entries); ++i)
+ entries[i].entry = i;
+
+ vectors = ipr_number_of_msix;
+
+ while ((err = pci_enable_msix(ioa_cfg->pdev, entries, vectors)) > 0)
+ vectors = err;
+
+ if (err < 0) {
+ pci_disable_msix(ioa_cfg->pdev);
+ return err;
+ }
+
+ if (!err) {
+ for (i = 0; i < vectors; i++)
+ ioa_cfg->vectors_info[i].vec = entries[i].vector;
+ ioa_cfg->nvectors = vectors;
+ }
+
+ return err;
+}
+
+static int ipr_enable_msi(struct ipr_ioa_cfg *ioa_cfg)
+{
+ int i, err, vectors;
+
+ vectors = ipr_number_of_msix;
+
+ while ((err = pci_enable_msi_block(ioa_cfg->pdev, vectors)) > 0)
+ vectors = err;
+
+ if (err < 0) {
+ pci_disable_msi(ioa_cfg->pdev);
+ return err;
+ }
+
+ if (!err) {
+ for (i = 0; i < vectors; i++)
+ ioa_cfg->vectors_info[i].vec = ioa_cfg->pdev->irq + i;
+ ioa_cfg->nvectors = vectors;
+ }
+
+ return err;
+}
+
+static void name_msi_vectors(struct ipr_ioa_cfg *ioa_cfg)
+{
+ int vec_idx, n = sizeof(ioa_cfg->vectors_info[0].desc) - 1;
+
+ for (vec_idx = 0; vec_idx < ioa_cfg->nvectors; vec_idx++) {
+ snprintf(ioa_cfg->vectors_info[vec_idx].desc, n,
+ "host%d-%d", ioa_cfg->host->host_no, vec_idx);
+ ioa_cfg->vectors_info[vec_idx].
+ desc[strlen(ioa_cfg->vectors_info[vec_idx].desc)] = 0;
+ }
+}
+
+static int ipr_request_other_msi_irqs(struct ipr_ioa_cfg *ioa_cfg)
+{
+ int i, rc;
+
+ for (i = 1; i < ioa_cfg->nvectors; i++) {
+ rc = request_irq(ioa_cfg->vectors_info[i].vec,
+ ipr_isr_mhrrq,
+ 0,
+ ioa_cfg->vectors_info[i].desc,
+ &ioa_cfg->hrrq[i]);
+ if (rc) {
+ while (--i >= 0)
+ free_irq(ioa_cfg->vectors_info[i].vec,
+ &ioa_cfg->hrrq[i]);
+ return rc;
+ }
+ }
+ return 0;
+}
+
/**
* ipr_test_intr - Handle the interrupt generated in ipr_test_msi().
* @pdev: PCI device struct
@@ -8734,12 +9334,13 @@ ipr_get_chip_info(const struct pci_device_id *dev_id)
* Return value:
* 0 on success / non-zero on failure
**/
-static irqreturn_t __devinit ipr_test_intr(int irq, void *devp)
+static irqreturn_t ipr_test_intr(int irq, void *devp)
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
unsigned long lock_flags = 0;
irqreturn_t rc = IRQ_HANDLED;
+ dev_info(&ioa_cfg->pdev->dev, "Received IRQ : %d\n", irq);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
ioa_cfg->msi_received = 1;
@@ -8761,8 +9362,7 @@ static irqreturn_t __devinit ipr_test_intr(int irq, void *devp)
* Return value:
* 0 on success / non-zero on failure
**/
-static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
- struct pci_dev *pdev)
+static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev)
{
int rc;
volatile u32 int_reg;
@@ -8778,7 +9378,10 @@ static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
+ if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+ rc = request_irq(ioa_cfg->vectors_info[0].vec, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
+ else
+ rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
if (rc) {
dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq);
return rc;
@@ -8788,9 +9391,9 @@ static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg32);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
wait_event_timeout(ioa_cfg->msi_wait_q, ioa_cfg->msi_received, HZ);
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
if (!ioa_cfg->msi_received) {
/* MSI test failed */
dev_info(&pdev->dev, "MSI test failed. Falling back to LSI.\n");
@@ -8800,23 +9403,25 @@ static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- free_irq(pdev->irq, ioa_cfg);
+ if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+ free_irq(ioa_cfg->vectors_info[0].vec, ioa_cfg);
+ else
+ free_irq(pdev->irq, ioa_cfg);
LEAVE;
return rc;
}
-/**
- * ipr_probe_ioa - Allocates memory and does first stage of initialization
+ /* ipr_probe_ioa - Allocates memory and does first stage of initialization
* @pdev: PCI device struct
* @dev_id: PCI device id struct
*
* Return value:
* 0 on success / non-zero on failure
**/
-static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
- const struct pci_device_id *dev_id)
+static int ipr_probe_ioa(struct pci_dev *pdev,
+ const struct pci_device_id *dev_id)
{
struct ipr_ioa_cfg *ioa_cfg;
struct Scsi_Host *host;
@@ -8824,6 +9429,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
void __iomem *ipr_regs;
int rc = PCIBIOS_SUCCESSFUL;
volatile u32 mask, uproc, interrupts;
+ unsigned long lock_flags, driver_lock_flags;
ENTER;
@@ -8919,17 +9525,56 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto cleanup_nomem;
}
- /* Enable MSI style interrupts if they are supported. */
- if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI && !pci_enable_msi(pdev)) {
+ if (ipr_number_of_msix > IPR_MAX_MSIX_VECTORS) {
+ dev_err(&pdev->dev, "The max number of MSIX is %d\n",
+ IPR_MAX_MSIX_VECTORS);
+ ipr_number_of_msix = IPR_MAX_MSIX_VECTORS;
+ }
+
+ if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI &&
+ ipr_enable_msix(ioa_cfg) == 0)
+ ioa_cfg->intr_flag = IPR_USE_MSIX;
+ else if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI &&
+ ipr_enable_msi(ioa_cfg) == 0)
+ ioa_cfg->intr_flag = IPR_USE_MSI;
+ else {
+ ioa_cfg->intr_flag = IPR_USE_LSI;
+ ioa_cfg->nvectors = 1;
+ dev_info(&pdev->dev, "Cannot enable MSI.\n");
+ }
+
+ if (ioa_cfg->intr_flag == IPR_USE_MSI ||
+ ioa_cfg->intr_flag == IPR_USE_MSIX) {
rc = ipr_test_msi(ioa_cfg, pdev);
- if (rc == -EOPNOTSUPP)
- pci_disable_msi(pdev);
+ if (rc == -EOPNOTSUPP) {
+ if (ioa_cfg->intr_flag == IPR_USE_MSI) {
+ ioa_cfg->intr_flag &= ~IPR_USE_MSI;
+ pci_disable_msi(pdev);
+ } else if (ioa_cfg->intr_flag == IPR_USE_MSIX) {
+ ioa_cfg->intr_flag &= ~IPR_USE_MSIX;
+ pci_disable_msix(pdev);
+ }
+
+ ioa_cfg->intr_flag = IPR_USE_LSI;
+ ioa_cfg->nvectors = 1;
+ }
else if (rc)
goto out_msi_disable;
- else
- dev_info(&pdev->dev, "MSI enabled with IRQ: %d\n", pdev->irq);
- } else if (ipr_debug)
- dev_info(&pdev->dev, "Cannot enable MSI.\n");
+ else {
+ if (ioa_cfg->intr_flag == IPR_USE_MSI)
+ dev_info(&pdev->dev,
+ "Request for %d MSIs succeeded with starting IRQ: %d\n",
+ ioa_cfg->nvectors, pdev->irq);
+ else if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+ dev_info(&pdev->dev,
+ "Request for %d MSIXs succeeded.",
+ ioa_cfg->nvectors);
+ }
+ }
+
+ ioa_cfg->hrrq_num = min3(ioa_cfg->nvectors,
+ (unsigned int)num_online_cpus(),
+ (unsigned int)IPR_MAX_HRRQ_NUM);
/* Save away PCI config space for use following IOA reset */
rc = pci_save_state(pdev);
@@ -8976,11 +9621,24 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
if (interrupts & IPR_PCII_IOA_UNIT_CHECKED)
ioa_cfg->ioa_unit_checked = 1;
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
- rc = request_irq(pdev->irq, ipr_isr,
- ioa_cfg->msi_received ? 0 : IRQF_SHARED,
- IPR_NAME, ioa_cfg);
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ if (ioa_cfg->intr_flag == IPR_USE_MSI
+ || ioa_cfg->intr_flag == IPR_USE_MSIX) {
+ name_msi_vectors(ioa_cfg);
+ rc = request_irq(ioa_cfg->vectors_info[0].vec, ipr_isr,
+ 0,
+ ioa_cfg->vectors_info[0].desc,
+ &ioa_cfg->hrrq[0]);
+ if (!rc)
+ rc = ipr_request_other_msi_irqs(ioa_cfg);
+ } else {
+ rc = request_irq(pdev->irq, ipr_isr,
+ IRQF_SHARED,
+ IPR_NAME, &ioa_cfg->hrrq[0]);
+ }
if (rc) {
dev_err(&pdev->dev, "Couldn't register IRQ %d! rc=%d\n",
pdev->irq, rc);
@@ -8994,9 +9652,9 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
} else
ioa_cfg->reset = ipr_reset_start_bist;
- spin_lock(&ipr_driver_lock);
+ spin_lock_irqsave(&ipr_driver_lock, driver_lock_flags);
list_add_tail(&ioa_cfg->queue, &ipr_ioa_head);
- spin_unlock(&ipr_driver_lock);
+ spin_unlock_irqrestore(&ipr_driver_lock, driver_lock_flags);
LEAVE;
out:
@@ -9005,7 +9663,10 @@ out:
cleanup_nolog:
ipr_free_mem(ioa_cfg);
out_msi_disable:
- pci_disable_msi(pdev);
+ if (ioa_cfg->intr_flag == IPR_USE_MSI)
+ pci_disable_msi(pdev);
+ else if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+ pci_disable_msix(pdev);
cleanup_nomem:
iounmap(ipr_regs);
out_release_regions:
@@ -9075,6 +9736,8 @@ static void __ipr_remove(struct pci_dev *pdev)
{
unsigned long host_lock_flags = 0;
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
+ int i;
+ unsigned long driver_lock_flags;
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
@@ -9084,16 +9747,23 @@ static void __ipr_remove(struct pci_dev *pdev)
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
}
+ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+ spin_lock(&ioa_cfg->hrrq[i]._lock);
+ ioa_cfg->hrrq[i].removing_ioa = 1;
+ spin_unlock(&ioa_cfg->hrrq[i]._lock);
+ }
+ wmb();
ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
flush_work(&ioa_cfg->work_q);
+ INIT_LIST_HEAD(&ioa_cfg->used_res_q);
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
- spin_lock(&ipr_driver_lock);
+ spin_lock_irqsave(&ipr_driver_lock, driver_lock_flags);
list_del(&ioa_cfg->queue);
- spin_unlock(&ipr_driver_lock);
+ spin_unlock_irqrestore(&ipr_driver_lock, driver_lock_flags);
if (ioa_cfg->sdt_state == ABORT_DUMP)
ioa_cfg->sdt_state = WAIT_FOR_DUMP;
@@ -9113,7 +9783,7 @@ static void __ipr_remove(struct pci_dev *pdev)
* Return value:
* none
**/
-static void __devexit ipr_remove(struct pci_dev *pdev)
+static void ipr_remove(struct pci_dev *pdev)
{
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
@@ -9136,11 +9806,10 @@ static void __devexit ipr_remove(struct pci_dev *pdev)
* Return value:
* 0 on success / non-zero on failure
**/
-static int __devinit ipr_probe(struct pci_dev *pdev,
- const struct pci_device_id *dev_id)
+static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
{
struct ipr_ioa_cfg *ioa_cfg;
- int rc;
+ int rc, i;
rc = ipr_probe_ioa(pdev, dev_id);
@@ -9187,6 +9856,17 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
scsi_add_device(ioa_cfg->host, IPR_IOA_BUS, IPR_IOA_TARGET, IPR_IOA_LUN);
ioa_cfg->allow_ml_add_del = 1;
ioa_cfg->host->max_channel = IPR_VSET_BUS;
+ ioa_cfg->iopoll_weight = ioa_cfg->chip_cfg->iopoll_weight;
+
+ if (blk_iopoll_enabled && ioa_cfg->iopoll_weight &&
+ ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
+ for (i = 1; i < ioa_cfg->hrrq_num; i++) {
+ blk_iopoll_init(&ioa_cfg->hrrq[i].iopoll,
+ ioa_cfg->iopoll_weight, ipr_iopoll);
+ blk_iopoll_enable(&ioa_cfg->hrrq[i].iopoll);
+ }
+ }
+
schedule_work(&ioa_cfg->work_q);
return 0;
}
@@ -9205,8 +9885,16 @@ static void ipr_shutdown(struct pci_dev *pdev)
{
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
unsigned long lock_flags = 0;
+ int i;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ if (blk_iopoll_enabled && ioa_cfg->iopoll_weight &&
+ ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
+ ioa_cfg->iopoll_weight = 0;
+ for (i = 1; i < ioa_cfg->hrrq_num; i++)
+ blk_iopoll_disable(&ioa_cfg->hrrq[i].iopoll);
+ }
+
while (ioa_cfg->in_reset_reload) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
@@ -9218,7 +9906,7 @@ static void ipr_shutdown(struct pci_dev *pdev)
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
}
-static struct pci_device_id ipr_pci_table[] __devinitdata = {
+static struct pci_device_id ipr_pci_table[] = {
{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, 0, 0, 0 },
{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
@@ -9279,6 +9967,8 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B2, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C0, 0, 0, 0 },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C3, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C4, 0, 0, 0 },
@@ -9292,6 +9982,14 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C8, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57CE, 0, 0, 0 },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57D5, 0, 0, 0 },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57D6, 0, 0, 0 },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57D7, 0, 0, 0 },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57D8, 0, 0, 0 },
{ }
};
MODULE_DEVICE_TABLE(pci, ipr_pci_table);
@@ -9305,7 +10003,7 @@ static struct pci_driver ipr_driver = {
.name = IPR_NAME,
.id_table = ipr_pci_table,
.probe = ipr_probe,
- .remove = __devexit_p(ipr_remove),
+ .remove = ipr_remove,
.shutdown = ipr_shutdown,
.err_handler = &ipr_err_handler,
};
@@ -9318,9 +10016,7 @@ static struct pci_driver ipr_driver = {
**/
static void ipr_halt_done(struct ipr_cmnd *ipr_cmd)
{
- struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
}
/**
@@ -9333,16 +10029,16 @@ static int ipr_halt(struct notifier_block *nb, ulong event, void *buf)
{
struct ipr_cmnd *ipr_cmd;
struct ipr_ioa_cfg *ioa_cfg;
- unsigned long flags = 0;
+ unsigned long flags = 0, driver_lock_flags;
if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
return NOTIFY_DONE;
- spin_lock(&ipr_driver_lock);
+ spin_lock_irqsave(&ipr_driver_lock, driver_lock_flags);
list_for_each_entry(ioa_cfg, &ipr_ioa_head, queue) {
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
- if (!ioa_cfg->allow_cmds) {
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
continue;
}
@@ -9356,7 +10052,7 @@ static int ipr_halt(struct notifier_block *nb, ulong event, void *buf)
ipr_do_req(ipr_cmd, ipr_halt_done, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
}
- spin_unlock(&ipr_driver_lock);
+ spin_unlock_irqrestore(&ipr_driver_lock, driver_lock_flags);
return NOTIFY_OK;
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index c8a137f..07a85ce 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -32,14 +32,15 @@
#include <linux/libata.h>
#include <linux/list.h>
#include <linux/kref.h>
+#include <linux/blk-iopoll.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.5.4"
-#define IPR_DRIVER_DATE "(July 11, 2012)"
+#define IPR_DRIVER_VERSION "2.6.0"
+#define IPR_DRIVER_DATE "(November 16, 2012)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -82,6 +83,7 @@
#define IPR_SUBS_DEV_ID_57B4 0x033B
#define IPR_SUBS_DEV_ID_57B2 0x035F
+#define IPR_SUBS_DEV_ID_57C0 0x0352
#define IPR_SUBS_DEV_ID_57C3 0x0353
#define IPR_SUBS_DEV_ID_57C4 0x0354
#define IPR_SUBS_DEV_ID_57C6 0x0357
@@ -94,6 +96,10 @@
#define IPR_SUBS_DEV_ID_574D 0x0356
#define IPR_SUBS_DEV_ID_57C8 0x035D
+#define IPR_SUBS_DEV_ID_57D5 0x03FB
+#define IPR_SUBS_DEV_ID_57D6 0x03FC
+#define IPR_SUBS_DEV_ID_57D7 0x03FF
+#define IPR_SUBS_DEV_ID_57D8 0x03FE
#define IPR_NAME "ipr"
/*
@@ -298,6 +304,9 @@ IPR_PCII_NO_HOST_RRQ | IPR_PCII_IOARRIN_LOST | IPR_PCII_MMIO_ERROR)
* Misc literals
*/
#define IPR_NUM_IOADL_ENTRIES IPR_MAX_SGLIST
+#define IPR_MAX_MSIX_VECTORS 0x5
+#define IPR_MAX_HRRQ_NUM 0x10
+#define IPR_INIT_HRRQ 0x0
/*
* Adapter interface types
@@ -404,7 +413,7 @@ struct ipr_config_table_entry64 {
__be64 dev_id;
__be64 lun;
__be64 lun_wwn[2];
-#define IPR_MAX_RES_PATH_LENGTH 24
+#define IPR_MAX_RES_PATH_LENGTH 48
__be64 res_path;
struct ipr_std_inq_data std_inq_data;
u8 reserved2[4];
@@ -459,9 +468,40 @@ struct ipr_supported_device {
u8 reserved2[16];
}__attribute__((packed, aligned (4)));
+struct ipr_hrr_queue {
+ struct ipr_ioa_cfg *ioa_cfg;
+ __be32 *host_rrq;
+ dma_addr_t host_rrq_dma;
+#define IPR_HRRQ_REQ_RESP_HANDLE_MASK 0xfffffffc
+#define IPR_HRRQ_RESP_BIT_SET 0x00000002
+#define IPR_HRRQ_TOGGLE_BIT 0x00000001
+#define IPR_HRRQ_REQ_RESP_HANDLE_SHIFT 2
+#define IPR_ID_HRRQ_SELE_ENABLE 0x02
+ volatile __be32 *hrrq_start;
+ volatile __be32 *hrrq_end;
+ volatile __be32 *hrrq_curr;
+
+ struct list_head hrrq_free_q;
+ struct list_head hrrq_pending_q;
+ spinlock_t _lock;
+ spinlock_t *lock;
+
+ volatile u32 toggle_bit;
+ u32 size;
+ u32 min_cmd_id;
+ u32 max_cmd_id;
+ u8 allow_interrupts:1;
+ u8 ioa_is_dead:1;
+ u8 allow_cmds:1;
+ u8 removing_ioa:1;
+
+ struct blk_iopoll iopoll;
+};
+
/* Command packet structure */
struct ipr_cmd_pkt {
- __be16 reserved; /* Reserved by IOA */
+ u8 reserved; /* Reserved by IOA */
+ u8 hrrq_id;
u8 request_type;
#define IPR_RQTYPE_SCSICDB 0x00
#define IPR_RQTYPE_IOACMD 0x01
@@ -512,7 +552,7 @@ struct ipr_ioarcb_ata_regs { /* 22 bytes */
u8 hob_lbam;
u8 hob_lbah;
u8 ctl;
-}__attribute__ ((packed, aligned(4)));
+}__attribute__ ((packed, aligned(2)));
struct ipr_ioadl_desc {
__be32 flags_and_data_len;
@@ -1022,6 +1062,10 @@ struct ipr_hostrcb64_fabric_desc {
struct ipr_hostrcb64_config_element elem[1];
}__attribute__((packed, aligned (8)));
+#define for_each_hrrq(hrrq, ioa_cfg) \
+ for (hrrq = (ioa_cfg)->hrrq; \
+ hrrq < ((ioa_cfg)->hrrq + (ioa_cfg)->hrrq_num); hrrq++)
+
#define for_each_fabric_cfg(fabric, cfg) \
for (cfg = (fabric)->elem; \
cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \
@@ -1308,6 +1352,7 @@ struct ipr_chip_cfg_t {
u16 max_cmds;
u8 cache_line_size;
u8 clear_isr;
+ u32 iopoll_weight;
struct ipr_interrupt_offsets regs;
};
@@ -1317,6 +1362,7 @@ struct ipr_chip_t {
u16 intr_type;
#define IPR_USE_LSI 0x00
#define IPR_USE_MSI 0x01
+#define IPR_USE_MSIX 0x02
u16 sis_type;
#define IPR_SIS32 0x00
#define IPR_SIS64 0x01
@@ -1375,13 +1421,10 @@ struct ipr_ioa_cfg {
struct list_head queue;
- u8 allow_interrupts:1;
u8 in_reset_reload:1;
u8 in_ioa_bringdown:1;
u8 ioa_unit_checked:1;
- u8 ioa_is_dead:1;
u8 dump_taken:1;
- u8 allow_cmds:1;
u8 allow_ml_add_del:1;
u8 needs_hard_reset:1;
u8 dual_raid:1;
@@ -1397,9 +1440,9 @@ struct ipr_ioa_cfg {
/*
* Bitmaps for SIS64 generated target values
*/
- unsigned long *target_ids;
- unsigned long *array_ids;
- unsigned long *vset_ids;
+ unsigned long target_ids[BITS_TO_LONGS(IPR_MAX_SIS64_DEVS)];
+ unsigned long array_ids[BITS_TO_LONGS(IPR_MAX_SIS64_DEVS)];
+ unsigned long vset_ids[BITS_TO_LONGS(IPR_MAX_SIS64_DEVS)];
u16 type; /* CCIN of the card */
@@ -1413,21 +1456,7 @@ struct ipr_ioa_cfg {
char trace_start[8];
#define IPR_TRACE_START_LABEL "trace"
struct ipr_trace_entry *trace;
- u32 trace_index:IPR_NUM_TRACE_INDEX_BITS;
-
- /*
- * Queue for free command blocks
- */
- char ipr_free_label[8];
-#define IPR_FREEQ_LABEL "free-q"
- struct list_head free_q;
-
- /*
- * Queue for command blocks outstanding to the adapter
- */
- char ipr_pending_label[8];
-#define IPR_PENDQ_LABEL "pend-q"
- struct list_head pending_q;
+ atomic_t trace_index;
char cfg_table_start[8];
#define IPR_CFG_TBL_START "cfg"
@@ -1452,16 +1481,10 @@ struct ipr_ioa_cfg {
struct list_head hostrcb_free_q;
struct list_head hostrcb_pending_q;
- __be32 *host_rrq;
- dma_addr_t host_rrq_dma;
-#define IPR_HRRQ_REQ_RESP_HANDLE_MASK 0xfffffffc
-#define IPR_HRRQ_RESP_BIT_SET 0x00000002
-#define IPR_HRRQ_TOGGLE_BIT 0x00000001
-#define IPR_HRRQ_REQ_RESP_HANDLE_SHIFT 2
- volatile __be32 *hrrq_start;
- volatile __be32 *hrrq_end;
- volatile __be32 *hrrq_curr;
- volatile u32 toggle_bit;
+ struct ipr_hrr_queue hrrq[IPR_MAX_HRRQ_NUM];
+ u32 hrrq_num;
+ atomic_t hrrq_index;
+ u16 identify_hrrq_index;
struct ipr_bus_attributes bus_attr[IPR_MAX_NUM_BUSES];
@@ -1507,6 +1530,17 @@ struct ipr_ioa_cfg {
u32 max_cmds;
struct ipr_cmnd **ipr_cmnd_list;
dma_addr_t *ipr_cmnd_list_dma;
+
+ u16 intr_flag;
+ unsigned int nvectors;
+
+ struct {
+ unsigned short vec;
+ char desc[22];
+ } vectors_info[IPR_MAX_MSIX_VECTORS];
+
+ u32 iopoll_weight;
+
}; /* struct ipr_ioa_cfg */
struct ipr_cmnd {
@@ -1544,6 +1578,7 @@ struct ipr_cmnd {
struct scsi_device *sdev;
} u;
+ struct ipr_hrr_queue *hrrq;
struct ipr_ioa_cfg *ioa_cfg;
};
@@ -1717,7 +1752,8 @@ struct ipr_ucode_image_header {
if (ipr_is_device(hostrcb)) { \
if ((hostrcb)->ioa_cfg->sis64) { \
printk(KERN_ERR IPR_NAME ": %s: " fmt, \
- ipr_format_res_path(hostrcb->hcam.u.error64.fd_res_path, \
+ ipr_format_res_path(hostrcb->ioa_cfg, \
+ hostrcb->hcam.u.error64.fd_res_path, \
hostrcb->rp_buffer, \
sizeof(hostrcb->rp_buffer)), \
__VA_ARGS__); \
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index b6d7a5c..8d5ea8a 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -326,10 +326,9 @@ static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data,
static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
unsigned int count);
-static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static int ips_host_info(ips_ha_t *, char *, off_t, int);
-static void copy_mem_info(IPS_INFOSTR *, char *, int);
-static int copy_info(IPS_INFOSTR *, char *, ...);
+static int ips_write_info(struct Scsi_Host *, char *, int);
+static int ips_show_info(struct seq_file *, struct Scsi_Host *);
+static int ips_host_info(ips_ha_t *, struct seq_file *);
static int ips_abort_init(ips_ha_t * ha, int index);
static int ips_init_phase2(int index);
@@ -367,7 +366,8 @@ static struct scsi_host_template ips_driver_template = {
.eh_abort_handler = ips_eh_abort,
.eh_host_reset_handler = ips_eh_reset,
.proc_name = "ips",
- .proc_info = ips_proc_info,
+ .show_info = ips_show_info,
+ .write_info = ips_write_info,
.slave_configure = ips_slave_configure,
.bios_param = ips_biosparam,
.this_id = -1,
@@ -389,14 +389,14 @@ MODULE_DEVICE_TABLE( pci, ips_pci_table );
static char ips_hot_plug_name[] = "ips";
-static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
-static void __devexit ips_remove_device(struct pci_dev *pci_dev);
+static int ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
+static void ips_remove_device(struct pci_dev *pci_dev);
static struct pci_driver ips_pci_driver = {
.name = ips_hot_plug_name,
.id_table = ips_pci_table,
.probe = ips_insert_device,
- .remove = __devexit_p(ips_remove_device),
+ .remove = ips_remove_device,
};
@@ -1433,25 +1433,12 @@ ips_info(struct Scsi_Host *SH)
return (bp);
}
-/****************************************************************************/
-/* */
-/* Routine Name: ips_proc_info */
-/* */
-/* Routine Description: */
-/* */
-/* The passthru interface for the driver */
-/* */
-/****************************************************************************/
static int
-ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
- int length, int func)
+ips_write_info(struct Scsi_Host *host, char *buffer, int length)
{
int i;
- int ret;
ips_ha_t *ha = NULL;
- METHOD_TRACE("ips_proc_info", 1);
-
/* Find our host structure */
for (i = 0; i < ips_next_controller; i++) {
if (ips_sh[i]) {
@@ -1465,18 +1452,29 @@ ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
if (!ha)
return (-EINVAL);
- if (func) {
- /* write */
- return (0);
- } else {
- /* read */
- if (start)
- *start = buffer;
+ return 0;
+}
- ret = ips_host_info(ha, buffer, offset, length);
+static int
+ips_show_info(struct seq_file *m, struct Scsi_Host *host)
+{
+ int i;
+ ips_ha_t *ha = NULL;
- return (ret);
+ /* Find our host structure */
+ for (i = 0; i < ips_next_controller; i++) {
+ if (ips_sh[i]) {
+ if (ips_sh[i] == host) {
+ ha = (ips_ha_t *) ips_sh[i]->hostdata;
+ break;
+ }
+ }
}
+
+ if (!ha)
+ return (-EINVAL);
+
+ return ips_host_info(ha, m);
}
/*--------------------------------------------------------------------------*/
@@ -2035,183 +2033,113 @@ ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb)
/* */
/****************************************************************************/
static int
-ips_host_info(ips_ha_t * ha, char *ptr, off_t offset, int len)
+ips_host_info(ips_ha_t *ha, struct seq_file *m)
{
- IPS_INFOSTR info;
-
METHOD_TRACE("ips_host_info", 1);
- info.buffer = ptr;
- info.length = len;
- info.offset = offset;
- info.pos = 0;
- info.localpos = 0;
-
- copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
+ seq_printf(m, "\nIBM ServeRAID General Information:\n\n");
if ((le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) &&
(le16_to_cpu(ha->nvram->adapter_type) != 0))
- copy_info(&info, "\tController Type : %s\n",
+ seq_printf(m, "\tController Type : %s\n",
ips_adapter_name[ha->ad_type - 1]);
else
- copy_info(&info,
+ seq_printf(m,
"\tController Type : Unknown\n");
if (ha->io_addr)
- copy_info(&info,
- "\tIO region : 0x%lx (%d bytes)\n",
+ seq_printf(m,
+ "\tIO region : 0x%x (%d bytes)\n",
ha->io_addr, ha->io_len);
if (ha->mem_addr) {
- copy_info(&info,
- "\tMemory region : 0x%lx (%d bytes)\n",
+ seq_printf(m,
+ "\tMemory region : 0x%x (%d bytes)\n",
ha->mem_addr, ha->mem_len);
- copy_info(&info,
+ seq_printf(m,
"\tShared memory address : 0x%lx\n",
- ha->mem_ptr);
+ (unsigned long)ha->mem_ptr);
}
- copy_info(&info, "\tIRQ number : %d\n", ha->pcidev->irq);
+ seq_printf(m, "\tIRQ number : %d\n", ha->pcidev->irq);
/* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
/* That keeps everything happy for "text" operations on the proc file. */
if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
if (ha->nvram->bios_low[3] == 0) {
- copy_info(&info,
- "\tBIOS Version : %c%c%c%c%c%c%c\n",
- ha->nvram->bios_high[0], ha->nvram->bios_high[1],
- ha->nvram->bios_high[2], ha->nvram->bios_high[3],
- ha->nvram->bios_low[0], ha->nvram->bios_low[1],
- ha->nvram->bios_low[2]);
+ seq_printf(m,
+ "\tBIOS Version : %c%c%c%c%c%c%c\n",
+ ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+ ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+ ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+ ha->nvram->bios_low[2]);
} else {
- copy_info(&info,
- "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
- ha->nvram->bios_high[0], ha->nvram->bios_high[1],
- ha->nvram->bios_high[2], ha->nvram->bios_high[3],
- ha->nvram->bios_low[0], ha->nvram->bios_low[1],
- ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
+ seq_printf(m,
+ "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
+ ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+ ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+ ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+ ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
}
}
if (ha->enq->CodeBlkVersion[7] == 0) {
- copy_info(&info,
- "\tFirmware Version : %c%c%c%c%c%c%c\n",
- ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
- ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
- ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
- ha->enq->CodeBlkVersion[6]);
+ seq_printf(m,
+ "\tFirmware Version : %c%c%c%c%c%c%c\n",
+ ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+ ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+ ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+ ha->enq->CodeBlkVersion[6]);
} else {
- copy_info(&info,
- "\tFirmware Version : %c%c%c%c%c%c%c%c\n",
- ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
- ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
- ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
- ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
+ seq_printf(m,
+ "\tFirmware Version : %c%c%c%c%c%c%c%c\n",
+ ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+ ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+ ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+ ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
}
if (ha->enq->BootBlkVersion[7] == 0) {
- copy_info(&info,
- "\tBoot Block Version : %c%c%c%c%c%c%c\n",
- ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
- ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
- ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
- ha->enq->BootBlkVersion[6]);
+ seq_printf(m,
+ "\tBoot Block Version : %c%c%c%c%c%c%c\n",
+ ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+ ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+ ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+ ha->enq->BootBlkVersion[6]);
} else {
- copy_info(&info,
- "\tBoot Block Version : %c%c%c%c%c%c%c%c\n",
- ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
- ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
- ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
- ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
+ seq_printf(m,
+ "\tBoot Block Version : %c%c%c%c%c%c%c%c\n",
+ ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+ ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+ ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+ ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
}
- copy_info(&info, "\tDriver Version : %s%s\n",
+ seq_printf(m, "\tDriver Version : %s%s\n",
IPS_VERSION_HIGH, IPS_VERSION_LOW);
- copy_info(&info, "\tDriver Build : %d\n",
+ seq_printf(m, "\tDriver Build : %d\n",
IPS_BUILD_IDENT);
- copy_info(&info, "\tMax Physical Devices : %d\n",
+ seq_printf(m, "\tMax Physical Devices : %d\n",
ha->enq->ucMaxPhysicalDevices);
- copy_info(&info, "\tMax Active Commands : %d\n",
+ seq_printf(m, "\tMax Active Commands : %d\n",
ha->max_cmds);
- copy_info(&info, "\tCurrent Queued Commands : %d\n",
+ seq_printf(m, "\tCurrent Queued Commands : %d\n",
ha->scb_waitlist.count);
- copy_info(&info, "\tCurrent Active Commands : %d\n",
+ seq_printf(m, "\tCurrent Active Commands : %d\n",
ha->scb_activelist.count - ha->num_ioctl);
- copy_info(&info, "\tCurrent Queued PT Commands : %d\n",
+ seq_printf(m, "\tCurrent Queued PT Commands : %d\n",
ha->copp_waitlist.count);
- copy_info(&info, "\tCurrent Active PT Commands : %d\n",
+ seq_printf(m, "\tCurrent Active PT Commands : %d\n",
ha->num_ioctl);
- copy_info(&info, "\n");
-
- return (info.localpos);
-}
-
-/****************************************************************************/
-/* */
-/* Routine Name: copy_mem_info */
-/* */
-/* Routine Description: */
-/* */
-/* Copy data into an IPS_INFOSTR structure */
-/* */
-/****************************************************************************/
-static void
-copy_mem_info(IPS_INFOSTR * info, char *data, int len)
-{
- METHOD_TRACE("copy_mem_info", 1);
-
- if (info->pos + len < info->offset) {
- info->pos += len;
- return;
- }
+ seq_printf(m, "\n");
- if (info->pos < info->offset) {
- data += (info->offset - info->pos);
- len -= (info->offset - info->pos);
- info->pos += (info->offset - info->pos);
- }
-
- if (info->localpos + len > info->length)
- len = info->length - info->localpos;
-
- if (len > 0) {
- memcpy(info->buffer + info->localpos, data, len);
- info->pos += len;
- info->localpos += len;
- }
-}
-
-/****************************************************************************/
-/* */
-/* Routine Name: copy_info */
-/* */
-/* Routine Description: */
-/* */
-/* printf style wrapper for an info structure */
-/* */
-/****************************************************************************/
-static int
-copy_info(IPS_INFOSTR * info, char *fmt, ...)
-{
- va_list args;
- char buf[128];
- int len;
-
- METHOD_TRACE("copy_info", 1);
-
- va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
- va_end(args);
-
- copy_mem_info(info, buf, len);
-
- return (len);
+ return 0;
}
/****************************************************************************/
@@ -6837,7 +6765,7 @@ err_out_sh:
/* Routine Description: */
/* Remove one Adapter ( Hot Plugging ) */
/*---------------------------------------------------------------------------*/
-static void __devexit
+static void
ips_remove_device(struct pci_dev *pci_dev)
{
struct Scsi_Host *sh = pci_get_drvdata(pci_dev);
@@ -6898,7 +6826,7 @@ module_exit(ips_module_exit);
/* Return Value: */
/* 0 if Successful, else non-zero */
/*---------------------------------------------------------------------------*/
-static int __devinit
+static int
ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
{
int index = -1;
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index f2df059..45b9566 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -416,7 +416,6 @@
/*
* Scsi_Host Template
*/
- static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[]);
static int ips_slave_configure(struct scsi_device *SDptr);
@@ -959,14 +958,6 @@ typedef union {
IPS_ENH_SG_LIST *enh_list;
} IPS_SG_LIST;
-typedef struct _IPS_INFOSTR {
- char *buffer;
- int length;
- int offset;
- int pos;
- int localpos;
-} IPS_INFOSTR;
-
typedef struct {
char *option_name;
int *option_flag;
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index b74050b..d25d0d8 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -282,7 +282,7 @@ static void isci_unregister(struct isci_host *isci_host)
scsi_host_put(shost);
}
-static int __devinit isci_pci_init(struct pci_dev *pdev)
+static int isci_pci_init(struct pci_dev *pdev)
{
int err, bar_num, bar_mask = 0;
void __iomem * const *iomap;
@@ -616,7 +616,7 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
return NULL;
}
-static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct isci_pci_info *pci_info;
int err, i;
@@ -633,7 +633,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
return -ENOMEM;
pci_set_drvdata(pdev, pci_info);
- if (efi_enabled)
+ if (efi_enabled(EFI_RUNTIME_SERVICES))
orom = isci_get_efi_var(pdev);
if (!orom)
@@ -709,7 +709,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
return err;
}
-static void __devexit isci_pci_remove(struct pci_dev *pdev)
+static void isci_pci_remove(struct pci_dev *pdev)
{
struct isci_host *ihost;
int i;
@@ -721,7 +721,7 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev)
}
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int isci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -770,18 +770,16 @@ static int isci_resume(struct device *dev)
return 0;
}
+#endif
static SIMPLE_DEV_PM_OPS(isci_pm_ops, isci_suspend, isci_resume);
-#endif
static struct pci_driver isci_pci_driver = {
.name = DRV_NAME,
.id_table = isci_id_table,
.probe = isci_pci_probe,
- .remove = __devexit_p(isci_pci_remove),
-#ifdef CONFIG_PM
+ .remove = isci_pci_remove,
.driver.pm = &isci_pm_ops,
-#endif
};
static __init int isci_init(void)
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index c3aa6c5..96a26f4 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -1085,7 +1085,7 @@ static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *s
struct isci_host *ihost = idev->owning_port->owning_controller;
struct domain_device *dev = idev->domain_dev;
- if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
+ if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
sci_change_state(&idev->sm, SCI_STP_DEV_IDLE);
} else if (dev_is_expander(dev)) {
sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE);
@@ -1098,7 +1098,7 @@ static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
struct domain_device *dev = idev->domain_dev;
- if (dev->dev_type == SAS_END_DEV) {
+ if (dev->dev_type == SAS_END_DEVICE) {
struct isci_host *ihost = idev->owning_port->owning_controller;
isci_remote_device_not_ready(ihost, idev,
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 7674caa..47a013f 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -297,7 +297,7 @@ static inline struct isci_remote_device *rnc_to_dev(struct sci_remote_node_conte
static inline bool dev_is_expander(struct domain_device *dev)
{
- return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV;
+ return dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE;
}
static inline void sci_remote_device_decrement_request_count(struct isci_remote_device *idev)
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 9594ab6..7b08215 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -184,8 +184,8 @@ static void sci_io_request_build_ssp_command_iu(struct isci_request *ireq)
cmd_iu->task_attr = task->ssp_task.task_attr;
cmd_iu->_r_c = 0;
- sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cdb,
- sizeof(task->ssp_task.cdb) / sizeof(u32));
+ sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cmd->cmnd,
+ task->ssp_task.cmd->cmd_len / sizeof(u32));
}
static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq)
@@ -2978,7 +2978,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
/* all unaccelerated request types (non ssp or ncq) handled with
* substates
*/
- if (!task && dev->dev_type == SAS_END_DEV) {
+ if (!task && dev->dev_type == SAS_END_DEVICE) {
state = SCI_REQ_TASK_WAIT_TC_COMP;
} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
state = SCI_REQ_SMP_WAIT_RESP;
@@ -3101,7 +3101,7 @@ sci_io_request_construct(struct isci_host *ihost,
if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
return SCI_FAILURE_INVALID_REMOTE_DEVICE;
- if (dev->dev_type == SAS_END_DEV)
+ if (dev->dev_type == SAS_END_DEVICE)
/* pass */;
else if (dev_is_sata(dev))
memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
@@ -3125,7 +3125,7 @@ enum sci_status sci_task_request_construct(struct isci_host *ihost,
/* Build the common part of the request */
sci_general_request_construct(ihost, idev, ireq);
- if (dev->dev_type == SAS_END_DEV || dev_is_sata(dev)) {
+ if (dev->dev_type == SAS_END_DEVICE || dev_is_sata(dev)) {
set_bit(IREQ_TMF, &ireq->flags);
memset(ireq->tc, 0, sizeof(struct scu_task_context));
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index b6f19a1..9bb020a 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -250,7 +250,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
}
/* XXX convert to get this from task->tproto like other drivers */
- if (dev->dev_type == SAS_END_DEV) {
+ if (dev->dev_type == SAS_END_DEVICE) {
isci_tmf->proto = SAS_PROTOCOL_SSP;
status = sci_task_request_construct_ssp(ireq);
if (status != SCI_SUCCESS)
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 1b91ca0..9e2588a 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -370,17 +370,24 @@ static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn)
static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
{
struct iscsi_conn *conn = task->conn;
- int rc;
+ unsigned long pflags = current->flags;
+ int rc = 0;
+
+ current->flags |= PF_MEMALLOC;
while (iscsi_sw_tcp_xmit_qlen(conn)) {
rc = iscsi_sw_tcp_xmit(conn);
- if (rc == 0)
- return -EAGAIN;
+ if (rc == 0) {
+ rc = -EAGAIN;
+ break;
+ }
if (rc < 0)
- return rc;
+ break;
+ rc = 0;
}
- return 0;
+ tsk_restore_flags(current, pflags, PF_MEMALLOC);
+ return rc;
}
/*
@@ -665,6 +672,7 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
sk->sk_reuse = SK_CAN_REUSE;
sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
sk->sk_allocation = GFP_ATOMIC;
+ sk_set_memalloc(sk);
iscsi_sw_tcp_conn_set_callbacks(conn);
tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 27cfb0c..69efbf1 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -129,7 +129,7 @@ static const struct esp_driver_ops jazz_esp_ops = {
.dma_error = jazz_esp_dma_error,
};
-static int __devinit esp_jazz_probe(struct platform_device *dev)
+static int esp_jazz_probe(struct platform_device *dev)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
struct Scsi_Host *host;
@@ -201,7 +201,7 @@ fail:
return err;
}
-static int __devexit esp_jazz_remove(struct platform_device *dev)
+static int esp_jazz_remove(struct platform_device *dev)
{
struct esp *esp = dev_get_drvdata(&dev->dev);
unsigned int irq = esp->host->irq;
@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:jazz_esp");
static struct platform_driver esp_jazz_driver = {
.probe = esp_jazz_probe,
- .remove = __devexit_p(esp_jazz_remove),
+ .remove = esp_jazz_remove,
.driver = {
.name = "jazz_esp",
.owner = THIS_MODULE,
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 23880f8..5c4ded9 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -168,7 +168,7 @@ static struct parisc_driver lasi700_driver = {
.name = "lasi_scsi",
.id_table = lasi700_ids,
.probe = lasi700_probe,
- .remove = __devexit_p(lasi700_driver_remove),
+ .remove = lasi700_driver_remove,
};
static int __init
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 8e561e6..880a906 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -712,12 +712,13 @@ static void fc_disc_stop_final(struct fc_lport *lport)
}
/**
- * fc_disc_init() - Initialize the discovery layer for a local port
- * @lport: The local port that needs the discovery layer to be initialized
+ * fc_disc_config() - Configure the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be configured
+ * @priv: Private data structre for users of the discovery layer
*/
-int fc_disc_init(struct fc_lport *lport)
+void fc_disc_config(struct fc_lport *lport, void *priv)
{
- struct fc_disc *disc;
+ struct fc_disc *disc = &lport->disc;
if (!lport->tt.disc_start)
lport->tt.disc_start = fc_disc_start;
@@ -732,12 +733,21 @@ int fc_disc_init(struct fc_lport *lport)
lport->tt.disc_recv_req = fc_disc_recv_req;
disc = &lport->disc;
+
+ disc->priv = priv;
+}
+EXPORT_SYMBOL(fc_disc_config);
+
+/**
+ * fc_disc_init() - Initialize the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be initialized
+ */
+void fc_disc_init(struct fc_lport *lport)
+{
+ struct fc_disc *disc = &lport->disc;
+
INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
mutex_init(&disc->disc_mutex);
INIT_LIST_HEAD(&disc->rports);
-
- disc->priv = lport;
-
- return 0;
}
EXPORT_SYMBOL(fc_disc_init);
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index c772d8d..5879929 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -337,7 +337,7 @@ static void fc_exch_release(struct fc_exch *ep)
* fc_exch_timer_cancel() - cancel exch timer
* @ep: The exchange whose timer to be canceled
*/
-static inline void fc_exch_timer_cancel(struct fc_exch *ep)
+static inline void fc_exch_timer_cancel(struct fc_exch *ep)
{
if (cancel_delayed_work(&ep->timeout_work)) {
FC_EXCH_DBG(ep, "Exchange timer canceled\n");
@@ -463,13 +463,7 @@ static void fc_exch_delete(struct fc_exch *ep)
fc_exch_release(ep); /* drop hold for exch in mp */
}
-/**
- * fc_seq_send() - Send a frame using existing sequence/exchange pair
- * @lport: The local port that the exchange will be sent on
- * @sp: The sequence to be sent
- * @fp: The frame to be sent on the exchange
- */
-static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
+static int fc_seq_send_locked(struct fc_lport *lport, struct fc_seq *sp,
struct fc_frame *fp)
{
struct fc_exch *ep;
@@ -479,7 +473,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
u8 fh_type = fh->fh_type;
ep = fc_seq_exch(sp);
- WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT);
+ WARN_ON(!(ep->esb_stat & ESB_ST_SEQ_INIT));
f_ctl = ntoh24(fh->fh_f_ctl);
fc_exch_setup_hdr(ep, fp, f_ctl);
@@ -502,17 +496,34 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
error = lport->tt.frame_send(lport, fp);
if (fh_type == FC_TYPE_BLS)
- return error;
+ goto out;
/*
* Update the exchange and sequence flags,
* assuming all frames for the sequence have been sent.
* We can only be called to send once for each sequence.
*/
- spin_lock_bh(&ep->ex_lock);
ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ; /* not first seq */
if (f_ctl & FC_FC_SEQ_INIT)
ep->esb_stat &= ~ESB_ST_SEQ_INIT;
+out:
+ return error;
+}
+
+/**
+ * fc_seq_send() - Send a frame using existing sequence/exchange pair
+ * @lport: The local port that the exchange will be sent on
+ * @sp: The sequence to be sent
+ * @fp: The frame to be sent on the exchange
+ */
+static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
+ struct fc_frame *fp)
+{
+ struct fc_exch *ep;
+ int error;
+ ep = fc_seq_exch(sp);
+ spin_lock_bh(&ep->ex_lock);
+ error = fc_seq_send_locked(lport, sp, fp);
spin_unlock_bh(&ep->ex_lock);
return error;
}
@@ -629,7 +640,7 @@ static int fc_exch_abort_locked(struct fc_exch *ep,
if (fp) {
fc_fill_fc_hdr(fp, FC_RCTL_BA_ABTS, ep->did, ep->sid,
FC_TYPE_BLS, FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
- error = fc_seq_send(ep->lp, sp, fp);
+ error = fc_seq_send_locked(ep->lp, sp, fp);
} else
error = -ENOBUFS;
return error;
@@ -1132,7 +1143,7 @@ static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp,
f_ctl = FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT;
f_ctl |= ep->f_ctl;
fc_fill_fc_hdr(fp, rctl, ep->did, ep->sid, fh_type, f_ctl, 0);
- fc_seq_send(ep->lp, sp, fp);
+ fc_seq_send_locked(ep->lp, sp, fp);
}
/**
@@ -1307,8 +1318,8 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
ap->ba_low_seq_cnt = htons(sp->cnt);
}
sp = fc_seq_start_next_locked(sp);
- spin_unlock_bh(&ep->ex_lock);
fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS);
+ spin_unlock_bh(&ep->ex_lock);
fc_frame_free(rx_fp);
return;
@@ -1556,7 +1567,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
fc_exch_rctl_name(fh->fh_r_ctl));
if (cancel_delayed_work_sync(&ep->timeout_work)) {
- FC_EXCH_DBG(ep, "Exchange timer canceled\n");
+ FC_EXCH_DBG(ep, "Exchange timer canceled due to ABTS response\n");
fc_exch_release(ep); /* release from pending timer hold */
}
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index fcb9d0b..5fd0f1f 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1381,10 +1381,10 @@ static void fc_fcp_timeout(unsigned long data)
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
- if (fsp->state & FC_SRB_RCV_STATUS)
- fc_fcp_complete_locked(fsp);
- else if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
+ if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
fc_fcp_rec(fsp);
+ else if (fsp->state & FC_SRB_RCV_STATUS)
+ fc_fcp_complete_locked(fsp);
else
fc_fcp_recovery(fsp, FC_TIMED_OUT);
fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
@@ -2043,7 +2043,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
return SUCCESS;
}
- /* grab a ref so the fsp and sc_cmd cannot be relased from under us */
+ /* grab a ref so the fsp and sc_cmd cannot be released from under us */
fc_fcp_pkt_hold(fsp);
spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index c2830cc..b74189d 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -41,25 +41,25 @@ extern unsigned int fc_debug_logging;
#define FC_LIBFC_DBG(fmt, args...) \
FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \
- printk(KERN_INFO "libfc: " fmt, ##args))
+ pr_info("libfc: " fmt, ##args))
#define FC_LPORT_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_LPORT_LOGGING, \
- printk(KERN_INFO "host%u: lport %6.6x: " fmt, \
- (lport)->host->host_no, \
- (lport)->port_id, ##args))
+ pr_info("host%u: lport %6.6x: " fmt, \
+ (lport)->host->host_no, \
+ (lport)->port_id, ##args))
-#define FC_DISC_DBG(disc, fmt, args...) \
- FC_CHECK_LOGGING(FC_DISC_LOGGING, \
- printk(KERN_INFO "host%u: disc: " fmt, \
- fc_disc_lport(disc)->host->host_no, \
- ##args))
+#define FC_DISC_DBG(disc, fmt, args...) \
+ FC_CHECK_LOGGING(FC_DISC_LOGGING, \
+ pr_info("host%u: disc: " fmt, \
+ fc_disc_lport(disc)->host->host_no, \
+ ##args))
#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \
FC_CHECK_LOGGING(FC_RPORT_LOGGING, \
- printk(KERN_INFO "host%u: rport %6.6x: " fmt, \
- (lport)->host->host_no, \
- (port_id), ##args))
+ pr_info("host%u: rport %6.6x: " fmt, \
+ (lport)->host->host_no, \
+ (port_id), ##args))
#define FC_RPORT_DBG(rdata, fmt, args...) \
FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args)
@@ -70,13 +70,13 @@ extern unsigned int fc_debug_logging;
if ((pkt)->seq_ptr) { \
struct fc_exch *_ep = NULL; \
_ep = fc_seq_exch((pkt)->seq_ptr); \
- printk(KERN_INFO "host%u: fcp: %6.6x: " \
+ pr_info("host%u: fcp: %6.6x: " \
"xid %04x-%04x: " fmt, \
(pkt)->lp->host->host_no, \
(pkt)->rport->port_id, \
(_ep)->oxid, (_ep)->rxid, ##args); \
} else { \
- printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \
+ pr_info("host%u: fcp: %6.6x: " fmt, \
(pkt)->lp->host->host_no, \
(pkt)->rport->port_id, ##args); \
} \
@@ -84,14 +84,14 @@ extern unsigned int fc_debug_logging;
#define FC_EXCH_DBG(exch, fmt, args...) \
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
- printk(KERN_INFO "host%u: xid %4x: " fmt, \
- (exch)->lp->host->host_no, \
- exch->xid, ##args))
+ pr_info("host%u: xid %4x: " fmt, \
+ (exch)->lp->host->host_no, \
+ exch->xid, ##args))
#define FC_SCSI_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_SCSI_LOGGING, \
- printk(KERN_INFO "host%u: scsi: " fmt, \
- (lport)->host->host_no, ##args))
+ pr_info("host%u: scsi: " fmt, \
+ (lport)->host->host_no, ##args))
/*
* FC-4 Providers.
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 83aa1ef..c710d90 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -582,7 +582,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
static void fc_rport_error_retry(struct fc_rport_priv *rdata,
struct fc_frame *fp)
{
- unsigned long delay = FC_DEF_E_D_TOV;
+ unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
if (PTR_ERR(fp) == -FC_EX_CLOSED)
@@ -926,6 +926,20 @@ err:
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
}
+static bool
+fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata)
+{
+ if (rdata->ids.roles == FC_PORT_ROLE_UNKNOWN)
+ return true;
+ if ((rdata->ids.roles & FC_PORT_ROLE_FCP_TARGET) &&
+ (lport->service_params & FCP_SPPF_INIT_FCN))
+ return true;
+ if ((rdata->ids.roles & FC_PORT_ROLE_FCP_INITIATOR) &&
+ (lport->service_params & FCP_SPPF_TARG_FCN))
+ return true;
+ return false;
+}
+
/**
* fc_rport_enter_plogi() - Send Port Login (PLOGI) request
* @rdata: The remote port to send a PLOGI to
@@ -938,6 +952,12 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
struct fc_lport *lport = rdata->local_port;
struct fc_frame *fp;
+ if (!fc_rport_compatible_roles(lport, rdata)) {
+ FC_RPORT_DBG(rdata, "PLOGI suppressed for incompatible role\n");
+ fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
+ return;
+ }
+
FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n",
fc_rport_state(rdata));
@@ -1646,6 +1666,13 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
rjt_data.explan = ELS_EXPL_NONE;
goto reject;
}
+ if (!fc_rport_compatible_roles(lport, rdata)) {
+ FC_RPORT_DBG(rdata, "Received PLOGI for incompatible role\n");
+ mutex_unlock(&rdata->rp_mutex);
+ rjt_data.reason = ELS_RJT_LOGIC;
+ rjt_data.explan = ELS_EXPL_NONE;
+ goto reject;
+ }
/*
* Get session payload size from incoming PLOGI.
@@ -1962,7 +1989,7 @@ static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len,
rdata->flags |= FC_RP_FLAGS_RETRY;
rdata->supported_classes = FC_COS_CLASS3;
- if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR))
+ if (!(lport->service_params & FCP_SPPF_INIT_FCN))
return 0;
spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 82c3fd4..ae69dfc 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -507,7 +507,6 @@ static void iscsi_free_task(struct iscsi_task *task)
kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*));
if (sc) {
- task->sc = NULL;
/* SCSI eh reuses commands to verify us */
sc->SCp.ptr = NULL;
/*
@@ -2809,6 +2808,9 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
kfree(session->targetname);
kfree(session->targetalias);
kfree(session->initiatorname);
+ kfree(session->boot_root);
+ kfree(session->boot_nic);
+ kfree(session->boot_target);
kfree(session->ifacename);
iscsi_destroy_session(cls_session);
@@ -3142,7 +3144,7 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
}
EXPORT_SYMBOL_GPL(iscsi_conn_bind);
-static int iscsi_switch_str_param(char **param, char *new_val_buf)
+int iscsi_switch_str_param(char **param, char *new_val_buf)
{
char *new_val;
@@ -3159,6 +3161,7 @@ static int iscsi_switch_str_param(char **param, char *new_val_buf)
*param = new_val;
return 0;
}
+EXPORT_SYMBOL_GPL(iscsi_switch_str_param);
int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
enum iscsi_param param, char *buf, int buflen)
@@ -3248,6 +3251,12 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
return iscsi_switch_str_param(&session->ifacename, buf);
case ISCSI_PARAM_INITIATOR_NAME:
return iscsi_switch_str_param(&session->initiatorname, buf);
+ case ISCSI_PARAM_BOOT_ROOT:
+ return iscsi_switch_str_param(&session->boot_root, buf);
+ case ISCSI_PARAM_BOOT_NIC:
+ return iscsi_switch_str_param(&session->boot_nic, buf);
+ case ISCSI_PARAM_BOOT_TARGET:
+ return iscsi_switch_str_param(&session->boot_target, buf);
default:
return -ENOSYS;
}
@@ -3326,6 +3335,15 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
case ISCSI_PARAM_INITIATOR_NAME:
len = sprintf(buf, "%s\n", session->initiatorname);
break;
+ case ISCSI_PARAM_BOOT_ROOT:
+ len = sprintf(buf, "%s\n", session->boot_root);
+ break;
+ case ISCSI_PARAM_BOOT_NIC:
+ len = sprintf(buf, "%s\n", session->boot_nic);
+ break;
+ case ISCSI_PARAM_BOOT_TARGET:
+ len = sprintf(buf, "%s\n", session->boot_target);
+ break;
default:
return -ENOSYS;
}
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 552e8a2..1d58d53 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -558,7 +558,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
if (!rc) {
iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
"Target has sent more R2Ts than it "
- "negotiated for or driver has has leaked.\n");
+ "negotiated for or driver has leaked.\n");
return ISCSI_ERR_PROTO;
}
@@ -906,7 +906,6 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
ISCSI_DBG_TCP(conn, "no more data avail. Consumed %d\n",
consumed);
*status = ISCSI_TCP_SKB_DONE;
- skb_abort_seq_read(&seq);
goto skb_done;
}
BUG_ON(segment->copied >= segment->size);
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index bdb81cd..161c98e 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -285,14 +285,14 @@ int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy)
if (phy->attached_tproto & SAS_PROTOCOL_STP)
dev->tproto = phy->attached_tproto;
if (phy->attached_sata_dev)
- dev->tproto |= SATA_DEV;
+ dev->tproto |= SAS_SATA_DEV;
- if (phy->attached_dev_type == SATA_PENDING)
- dev->dev_type = SATA_PENDING;
+ if (phy->attached_dev_type == SAS_SATA_PENDING)
+ dev->dev_type = SAS_SATA_PENDING;
else {
int res;
- dev->dev_type = SATA_DEV;
+ dev->dev_type = SAS_SATA_DEV;
res = sas_get_report_phy_sata(dev->parent, phy->phy_id,
&dev->sata_dev.rps_resp);
if (res) {
@@ -314,7 +314,7 @@ static int sas_ata_clear_pending(struct domain_device *dev, struct ex_phy *phy)
int res;
/* we weren't pending, so successfully end the reset sequence now */
- if (dev->dev_type != SATA_PENDING)
+ if (dev->dev_type != SAS_SATA_PENDING)
return 1;
/* hmmm, if this succeeds do we need to repost the domain_device to the
@@ -348,9 +348,9 @@ static int smp_ata_check_ready(struct ata_link *link)
return 0;
switch (ex_phy->attached_dev_type) {
- case SATA_PENDING:
+ case SAS_SATA_PENDING:
return 0;
- case SAS_END_DEV:
+ case SAS_END_DEVICE:
if (ex_phy->attached_sata_dev)
return sas_ata_clear_pending(dev, ex_phy);
default:
@@ -631,7 +631,7 @@ static void sas_get_ata_command_set(struct domain_device *dev)
struct dev_to_host_fis *fis =
(struct dev_to_host_fis *) dev->frame_rcvd;
- if (dev->dev_type == SATA_PENDING)
+ if (dev->dev_type == SAS_SATA_PENDING)
return;
if ((fis->sector_count == 1 && /* ATA */
@@ -797,7 +797,7 @@ int sas_discover_sata(struct domain_device *dev)
{
int res;
- if (dev->dev_type == SATA_PM)
+ if (dev->dev_type == SAS_SATA_PM)
return -ENODEV;
sas_get_ata_command_set(dev);
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index a0c3003..62b58d3 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -39,11 +39,11 @@
void sas_init_dev(struct domain_device *dev)
{
switch (dev->dev_type) {
- case SAS_END_DEV:
+ case SAS_END_DEVICE:
INIT_LIST_HEAD(&dev->ssp_dev.eh_list_node);
break;
- case EDGE_DEV:
- case FANOUT_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
INIT_LIST_HEAD(&dev->ex_dev.children);
mutex_init(&dev->ex_dev.cmd_mutex);
break;
@@ -93,9 +93,9 @@ static int sas_get_port_device(struct asd_sas_port *port)
if (fis->interrupt_reason == 1 && fis->lbal == 1 &&
fis->byte_count_low==0x69 && fis->byte_count_high == 0x96
&& (fis->device & ~0x10) == 0)
- dev->dev_type = SATA_PM;
+ dev->dev_type = SAS_SATA_PM;
else
- dev->dev_type = SATA_DEV;
+ dev->dev_type = SAS_SATA_DEV;
dev->tproto = SAS_PROTOCOL_SATA;
} else {
struct sas_identify_frame *id =
@@ -109,21 +109,21 @@ static int sas_get_port_device(struct asd_sas_port *port)
dev->port = port;
switch (dev->dev_type) {
- case SATA_DEV:
+ case SAS_SATA_DEV:
rc = sas_ata_init(dev);
if (rc) {
rphy = NULL;
break;
}
/* fall through */
- case SAS_END_DEV:
+ case SAS_END_DEVICE:
rphy = sas_end_device_alloc(port->port);
break;
- case EDGE_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
rphy = sas_expander_alloc(port->port,
SAS_EDGE_EXPANDER_DEVICE);
break;
- case FANOUT_DEV:
+ case SAS_FANOUT_EXPANDER_DEVICE:
rphy = sas_expander_alloc(port->port,
SAS_FANOUT_EXPANDER_DEVICE);
break;
@@ -156,7 +156,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
dev->rphy = rphy;
get_device(&dev->rphy->dev);
- if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
+ if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEVICE)
list_add_tail(&dev->disco_list_node, &port->disco_list);
else {
spin_lock_irq(&port->dev_list_lock);
@@ -315,7 +315,7 @@ void sas_free_device(struct kref *kref)
dev->phy = NULL;
/* remove the phys and ports, everything else should be gone */
- if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
+ if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
kfree(dev->ex_dev.ex_phy);
if (dev_is_sata(dev) && dev->sata_dev.ap) {
@@ -343,7 +343,7 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d
spin_unlock_irq(&port->dev_list_lock);
spin_lock_irq(&ha->lock);
- if (dev->dev_type == SAS_END_DEV &&
+ if (dev->dev_type == SAS_END_DEVICE &&
!list_empty(&dev->ssp_dev.eh_list_node)) {
list_del_init(&dev->ssp_dev.eh_list_node);
ha->eh_active--;
@@ -457,15 +457,15 @@ static void sas_discover_domain(struct work_struct *work)
task_pid_nr(current));
switch (dev->dev_type) {
- case SAS_END_DEV:
+ case SAS_END_DEVICE:
error = sas_discover_end_dev(dev);
break;
- case EDGE_DEV:
- case FANOUT_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
error = sas_discover_root_expander(dev);
break;
- case SATA_DEV:
- case SATA_PM:
+ case SAS_SATA_DEV:
+ case SAS_SATA_PM:
#ifdef CONFIG_SCSI_SAS_ATA
error = sas_discover_sata(dev);
break;
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index aec2e0d..446b851 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -183,21 +183,21 @@ static char sas_route_char(struct domain_device *dev, struct ex_phy *phy)
}
}
-static enum sas_dev_type to_dev_type(struct discover_resp *dr)
+static enum sas_device_type to_dev_type(struct discover_resp *dr)
{
/* This is detecting a failure to transmit initial dev to host
* FIS as described in section J.5 of sas-2 r16
*/
- if (dr->attached_dev_type == NO_DEVICE && dr->attached_sata_dev &&
+ if (dr->attached_dev_type == SAS_PHY_UNUSED && dr->attached_sata_dev &&
dr->linkrate >= SAS_LINK_RATE_1_5_GBPS)
- return SATA_PENDING;
+ return SAS_SATA_PENDING;
else
return dr->attached_dev_type;
}
static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
{
- enum sas_dev_type dev_type;
+ enum sas_device_type dev_type;
enum sas_linkrate linkrate;
u8 sas_addr[SAS_ADDR_SIZE];
struct smp_resp *resp = rsp;
@@ -235,6 +235,17 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
linkrate = phy->linkrate;
memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
+ /* Handle vacant phy - rest of dr data is not valid so skip it */
+ if (phy->phy_state == PHY_VACANT) {
+ memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+ phy->attached_dev_type = SAS_PHY_UNUSED;
+ if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
+ phy->phy_id = phy_id;
+ goto skip;
+ } else
+ goto out;
+ }
+
phy->attached_dev_type = to_dev_type(dr);
if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
goto out;
@@ -248,7 +259,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
/* help some expanders that fail to zero sas_address in the 'no
* device' case
*/
- if (phy->attached_dev_type == NO_DEVICE ||
+ if (phy->attached_dev_type == SAS_PHY_UNUSED ||
phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
else
@@ -272,6 +283,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
phy->phy->maximum_linkrate = dr->pmax_linkrate;
phy->phy->negotiated_linkrate = phy->linkrate;
+ skip:
if (new_phy)
if (sas_phy_add(phy->phy)) {
sas_phy_free(phy->phy);
@@ -280,13 +292,13 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
out:
switch (phy->attached_dev_type) {
- case SATA_PENDING:
+ case SAS_SATA_PENDING:
type = "stp pending";
break;
- case NO_DEVICE:
+ case SAS_PHY_UNUSED:
type = "no device";
break;
- case SAS_END_DEV:
+ case SAS_END_DEVICE:
if (phy->attached_iproto) {
if (phy->attached_tproto)
type = "host+target";
@@ -299,8 +311,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
type = "ssp";
}
break;
- case EDGE_DEV:
- case FANOUT_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
type = "smp";
break;
default:
@@ -388,7 +400,7 @@ int sas_ex_phy_discover(struct domain_device *dev, int single)
if (!disc_req)
return -ENOMEM;
- disc_resp = alloc_smp_req(DISCOVER_RESP_SIZE);
+ disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
if (!disc_resp) {
kfree(disc_req);
return -ENOMEM;
@@ -821,7 +833,7 @@ static struct domain_device *sas_ex_discover_end_dev(
} else
#endif
if (phy->attached_tproto & SAS_PROTOCOL_SSP) {
- child->dev_type = SAS_END_DEV;
+ child->dev_type = SAS_END_DEVICE;
rphy = sas_end_device_alloc(phy->port);
/* FIXME: error handling */
if (unlikely(!rphy))
@@ -920,11 +932,11 @@ static struct domain_device *sas_ex_discover_expander(
switch (phy->attached_dev_type) {
- case EDGE_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
rphy = sas_expander_alloc(phy->port,
SAS_EDGE_EXPANDER_DEVICE);
break;
- case FANOUT_DEV:
+ case SAS_FANOUT_EXPANDER_DEVICE:
rphy = sas_expander_alloc(phy->port,
SAS_FANOUT_EXPANDER_DEVICE);
break;
@@ -1001,7 +1013,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr))
sas_ex_disable_port(dev, ex_phy->attached_sas_addr);
- if (ex_phy->attached_dev_type == NO_DEVICE) {
+ if (ex_phy->attached_dev_type == SAS_PHY_UNUSED) {
if (ex_phy->routing_attr == DIRECT_ROUTING) {
memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
sas_configure_routing(dev, ex_phy->attached_sas_addr);
@@ -1010,10 +1022,10 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
} else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN)
return 0;
- if (ex_phy->attached_dev_type != SAS_END_DEV &&
- ex_phy->attached_dev_type != FANOUT_DEV &&
- ex_phy->attached_dev_type != EDGE_DEV &&
- ex_phy->attached_dev_type != SATA_PENDING) {
+ if (ex_phy->attached_dev_type != SAS_END_DEVICE &&
+ ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE &&
+ ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE &&
+ ex_phy->attached_dev_type != SAS_SATA_PENDING) {
SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx "
"phy 0x%x\n", ex_phy->attached_dev_type,
SAS_ADDR(dev->sas_addr),
@@ -1037,11 +1049,11 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
}
switch (ex_phy->attached_dev_type) {
- case SAS_END_DEV:
- case SATA_PENDING:
+ case SAS_END_DEVICE:
+ case SAS_SATA_PENDING:
child = sas_ex_discover_end_dev(dev, phy_id);
break;
- case FANOUT_DEV:
+ case SAS_FANOUT_EXPANDER_DEVICE:
if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) {
SAS_DPRINTK("second fanout expander %016llx phy 0x%x "
"attached to ex %016llx phy 0x%x\n",
@@ -1055,7 +1067,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
memcpy(dev->port->disc.fanout_sas_addr,
ex_phy->attached_sas_addr, SAS_ADDR_SIZE);
/* fallthrough */
- case EDGE_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
child = sas_ex_discover_expander(dev, phy_id);
break;
default:
@@ -1099,8 +1111,8 @@ static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr)
phy->phy_state == PHY_NOT_PRESENT)
continue;
- if ((phy->attached_dev_type == EDGE_DEV ||
- phy->attached_dev_type == FANOUT_DEV) &&
+ if ((phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) &&
phy->routing_attr == SUBTRACTIVE_ROUTING) {
memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE);
@@ -1118,8 +1130,8 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev)
u8 sub_addr[8] = {0, };
list_for_each_entry(child, &ex->children, siblings) {
- if (child->dev_type != EDGE_DEV &&
- child->dev_type != FANOUT_DEV)
+ if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE &&
+ child->dev_type != SAS_FANOUT_EXPANDER_DEVICE)
continue;
if (sub_addr[0] == 0) {
sas_find_sub_addr(child, sub_addr);
@@ -1196,7 +1208,7 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev)
int i;
u8 *sub_sas_addr = NULL;
- if (dev->dev_type != EDGE_DEV)
+ if (dev->dev_type != SAS_EDGE_EXPANDER_DEVICE)
return 0;
for (i = 0; i < ex->num_phys; i++) {
@@ -1206,8 +1218,8 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev)
phy->phy_state == PHY_NOT_PRESENT)
continue;
- if ((phy->attached_dev_type == FANOUT_DEV ||
- phy->attached_dev_type == EDGE_DEV) &&
+ if ((phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE ||
+ phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE) &&
phy->routing_attr == SUBTRACTIVE_ROUTING) {
if (!sub_sas_addr)
@@ -1233,8 +1245,8 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
struct ex_phy *child_phy)
{
static const char *ex_type[] = {
- [EDGE_DEV] = "edge",
- [FANOUT_DEV] = "fanout",
+ [SAS_EDGE_EXPANDER_DEVICE] = "edge",
+ [SAS_FANOUT_EXPANDER_DEVICE] = "fanout",
};
struct domain_device *parent = child->parent;
@@ -1309,8 +1321,8 @@ static int sas_check_parent_topology(struct domain_device *child)
if (!child->parent)
return 0;
- if (child->parent->dev_type != EDGE_DEV &&
- child->parent->dev_type != FANOUT_DEV)
+ if (child->parent->dev_type != SAS_EDGE_EXPANDER_DEVICE &&
+ child->parent->dev_type != SAS_FANOUT_EXPANDER_DEVICE)
return 0;
parent_ex = &child->parent->ex_dev;
@@ -1329,8 +1341,8 @@ static int sas_check_parent_topology(struct domain_device *child)
child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id];
switch (child->parent->dev_type) {
- case EDGE_DEV:
- if (child->dev_type == FANOUT_DEV) {
+ case SAS_EDGE_EXPANDER_DEVICE:
+ if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING ||
child_phy->routing_attr != TABLE_ROUTING) {
sas_print_parent_topology_bug(child, parent_phy, child_phy);
@@ -1354,7 +1366,7 @@ static int sas_check_parent_topology(struct domain_device *child)
}
}
break;
- case FANOUT_DEV:
+ case SAS_FANOUT_EXPANDER_DEVICE:
if (parent_phy->routing_attr != TABLE_ROUTING ||
child_phy->routing_attr != SUBTRACTIVE_ROUTING) {
sas_print_parent_topology_bug(child, parent_phy, child_phy);
@@ -1607,8 +1619,8 @@ static int sas_ex_level_discovery(struct asd_sas_port *port, const int level)
struct domain_device *dev;
list_for_each_entry(dev, &port->dev_list, dev_list_node) {
- if (dev->dev_type == EDGE_DEV ||
- dev->dev_type == FANOUT_DEV) {
+ if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
struct sas_expander_device *ex =
rphy_to_expander_device(dev->rphy);
@@ -1708,7 +1720,7 @@ static int sas_get_phy_change_count(struct domain_device *dev,
}
static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
- u8 *sas_addr, enum sas_dev_type *type)
+ u8 *sas_addr, enum sas_device_type *type)
{
int res;
struct smp_resp *disc_resp;
@@ -1837,7 +1849,7 @@ static int sas_find_bcast_dev(struct domain_device *dev,
SAS_DPRINTK("Expander phys DID NOT change\n");
}
list_for_each_entry(ch, &ex->children, siblings) {
- if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) {
+ if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
res = sas_find_bcast_dev(ch, src_dev);
if (*src_dev)
return res;
@@ -1854,8 +1866,8 @@ static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_devi
list_for_each_entry_safe(child, n, &ex->children, siblings) {
set_bit(SAS_DEV_GONE, &child->state);
- if (child->dev_type == EDGE_DEV ||
- child->dev_type == FANOUT_DEV)
+ if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ child->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
sas_unregister_ex_tree(port, child);
else
sas_unregister_dev(port, child);
@@ -1875,8 +1887,8 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
if (SAS_ADDR(child->sas_addr) ==
SAS_ADDR(phy->attached_sas_addr)) {
set_bit(SAS_DEV_GONE, &child->state);
- if (child->dev_type == EDGE_DEV ||
- child->dev_type == FANOUT_DEV)
+ if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ child->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
sas_unregister_ex_tree(parent->port, child);
else
sas_unregister_dev(parent->port, child);
@@ -1904,8 +1916,8 @@ static int sas_discover_bfs_by_root_level(struct domain_device *root,
int res = 0;
list_for_each_entry(child, &ex_root->children, siblings) {
- if (child->dev_type == EDGE_DEV ||
- child->dev_type == FANOUT_DEV) {
+ if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
struct sas_expander_device *ex =
rphy_to_expander_device(child->rphy);
@@ -1958,8 +1970,8 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
list_for_each_entry(child, &dev->ex_dev.children, siblings) {
if (SAS_ADDR(child->sas_addr) ==
SAS_ADDR(ex_phy->attached_sas_addr)) {
- if (child->dev_type == EDGE_DEV ||
- child->dev_type == FANOUT_DEV)
+ if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ child->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
res = sas_discover_bfs_by_root(child);
break;
}
@@ -1967,16 +1979,16 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
return res;
}
-static bool dev_type_flutter(enum sas_dev_type new, enum sas_dev_type old)
+static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old)
{
if (old == new)
return true;
/* treat device directed resets as flutter, if we went
- * SAS_END_DEV to SATA_PENDING the link needs recovery
+ * SAS_END_DEVICE to SAS_SATA_PENDING the link needs recovery
*/
- if ((old == SATA_PENDING && new == SAS_END_DEV) ||
- (old == SAS_END_DEV && new == SATA_PENDING))
+ if ((old == SAS_SATA_PENDING && new == SAS_END_DEVICE) ||
+ (old == SAS_END_DEVICE && new == SAS_SATA_PENDING))
return true;
return false;
@@ -1986,7 +1998,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
{
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *phy = &ex->ex_phy[phy_id];
- enum sas_dev_type type = NO_DEVICE;
+ enum sas_device_type type = SAS_PHY_UNUSED;
u8 sas_addr[8];
int res;
@@ -2020,7 +2032,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
sas_ex_phy_discover(dev, phy_id);
- if (ata_dev && phy->attached_dev_type == SATA_PENDING)
+ if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
action = ", needs recovery";
SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n",
SAS_ADDR(dev->sas_addr), phy_id, action);
@@ -2151,10 +2163,10 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
}
/* do we need to support multiple segments? */
- if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
+ if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) {
printk("%s: multiple segments req %u %u, rsp %u %u\n",
- __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
- rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
+ __func__, bio_segments(req->bio), blk_rq_bytes(req),
+ bio_segments(rsp->bio), blk_rq_bytes(rsp));
return -EINVAL;
}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 1de6796..7e7ba83 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -131,16 +131,16 @@ static inline void sas_fill_in_rphy(struct domain_device *dev,
rphy->identify.initiator_port_protocols = dev->iproto;
rphy->identify.target_port_protocols = dev->tproto;
switch (dev->dev_type) {
- case SATA_DEV:
+ case SAS_SATA_DEV:
/* FIXME: need sata device type */
- case SAS_END_DEV:
- case SATA_PENDING:
+ case SAS_END_DEVICE:
+ case SAS_SATA_PENDING:
rphy->identify.device_type = SAS_END_DEVICE;
break;
- case EDGE_DEV:
+ case SAS_EDGE_EXPANDER_DEVICE:
rphy->identify.device_type = SAS_EDGE_EXPANDER_DEVICE;
break;
- case FANOUT_DEV:
+ case SAS_FANOUT_EXPANDER_DEVICE:
rphy->identify.device_type = SAS_FANOUT_EXPANDER_DEVICE;
break;
default:
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 1398b71..d3c5297 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -69,7 +69,7 @@ static void sas_resume_port(struct asd_sas_phy *phy)
continue;
}
- if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) {
+ if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
dev->ex_dev.ex_change_count = -1;
for (i = 0; i < dev->ex_dev.num_phys; i++) {
struct ex_phy *phy = &dev->ex_dev.ex_phy[i];
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 6e795a1..da3aee1 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -167,7 +167,7 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
int_to_scsilun(cmd->device->lun, &lun);
memcpy(task->ssp_task.LUN, &lun.scsi_lun, 8);
task->ssp_task.task_attr = TASK_ATTR_SIMPLE;
- memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
+ task->ssp_task.cmd = cmd;
task->scatter = scsi_sglist(cmd);
task->num_scatter = scsi_sg_count(cmd);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index df4c13a..93f222d 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -46,10 +46,15 @@ struct lpfc_sli2_slim;
#define LPFC_DEFAULT_MENLO_SG_SEG_CNT 128 /* sg element count per scsi
cmnd for menlo needs nearly twice as for firmware
downloads using bsg */
-#define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */
+
+#define LPFC_MIN_SG_SLI4_BUF_SZ 0x800 /* based on LPFC_DEFAULT_SG_SEG_CNT */
+#define LPFC_MAX_SG_SLI4_SEG_CNT_DIF 128 /* sg element count per scsi cmnd */
+#define LPFC_MAX_SG_SEG_CNT_DIF 512 /* sg element count per scsi cmnd */
#define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */
+#define LPFC_MAX_SGL_SEG_CNT 512 /* SGL element count per scsi cmnd */
+#define LPFC_MAX_BPL_SEG_CNT 4096 /* BPL element count per scsi cmnd */
+
#define LPFC_MAX_SGE_SIZE 0x80000000 /* Maximum data allowed in a SGE */
-#define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
#define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */
#define LPFC_VNAME_LEN 100 /* vport symbolic name length */
@@ -66,8 +71,10 @@ struct lpfc_sli2_slim;
* queue depths when there are driver resource error or Firmware
* resource error.
*/
-#define QUEUE_RAMP_DOWN_INTERVAL (1 * HZ) /* 1 Second */
-#define QUEUE_RAMP_UP_INTERVAL (300 * HZ) /* 5 minutes */
+/* 1 Second */
+#define QUEUE_RAMP_DOWN_INTERVAL (msecs_to_jiffies(1000 * 1))
+/* 5 minutes */
+#define QUEUE_RAMP_UP_INTERVAL (msecs_to_jiffies(1000 * 300))
/* Number of exchanges reserved for discovery to complete */
#define LPFC_DISC_IOCB_BUFF_COUNT 20
@@ -466,11 +473,13 @@ enum intr_type_t {
MSIX,
};
+#define LPFC_CT_CTX_MAX 64
struct unsol_rcv_ct_ctx {
uint32_t ctxt_id;
uint32_t SID;
- uint32_t flags;
-#define UNSOL_VALID 0x00000001
+ uint32_t valid;
+#define UNSOL_INVALID 0
+#define UNSOL_VALID 1
uint16_t oxid;
uint16_t rxid;
};
@@ -669,6 +678,7 @@ struct lpfc_hba {
uint32_t lmt;
uint32_t fc_topology; /* link topology, from LINK INIT */
+ uint32_t fc_topology_changed; /* link topology, from LINK INIT */
struct lpfc_stats fc_stat;
@@ -699,9 +709,11 @@ struct lpfc_hba {
uint32_t cfg_poll_tmo;
uint32_t cfg_use_msi;
uint32_t cfg_fcp_imax;
+ uint32_t cfg_fcp_cpu_map;
uint32_t cfg_fcp_wq_count;
uint32_t cfg_fcp_eq_count;
uint32_t cfg_fcp_io_channel;
+ uint32_t cfg_total_seg_cnt;
uint32_t cfg_sg_seg_cnt;
uint32_t cfg_prot_sg_seg_cnt;
uint32_t cfg_sg_dma_buf_size;
@@ -750,6 +762,15 @@ struct lpfc_hba {
void __iomem *ctrl_regs_memmap_p;/* Kernel memory mapped address for
PCI BAR2 */
+ void __iomem *pci_bar0_memmap_p; /* Kernel memory mapped address for
+ PCI BAR0 with dual-ULP support */
+ void __iomem *pci_bar2_memmap_p; /* Kernel memory mapped address for
+ PCI BAR2 with dual-ULP support */
+ void __iomem *pci_bar4_memmap_p; /* Kernel memory mapped address for
+ PCI BAR4 with dual-ULP support */
+#define PCI_64BIT_BAR0 0
+#define PCI_64BIT_BAR2 2
+#define PCI_64BIT_BAR4 4
void __iomem *MBslimaddr; /* virtual address for mbox cmds */
void __iomem *HAregaddr; /* virtual address for host attn reg */
void __iomem *CAregaddr; /* virtual address for chip attn reg */
@@ -793,8 +814,10 @@ struct lpfc_hba {
uint64_t bg_reftag_err_cnt;
/* fastpath list. */
- spinlock_t scsi_buf_list_lock;
- struct list_head lpfc_scsi_buf_list;
+ spinlock_t scsi_buf_list_get_lock; /* SCSI buf alloc list lock */
+ spinlock_t scsi_buf_list_put_lock; /* SCSI buf free list lock */
+ struct list_head lpfc_scsi_buf_list_get;
+ struct list_head lpfc_scsi_buf_list_put;
uint32_t total_scsi_bufs;
struct list_head lpfc_iocb_list;
uint32_t total_iocbq_bufs;
@@ -938,7 +961,7 @@ struct lpfc_hba {
spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */
struct list_head ct_ev_waiters;
- struct unsol_rcv_ct_ctx ct_ctx[64];
+ struct unsol_rcv_ct_ctx ct_ctx[LPFC_CT_CTX_MAX];
uint32_t ctx_idx;
uint8_t menlo_flag; /* menlo generic flags */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index a364cae..5cb08ae 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -674,6 +674,9 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
int i;
int rc;
+ if (phba->pport->fc_flag & FC_OFFLINE_MODE)
+ return 0;
+
init_completion(&online_compl);
rc = lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_OFFLINE_PREP);
@@ -692,7 +695,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
*/
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
- while (pring->txcmplq_cnt) {
+ while (!list_empty(&pring->txcmplq)) {
msleep(10);
if (cnt++ > 500) { /* 5 secs */
lpfc_printf_log(phba,
@@ -741,7 +744,8 @@ lpfc_selective_reset(struct lpfc_hba *phba)
int status = 0;
int rc;
- if (!phba->cfg_enable_hba_reset)
+ if ((!phba->cfg_enable_hba_reset) ||
+ (phba->pport->fc_flag & FC_OFFLINE_MODE))
return -EACCES;
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -895,6 +899,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
pci_disable_sriov(pdev);
phba->cfg_sriov_nr_virtfn = 0;
}
+
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
if (status != 0)
@@ -2302,11 +2307,17 @@ static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
"FCF Fast failover=1 Priority failover=2");
-int lpfc_enable_rrq;
+int lpfc_enable_rrq = 2;
module_param(lpfc_enable_rrq, int, S_IRUGO);
MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
lpfc_param_show(enable_rrq);
-lpfc_param_init(enable_rrq, 0, 0, 1);
+/*
+# lpfc_enable_rrq: Track XRI/OXID reuse after IO failures
+# 0x0 = disabled, XRI/OXID use not tracked.
+# 0x1 = XRI/OXID reuse is timed with ratov, RRQ sent.
+# 0x2 = XRI/OXID reuse is timed with ratov, No RRQ sent.
+*/
+lpfc_param_init(enable_rrq, 2, 0, 2);
static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL);
/*
@@ -2795,6 +2806,8 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"3054 lpfc_topology changed from %d to %d\n",
prev_val, val);
+ if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4)
+ phba->fc_topology_changed = 1;
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
if (err) {
phba->cfg_topology = prev_val;
@@ -3786,6 +3799,141 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR,
lpfc_fcp_imax_show, lpfc_fcp_imax_store);
+/**
+ * lpfc_state_show - Display current driver CPU affinity
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains text describing the state of the link.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_vector_map_info *cpup;
+ int idx, len = 0;
+
+ if ((phba->sli_rev != LPFC_SLI_REV4) ||
+ (phba->intr_type != MSIX))
+ return len;
+
+ switch (phba->cfg_fcp_cpu_map) {
+ case 0:
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "fcp_cpu_map: No mapping (%d)\n",
+ phba->cfg_fcp_cpu_map);
+ return len;
+ case 1:
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "fcp_cpu_map: HBA centric mapping (%d): "
+ "%d online CPUs\n",
+ phba->cfg_fcp_cpu_map,
+ phba->sli4_hba.num_online_cpu);
+ break;
+ case 2:
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "fcp_cpu_map: Driver centric mapping (%d): "
+ "%d online CPUs\n",
+ phba->cfg_fcp_cpu_map,
+ phba->sli4_hba.num_online_cpu);
+ break;
+ }
+
+ cpup = phba->sli4_hba.cpu_map;
+ for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
+ if (cpup->irq == LPFC_VECTOR_MAP_EMPTY)
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "CPU %02d io_chan %02d "
+ "physid %d coreid %d\n",
+ idx, cpup->channel_id, cpup->phys_id,
+ cpup->core_id);
+ else
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "CPU %02d io_chan %02d "
+ "physid %d coreid %d IRQ %d\n",
+ idx, cpup->channel_id, cpup->phys_id,
+ cpup->core_id, cpup->irq);
+
+ cpup++;
+ }
+ return len;
+}
+
+/**
+ * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: one or more lpfc_polling_flags values.
+ * @count: not used.
+ *
+ * Returns:
+ * -EINVAL - Not implemented yet.
+ **/
+static ssize_t
+lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int status = -EINVAL;
+ return status;
+}
+
+/*
+# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors
+# for the HBA.
+#
+# Value range is [0 to 2]. Default value is LPFC_DRIVER_CPU_MAP (2).
+# 0 - Do not affinitze IRQ vectors
+# 1 - Affintize HBA vectors with respect to each HBA
+# (start with CPU0 for each HBA)
+# 2 - Affintize HBA vectors with respect to the entire driver
+# (round robin thru all CPUs across all HBAs)
+*/
+static int lpfc_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
+module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(lpfc_fcp_cpu_map,
+ "Defines how to map CPUs to IRQ vectors per HBA");
+
+/**
+ * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable
+ * @phba: lpfc_hba pointer.
+ * @val: link speed value.
+ *
+ * Description:
+ * If val is in a valid range [0-2], then affinitze the adapter's
+ * MSIX vectors.
+ *
+ * Returns:
+ * zero if val saved.
+ * -EINVAL val out of range
+ **/
+static int
+lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val)
+{
+ if (phba->sli_rev != LPFC_SLI_REV4) {
+ phba->cfg_fcp_cpu_map = 0;
+ return 0;
+ }
+
+ if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) {
+ phba->cfg_fcp_cpu_map = val;
+ return 0;
+ }
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3326 fcp_cpu_map: %d out of range, using default\n",
+ val);
+ phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
+
+ return 0;
+}
+
+static DEVICE_ATTR(lpfc_fcp_cpu_map, S_IRUGO | S_IWUSR,
+ lpfc_fcp_cpu_map_show, lpfc_fcp_cpu_map_store);
+
/*
# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
# Value range is [2,3]. Default value is 3.
@@ -3922,11 +4070,28 @@ LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
"during discovery");
/*
-# lpfc_max_luns: maximum allowed LUN.
+# lpfc_max_luns: maximum allowed LUN ID. This is the highest LUN ID that
+# will be scanned by the SCSI midlayer when sequential scanning is
+# used; and is also the highest LUN ID allowed when the SCSI midlayer
+# parses REPORT_LUN responses. The lpfc driver has no LUN count or
+# LUN ID limit, but the SCSI midlayer requires this field for the uses
+# above. The lpfc driver limits the default value to 255 for two reasons.
+# As it bounds the sequential scan loop, scanning for thousands of luns
+# on a target can take minutes of wall clock time. Additionally,
+# there are FC targets, such as JBODs, that only recognize 8-bits of
+# LUN ID. When they receive a value greater than 8 bits, they chop off
+# the high order bits. In other words, they see LUN IDs 0, 256, 512,
+# and so on all as LUN ID 0. This causes the linux kernel, which sees
+# valid responses at each of the LUN IDs, to believe there are multiple
+# devices present, when in fact, there is only 1.
+# A customer that is aware of their target behaviors, and the results as
+# indicated above, is welcome to increase the lpfc_max_luns value.
+# As mentioned, this value is not used by the lpfc driver, only the
+# SCSI midlayer.
# Value range is [0,65535]. Default value is 255.
# NOTE: The SCSI layer might probe all allowed LUN on some old targets.
*/
-LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN");
+LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID");
/*
# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
@@ -4003,12 +4168,11 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
# 0 = disabled (default)
# 1 = enabled
# Value range is [0,1]. Default value is 0.
+#
+# This feature in under investigation and may be supported in the future.
*/
unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF;
-module_param(lpfc_fcp_look_ahead, uint, S_IRUGO);
-MODULE_PARM_DESC(lpfc_fcp_look_ahead, "Look ahead for completions");
-
/*
# lpfc_prot_mask: i
# - Bit mask of host protection capabilities used to register with the
@@ -4065,16 +4229,23 @@ MODULE_PARM_DESC(lpfc_delay_discovery,
/*
* lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
- * This value can be set to values between 64 and 256. The default value is
+ * This value can be set to values between 64 and 4096. The default value is
* 64, but may be increased to allow for larger Max I/O sizes. The scsi layer
* will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE).
+ * Because of the additional overhead involved in setting up T10-DIF,
+ * this parameter will be limited to 128 if BlockGuard is enabled under SLI4
+ * and will be limited to 512 if BlockGuard is enabled under SLI3.
*/
LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,
LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count");
-LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_PROT_SG_SEG_CNT,
- LPFC_DEFAULT_PROT_SG_SEG_CNT, LPFC_MAX_PROT_SG_SEG_CNT,
- "Max Protection Scatter Gather Segment Count");
+/*
+ * This parameter will be depricated, the driver cannot limit the
+ * protection data s/g list.
+ */
+LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT,
+ LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT,
+ "Max Protection Scatter Gather Segment Count");
struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_bg_info,
@@ -4135,6 +4306,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_poll_tmo,
&dev_attr_lpfc_use_msi,
&dev_attr_lpfc_fcp_imax,
+ &dev_attr_lpfc_fcp_cpu_map,
&dev_attr_lpfc_fcp_wq_count,
&dev_attr_lpfc_fcp_eq_count,
&dev_attr_lpfc_fcp_io_channel,
@@ -5117,6 +5289,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
lpfc_use_msi_init(phba, lpfc_use_msi);
lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
+ lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count);
lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index f7368eb..6630520 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2009-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2009-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -64,18 +64,14 @@ struct lpfc_bsg_event {
struct list_head events_to_get;
struct list_head events_to_see;
- /* job waiting for this event to finish */
- struct fc_bsg_job *set_job;
+ /* driver data associated with the job */
+ void *dd_data;
};
struct lpfc_bsg_iocb {
struct lpfc_iocbq *cmdiocbq;
- struct lpfc_iocbq *rspiocbq;
- struct lpfc_dmabuf *bmp;
+ struct lpfc_dmabuf *rmp;
struct lpfc_nodelist *ndlp;
-
- /* job waiting for this iocb to finish */
- struct fc_bsg_job *set_job;
};
struct lpfc_bsg_mbox {
@@ -86,20 +82,13 @@ struct lpfc_bsg_mbox {
uint32_t mbOffset; /* from app */
uint32_t inExtWLen; /* from app */
uint32_t outExtWLen; /* from app */
-
- /* job waiting for this mbox command to finish */
- struct fc_bsg_job *set_job;
};
#define MENLO_DID 0x0000FC0E
struct lpfc_bsg_menlo {
struct lpfc_iocbq *cmdiocbq;
- struct lpfc_iocbq *rspiocbq;
- struct lpfc_dmabuf *bmp;
-
- /* job waiting for this iocb to finish */
- struct fc_bsg_job *set_job;
+ struct lpfc_dmabuf *rmp;
};
#define TYPE_EVT 1
@@ -108,6 +97,7 @@ struct lpfc_bsg_menlo {
#define TYPE_MENLO 4
struct bsg_job_data {
uint32_t type;
+ struct fc_bsg_job *set_job; /* job waiting for this iocb to finish */
union {
struct lpfc_bsg_event *evt;
struct lpfc_bsg_iocb iocb;
@@ -141,6 +131,149 @@ struct lpfc_dmabufext {
uint32_t flag;
};
+static void
+lpfc_free_bsg_buffers(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
+{
+ struct lpfc_dmabuf *mlast, *next_mlast;
+
+ if (mlist) {
+ list_for_each_entry_safe(mlast, next_mlast, &mlist->list,
+ list) {
+ lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
+ list_del(&mlast->list);
+ kfree(mlast);
+ }
+ lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
+ kfree(mlist);
+ }
+ return;
+}
+
+static struct lpfc_dmabuf *
+lpfc_alloc_bsg_buffers(struct lpfc_hba *phba, unsigned int size,
+ int outbound_buffers, struct ulp_bde64 *bpl,
+ int *bpl_entries)
+{
+ struct lpfc_dmabuf *mlist = NULL;
+ struct lpfc_dmabuf *mp;
+ unsigned int bytes_left = size;
+
+ /* Verify we can support the size specified */
+ if (!size || (size > (*bpl_entries * LPFC_BPL_SIZE)))
+ return NULL;
+
+ /* Determine the number of dma buffers to allocate */
+ *bpl_entries = (size % LPFC_BPL_SIZE ? size/LPFC_BPL_SIZE + 1 :
+ size/LPFC_BPL_SIZE);
+
+ /* Allocate dma buffer and place in BPL passed */
+ while (bytes_left) {
+ /* Allocate dma buffer */
+ mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+ if (!mp) {
+ if (mlist)
+ lpfc_free_bsg_buffers(phba, mlist);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&mp->list);
+ mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
+
+ if (!mp->virt) {
+ kfree(mp);
+ if (mlist)
+ lpfc_free_bsg_buffers(phba, mlist);
+ return NULL;
+ }
+
+ /* Queue it to a linked list */
+ if (!mlist)
+ mlist = mp;
+ else
+ list_add_tail(&mp->list, &mlist->list);
+
+ /* Add buffer to buffer pointer list */
+ if (outbound_buffers)
+ bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ else
+ bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
+ bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
+ bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
+ bpl->tus.f.bdeSize = (uint16_t)
+ (bytes_left >= LPFC_BPL_SIZE ? LPFC_BPL_SIZE :
+ bytes_left);
+ bytes_left -= bpl->tus.f.bdeSize;
+ bpl->tus.w = le32_to_cpu(bpl->tus.w);
+ bpl++;
+ }
+ return mlist;
+}
+
+static unsigned int
+lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers,
+ struct fc_bsg_buffer *bsg_buffers,
+ unsigned int bytes_to_transfer, int to_buffers)
+{
+
+ struct lpfc_dmabuf *mp;
+ unsigned int transfer_bytes, bytes_copied = 0;
+ unsigned int sg_offset, dma_offset;
+ unsigned char *dma_address, *sg_address;
+ LIST_HEAD(temp_list);
+ struct sg_mapping_iter miter;
+ unsigned long flags;
+ unsigned int sg_flags = SG_MITER_ATOMIC;
+ bool sg_valid;
+
+ list_splice_init(&dma_buffers->list, &temp_list);
+ list_add(&dma_buffers->list, &temp_list);
+ sg_offset = 0;
+ if (to_buffers)
+ sg_flags |= SG_MITER_FROM_SG;
+ else
+ sg_flags |= SG_MITER_TO_SG;
+ sg_miter_start(&miter, bsg_buffers->sg_list, bsg_buffers->sg_cnt,
+ sg_flags);
+ local_irq_save(flags);
+ sg_valid = sg_miter_next(&miter);
+ list_for_each_entry(mp, &temp_list, list) {
+ dma_offset = 0;
+ while (bytes_to_transfer && sg_valid &&
+ (dma_offset < LPFC_BPL_SIZE)) {
+ dma_address = mp->virt + dma_offset;
+ if (sg_offset) {
+ /* Continue previous partial transfer of sg */
+ sg_address = miter.addr + sg_offset;
+ transfer_bytes = miter.length - sg_offset;
+ } else {
+ sg_address = miter.addr;
+ transfer_bytes = miter.length;
+ }
+ if (bytes_to_transfer < transfer_bytes)
+ transfer_bytes = bytes_to_transfer;
+ if (transfer_bytes > (LPFC_BPL_SIZE - dma_offset))
+ transfer_bytes = LPFC_BPL_SIZE - dma_offset;
+ if (to_buffers)
+ memcpy(dma_address, sg_address, transfer_bytes);
+ else
+ memcpy(sg_address, dma_address, transfer_bytes);
+ dma_offset += transfer_bytes;
+ sg_offset += transfer_bytes;
+ bytes_to_transfer -= transfer_bytes;
+ bytes_copied += transfer_bytes;
+ if (sg_offset >= miter.length) {
+ sg_offset = 0;
+ sg_valid = sg_miter_next(&miter);
+ }
+ }
+ }
+ sg_miter_stop(&miter);
+ local_irq_restore(flags);
+ list_del_init(&dma_buffers->list);
+ list_splice(&temp_list, &dma_buffers->list);
+ return bytes_copied;
+}
+
/**
* lpfc_bsg_send_mgmt_cmd_cmp - lpfc_bsg_send_mgmt_cmd's completion handler
* @phba: Pointer to HBA context object.
@@ -166,62 +299,72 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
struct bsg_job_data *dd_data;
struct fc_bsg_job *job;
IOCB_t *rsp;
- struct lpfc_dmabuf *bmp;
+ struct lpfc_dmabuf *bmp, *cmp, *rmp;
struct lpfc_nodelist *ndlp;
struct lpfc_bsg_iocb *iocb;
unsigned long flags;
+ unsigned int rsp_size;
int rc = 0;
+ dd_data = cmdiocbq->context1;
+
+ /* Determine if job has been aborted */
spin_lock_irqsave(&phba->ct_ev_lock, flags);
- dd_data = cmdiocbq->context2;
- if (!dd_data) {
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- lpfc_sli_release_iocbq(phba, cmdiocbq);
- return;
+ job = dd_data->set_job;
+ if (job) {
+ /* Prevent timeout handling from trying to abort job */
+ job->dd_data = NULL;
}
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
iocb = &dd_data->context_un.iocb;
- job = iocb->set_job;
- job->dd_data = NULL; /* so timeout handler does not reply */
-
- bmp = iocb->bmp;
+ ndlp = iocb->ndlp;
+ rmp = iocb->rmp;
+ cmp = cmdiocbq->context2;
+ bmp = cmdiocbq->context3;
rsp = &rspiocbq->iocb;
- ndlp = cmdiocbq->context1;
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ /* Copy the completed data or set the error status */
- if (rsp->ulpStatus) {
- if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
- switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
- case IOERR_SEQUENCE_TIMEOUT:
- rc = -ETIMEDOUT;
- break;
- case IOERR_INVALID_RPI:
- rc = -EFAULT;
- break;
- default:
+ if (job) {
+ if (rsp->ulpStatus) {
+ if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+ switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
+ case IOERR_SEQUENCE_TIMEOUT:
+ rc = -ETIMEDOUT;
+ break;
+ case IOERR_INVALID_RPI:
+ rc = -EFAULT;
+ break;
+ default:
+ rc = -EACCES;
+ break;
+ }
+ } else {
rc = -EACCES;
- break;
}
- } else
- rc = -EACCES;
- } else
- job->reply->reply_payload_rcv_len =
- rsp->un.genreq64.bdl.bdeSize;
+ } else {
+ rsp_size = rsp->un.genreq64.bdl.bdeSize;
+ job->reply->reply_payload_rcv_len =
+ lpfc_bsg_copy_data(rmp, &job->reply_payload,
+ rsp_size, 0);
+ }
+ }
+ lpfc_free_bsg_buffers(phba, cmp);
+ lpfc_free_bsg_buffers(phba, rmp);
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
+ kfree(bmp);
lpfc_sli_release_iocbq(phba, cmdiocbq);
lpfc_nlp_put(ndlp);
- kfree(bmp);
kfree(dd_data);
- /* make error code available to userspace */
- job->reply->result = rc;
- /* complete the job back to userspace */
- job->job_done(job);
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+
+ /* Complete the job if the job is still active */
+
+ if (job) {
+ job->reply->result = rc;
+ job->job_done(job);
+ }
return;
}
@@ -240,12 +383,9 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
uint32_t timeout;
struct lpfc_iocbq *cmdiocbq = NULL;
IOCB_t *cmd;
- struct lpfc_dmabuf *bmp = NULL;
+ struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
int request_nseg;
int reply_nseg;
- struct scatterlist *sgel = NULL;
- int numbde;
- dma_addr_t busaddr;
struct bsg_job_data *dd_data;
uint32_t creg_val;
int rc = 0;
@@ -268,54 +408,50 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
goto no_ndlp;
}
- bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
- if (!bmp) {
- rc = -ENOMEM;
- goto free_ndlp;
- }
-
if (ndlp->nlp_flag & NLP_ELS_SND_MASK) {
rc = -ENODEV;
- goto free_bmp;
+ goto free_ndlp;
}
cmdiocbq = lpfc_sli_get_iocbq(phba);
if (!cmdiocbq) {
rc = -ENOMEM;
- goto free_bmp;
+ goto free_ndlp;
}
cmd = &cmdiocbq->iocb;
+
+ bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+ if (!bmp) {
+ rc = -ENOMEM;
+ goto free_cmdiocbq;
+ }
bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
if (!bmp->virt) {
rc = -ENOMEM;
- goto free_cmdiocbq;
+ goto free_bmp;
}
INIT_LIST_HEAD(&bmp->list);
+
bpl = (struct ulp_bde64 *) bmp->virt;
- request_nseg = pci_map_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- for_each_sg(job->request_payload.sg_list, sgel, request_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
+ request_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64);
+ cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
+ 1, bpl, &request_nseg);
+ if (!cmp) {
+ rc = -ENOMEM;
+ goto free_bmp;
}
+ lpfc_bsg_copy_data(cmp, &job->request_payload,
+ job->request_payload.payload_len, 1);
- reply_nseg = pci_map_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
- for_each_sg(job->reply_payload.sg_list, sgel, reply_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
+ bpl += request_nseg;
+ reply_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64) - request_nseg;
+ rmp = lpfc_alloc_bsg_buffers(phba, job->reply_payload.payload_len, 0,
+ bpl, &reply_nseg);
+ if (!rmp) {
+ rc = -ENOMEM;
+ goto free_cmp;
}
cmd->un.genreq64.bdl.ulpIoTag32 = 0;
@@ -343,17 +479,21 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
cmd->ulpTimeout = timeout;
cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
- cmdiocbq->context1 = ndlp;
- cmdiocbq->context2 = dd_data;
+ cmdiocbq->context1 = dd_data;
+ cmdiocbq->context2 = cmp;
+ cmdiocbq->context3 = bmp;
+ cmdiocbq->context_un.ndlp = ndlp;
dd_data->type = TYPE_IOCB;
+ dd_data->set_job = job;
dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
- dd_data->context_un.iocb.set_job = job;
- dd_data->context_un.iocb.bmp = bmp;
+ dd_data->context_un.iocb.ndlp = ndlp;
+ dd_data->context_un.iocb.rmp = rmp;
+ job->dd_data = dd_data;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
rc = -EIO ;
- goto free_cmdiocbq;
+ goto free_rmp;
}
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
@@ -368,19 +508,18 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
else
rc = -EIO;
-
/* iocb failed so cleanup */
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
-
- lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-free_cmdiocbq:
- lpfc_sli_release_iocbq(phba, cmdiocbq);
+free_rmp:
+ lpfc_free_bsg_buffers(phba, rmp);
+free_cmp:
+ lpfc_free_bsg_buffers(phba, cmp);
free_bmp:
+ if (bmp->virt)
+ lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(bmp);
+free_cmdiocbq:
+ lpfc_sli_release_iocbq(phba, cmdiocbq);
free_ndlp:
lpfc_nlp_put(ndlp);
no_ndlp:
@@ -418,67 +557,68 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
struct fc_bsg_job *job;
IOCB_t *rsp;
struct lpfc_nodelist *ndlp;
- struct lpfc_dmabuf *pbuflist = NULL;
+ struct lpfc_dmabuf *pcmd = NULL, *prsp = NULL;
struct fc_bsg_ctels_reply *els_reply;
uint8_t *rjt_data;
unsigned long flags;
+ unsigned int rsp_size;
int rc = 0;
- spin_lock_irqsave(&phba->ct_ev_lock, flags);
dd_data = cmdiocbq->context1;
- /* normal completion and timeout crossed paths, already done */
- if (!dd_data) {
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- return;
- }
+ ndlp = dd_data->context_un.iocb.ndlp;
+ cmdiocbq->context1 = ndlp;
- cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
- if (cmdiocbq->context2 && rspiocbq)
- memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
- &rspiocbq->iocb, sizeof(IOCB_t));
+ /* Determine if job has been aborted */
+ spin_lock_irqsave(&phba->ct_ev_lock, flags);
+ job = dd_data->set_job;
+ if (job) {
+ /* Prevent timeout handling from trying to abort job */
+ job->dd_data = NULL;
+ }
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- job = dd_data->context_un.iocb.set_job;
- cmdiocbq = dd_data->context_un.iocb.cmdiocbq;
- rspiocbq = dd_data->context_un.iocb.rspiocbq;
rsp = &rspiocbq->iocb;
- ndlp = dd_data->context_un.iocb.ndlp;
+ pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2;
+ prsp = (struct lpfc_dmabuf *)pcmd->list.next;
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ /* Copy the completed job data or determine the job status if job is
+ * still active
+ */
- if (job->reply->result == -EAGAIN)
- rc = -EAGAIN;
- else if (rsp->ulpStatus == IOSTAT_SUCCESS)
- job->reply->reply_payload_rcv_len =
- rsp->un.elsreq64.bdl.bdeSize;
- else if (rsp->ulpStatus == IOSTAT_LS_RJT) {
- job->reply->reply_payload_rcv_len =
- sizeof(struct fc_bsg_ctels_reply);
- /* LS_RJT data returned in word 4 */
- rjt_data = (uint8_t *)&rsp->un.ulpWord[4];
- els_reply = &job->reply->reply_data.ctels_reply;
- els_reply->status = FC_CTELS_STATUS_REJECT;
- els_reply->rjt_data.action = rjt_data[3];
- els_reply->rjt_data.reason_code = rjt_data[2];
- els_reply->rjt_data.reason_explanation = rjt_data[1];
- els_reply->rjt_data.vendor_unique = rjt_data[0];
- } else
- rc = -EIO;
+ if (job) {
+ if (rsp->ulpStatus == IOSTAT_SUCCESS) {
+ rsp_size = rsp->un.elsreq64.bdl.bdeSize;
+ job->reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt,
+ prsp->virt,
+ rsp_size);
+ } else if (rsp->ulpStatus == IOSTAT_LS_RJT) {
+ job->reply->reply_payload_rcv_len =
+ sizeof(struct fc_bsg_ctels_reply);
+ /* LS_RJT data returned in word 4 */
+ rjt_data = (uint8_t *)&rsp->un.ulpWord[4];
+ els_reply = &job->reply->reply_data.ctels_reply;
+ els_reply->status = FC_CTELS_STATUS_REJECT;
+ els_reply->rjt_data.action = rjt_data[3];
+ els_reply->rjt_data.reason_code = rjt_data[2];
+ els_reply->rjt_data.reason_explanation = rjt_data[1];
+ els_reply->rjt_data.vendor_unique = rjt_data[0];
+ } else {
+ rc = -EIO;
+ }
+ }
- pbuflist = (struct lpfc_dmabuf *) cmdiocbq->context3;
- lpfc_mbuf_free(phba, pbuflist->virt, pbuflist->phys);
- lpfc_sli_release_iocbq(phba, rspiocbq);
- lpfc_sli_release_iocbq(phba, cmdiocbq);
lpfc_nlp_put(ndlp);
+ lpfc_els_free_iocb(phba, cmdiocbq);
kfree(dd_data);
- /* make error code available to userspace */
- job->reply->result = rc;
- job->dd_data = NULL;
- /* complete the job back to userspace */
- job->job_done(job);
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+
+ /* Complete the job if the job is still active */
+
+ if (job) {
+ job->reply->result = rc;
+ job->job_done(job);
+ }
return;
}
@@ -496,19 +636,8 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
uint32_t elscmd;
uint32_t cmdsize;
uint32_t rspsize;
- struct lpfc_iocbq *rspiocbq;
struct lpfc_iocbq *cmdiocbq;
- IOCB_t *rsp;
uint16_t rpi = 0;
- struct lpfc_dmabuf *pcmd;
- struct lpfc_dmabuf *prsp;
- struct lpfc_dmabuf *pbuflist = NULL;
- struct ulp_bde64 *bpl;
- int request_nseg;
- int reply_nseg;
- struct scatterlist *sgel = NULL;
- int numbde;
- dma_addr_t busaddr;
struct bsg_job_data *dd_data;
uint32_t creg_val;
int rc = 0;
@@ -516,6 +645,15 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
/* in case no data is transferred */
job->reply->reply_payload_rcv_len = 0;
+ /* verify the els command is not greater than the
+ * maximum ELS transfer size.
+ */
+
+ if (job->request_payload.payload_len > FCELSSIZE) {
+ rc = -EINVAL;
+ goto no_dd_data;
+ }
+
/* allocate our bsg tracking structure */
dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
if (!dd_data) {
@@ -525,88 +663,51 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
goto no_dd_data;
}
- if (!lpfc_nlp_get(ndlp)) {
- rc = -ENODEV;
- goto free_dd_data;
- }
-
elscmd = job->request->rqst_data.r_els.els_code;
cmdsize = job->request_payload.payload_len;
rspsize = job->reply_payload.payload_len;
- rspiocbq = lpfc_sli_get_iocbq(phba);
- if (!rspiocbq) {
- lpfc_nlp_put(ndlp);
- rc = -ENOMEM;
+
+ if (!lpfc_nlp_get(ndlp)) {
+ rc = -ENODEV;
goto free_dd_data;
}
- rsp = &rspiocbq->iocb;
- rpi = ndlp->nlp_rpi;
+ /* We will use the allocated dma buffers by prep els iocb for command
+ * and response to ensure if the job times out and the request is freed,
+ * we won't be dma into memory that is no longer allocated to for the
+ * request.
+ */
cmdiocbq = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp,
ndlp->nlp_DID, elscmd);
if (!cmdiocbq) {
rc = -EIO;
- goto free_rspiocbq;
+ goto release_ndlp;
}
- /* prep els iocb set context1 to the ndlp, context2 to the command
- * dmabuf, context3 holds the data dmabuf
- */
- pcmd = (struct lpfc_dmabuf *) cmdiocbq->context2;
- prsp = (struct lpfc_dmabuf *) pcmd->list.next;
- lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
- kfree(pcmd);
- lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
- kfree(prsp);
- cmdiocbq->context2 = NULL;
-
- pbuflist = (struct lpfc_dmabuf *) cmdiocbq->context3;
- bpl = (struct ulp_bde64 *) pbuflist->virt;
-
- request_nseg = pci_map_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- for_each_sg(job->request_payload.sg_list, sgel, request_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
- }
+ rpi = ndlp->nlp_rpi;
+
+ /* Transfer the request payload to allocated command dma buffer */
+
+ sg_copy_to_buffer(job->request_payload.sg_list,
+ job->request_payload.sg_cnt,
+ ((struct lpfc_dmabuf *)cmdiocbq->context2)->virt,
+ cmdsize);
- reply_nseg = pci_map_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
- for_each_sg(job->reply_payload.sg_list, sgel, reply_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
- }
- cmdiocbq->iocb.un.elsreq64.bdl.bdeSize =
- (request_nseg + reply_nseg) * sizeof(struct ulp_bde64);
if (phba->sli_rev == LPFC_SLI_REV4)
cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi];
else
cmdiocbq->iocb.ulpContext = rpi;
cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
- cmdiocbq->context1 = NULL;
- cmdiocbq->context2 = NULL;
-
- cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp;
cmdiocbq->context1 = dd_data;
cmdiocbq->context_un.ndlp = ndlp;
- cmdiocbq->context2 = rspiocbq;
+ cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp;
dd_data->type = TYPE_IOCB;
+ dd_data->set_job = job;
dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
- dd_data->context_un.iocb.rspiocbq = rspiocbq;
- dd_data->context_un.iocb.set_job = job;
- dd_data->context_un.iocb.bmp = NULL;
dd_data->context_un.iocb.ndlp = ndlp;
+ dd_data->context_un.iocb.rmp = NULL;
+ job->dd_data = dd_data;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
@@ -617,8 +718,9 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
+
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
- lpfc_nlp_put(ndlp);
+
if (rc == IOCB_SUCCESS)
return 0; /* done for now */
else if (rc == IOCB_BUSY)
@@ -627,17 +729,12 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
rc = -EIO;
linkdown_err:
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
-
- lpfc_mbuf_free(phba, pbuflist->virt, pbuflist->phys);
- lpfc_sli_release_iocbq(phba, cmdiocbq);
+ cmdiocbq->context1 = ndlp;
+ lpfc_els_free_iocb(phba, cmdiocbq);
-free_rspiocbq:
- lpfc_sli_release_iocbq(phba, rspiocbq);
+release_ndlp:
+ lpfc_nlp_put(ndlp);
free_dd_data:
kfree(dd_data);
@@ -680,6 +777,7 @@ lpfc_bsg_event_free(struct kref *kref)
kfree(ed);
}
+ kfree(evt->dd_data);
kfree(evt);
}
@@ -723,6 +821,7 @@ lpfc_bsg_event_new(uint32_t ev_mask, int ev_reg_id, uint32_t ev_req_id)
evt->req_id = ev_req_id;
evt->reg_id = ev_reg_id;
evt->wait_time_stamp = jiffies;
+ evt->dd_data = NULL;
init_waitqueue_head(&evt->wq);
kref_init(&evt->kref);
return evt;
@@ -790,6 +889,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_hbq_entry *hbqe;
struct lpfc_sli_ct_request *ct_req;
struct fc_bsg_job *job = NULL;
+ struct bsg_job_data *dd_data = NULL;
unsigned long flags;
int size = 0;
@@ -955,9 +1055,9 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
spin_lock_irqsave(&phba->ct_ev_lock, flags);
if (phba->sli_rev == LPFC_SLI_REV4) {
evt_dat->immed_dat = phba->ctx_idx;
- phba->ctx_idx = (phba->ctx_idx + 1) % 64;
+ phba->ctx_idx = (phba->ctx_idx + 1) % LPFC_CT_CTX_MAX;
/* Provide warning for over-run of the ct_ctx array */
- if (phba->ct_ctx[evt_dat->immed_dat].flags &
+ if (phba->ct_ctx[evt_dat->immed_dat].valid ==
UNSOL_VALID)
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
"2717 CT context array entry "
@@ -973,7 +1073,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
piocbq->iocb.unsli3.rcvsli3.ox_id;
phba->ct_ctx[evt_dat->immed_dat].SID =
piocbq->iocb.un.rcvels.remoteID;
- phba->ct_ctx[evt_dat->immed_dat].flags = UNSOL_VALID;
+ phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID;
} else
evt_dat->immed_dat = piocbq->iocb.ulpContext;
@@ -986,10 +1086,11 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
list_move(evt->events_to_see.prev, &evt->events_to_get);
- lpfc_bsg_event_unref(evt);
- job = evt->set_job;
- evt->set_job = NULL;
+ dd_data = (struct bsg_job_data *)evt->dd_data;
+ job = dd_data->set_job;
+ dd_data->set_job = NULL;
+ lpfc_bsg_event_unref(evt);
if (job) {
job->reply->reply_payload_rcv_len = size;
/* make error code available to userspace */
@@ -1013,6 +1114,47 @@ error_ct_unsol_exit:
}
/**
+ * lpfc_bsg_ct_unsol_abort - handler ct abort to management plane
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: pointer to a dmabuf that describes the FC sequence
+ *
+ * This function handles abort to the CT command toward management plane
+ * for SLI4 port.
+ *
+ * If the pending context of a CT command to management plane present, clears
+ * such context and returns 1 for handled; otherwise, it returns 0 indicating
+ * no context exists.
+ **/
+int
+lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
+{
+ struct fc_frame_header fc_hdr;
+ struct fc_frame_header *fc_hdr_ptr = &fc_hdr;
+ int ctx_idx, handled = 0;
+ uint16_t oxid, rxid;
+ uint32_t sid;
+
+ memcpy(fc_hdr_ptr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
+ sid = sli4_sid_from_fc_hdr(fc_hdr_ptr);
+ oxid = be16_to_cpu(fc_hdr_ptr->fh_ox_id);
+ rxid = be16_to_cpu(fc_hdr_ptr->fh_rx_id);
+
+ for (ctx_idx = 0; ctx_idx < LPFC_CT_CTX_MAX; ctx_idx++) {
+ if (phba->ct_ctx[ctx_idx].valid != UNSOL_VALID)
+ continue;
+ if (phba->ct_ctx[ctx_idx].rxid != rxid)
+ continue;
+ if (phba->ct_ctx[ctx_idx].oxid != oxid)
+ continue;
+ if (phba->ct_ctx[ctx_idx].SID != sid)
+ continue;
+ phba->ct_ctx[ctx_idx].valid = UNSOL_INVALID;
+ handled = 1;
+ }
+ return handled;
+}
+
+/**
* lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command
* @job: SET_EVENT fc_bsg_job
**/
@@ -1037,14 +1179,6 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
goto job_error;
}
- dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
- if (dd_data == NULL) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
- "2734 Failed allocation of dd_data\n");
- rc = -ENOMEM;
- goto job_error;
- }
-
event_req = (struct set_ct_event *)
job->request->rqst_data.h_vendor.vendor_cmd;
ev_mask = ((uint32_t)(unsigned long)event_req->type_mask &
@@ -1054,6 +1188,7 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
if (evt->reg_id == event_req->ev_reg_id) {
lpfc_bsg_event_ref(evt);
evt->wait_time_stamp = jiffies;
+ dd_data = (struct bsg_job_data *)evt->dd_data;
break;
}
}
@@ -1061,6 +1196,13 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
if (&evt->node == &phba->ct_ev_waiters) {
/* no event waiting struct yet - first call */
+ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
+ if (dd_data == NULL) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+ "2734 Failed allocation of dd_data\n");
+ rc = -ENOMEM;
+ goto job_error;
+ }
evt = lpfc_bsg_event_new(ev_mask, event_req->ev_reg_id,
event_req->ev_req_id);
if (!evt) {
@@ -1070,7 +1212,10 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
rc = -ENOMEM;
goto job_error;
}
-
+ dd_data->type = TYPE_EVT;
+ dd_data->set_job = NULL;
+ dd_data->context_un.evt = evt;
+ evt->dd_data = (void *)dd_data;
spin_lock_irqsave(&phba->ct_ev_lock, flags);
list_add(&evt->node, &phba->ct_ev_waiters);
lpfc_bsg_event_ref(evt);
@@ -1080,9 +1225,7 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
spin_lock_irqsave(&phba->ct_ev_lock, flags);
evt->waiting = 1;
- dd_data->type = TYPE_EVT;
- dd_data->context_un.evt = evt;
- evt->set_job = job; /* for unsolicited command */
+ dd_data->set_job = job; /* for unsolicited command */
job->dd_data = dd_data; /* for fc transport timeout callback*/
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
return 0; /* call job done later */
@@ -1211,57 +1354,64 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
struct bsg_job_data *dd_data;
struct fc_bsg_job *job;
IOCB_t *rsp;
- struct lpfc_dmabuf *bmp;
+ struct lpfc_dmabuf *bmp, *cmp;
struct lpfc_nodelist *ndlp;
unsigned long flags;
int rc = 0;
+ dd_data = cmdiocbq->context1;
+
+ /* Determine if job has been aborted */
spin_lock_irqsave(&phba->ct_ev_lock, flags);
- dd_data = cmdiocbq->context2;
- /* normal completion and timeout crossed paths, already done */
- if (!dd_data) {
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- return;
+ job = dd_data->set_job;
+ if (job) {
+ /* Prevent timeout handling from trying to abort job */
+ job->dd_data = NULL;
}
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- job = dd_data->context_un.iocb.set_job;
- bmp = dd_data->context_un.iocb.bmp;
- rsp = &rspiocbq->iocb;
ndlp = dd_data->context_un.iocb.ndlp;
+ cmp = cmdiocbq->context2;
+ bmp = cmdiocbq->context3;
+ rsp = &rspiocbq->iocb;
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
+ /* Copy the completed job data or set the error status */
- if (rsp->ulpStatus) {
- if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
- switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
- case IOERR_SEQUENCE_TIMEOUT:
- rc = -ETIMEDOUT;
- break;
- case IOERR_INVALID_RPI:
- rc = -EFAULT;
- break;
- default:
+ if (job) {
+ if (rsp->ulpStatus) {
+ if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+ switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
+ case IOERR_SEQUENCE_TIMEOUT:
+ rc = -ETIMEDOUT;
+ break;
+ case IOERR_INVALID_RPI:
+ rc = -EFAULT;
+ break;
+ default:
+ rc = -EACCES;
+ break;
+ }
+ } else {
rc = -EACCES;
- break;
}
- } else
- rc = -EACCES;
- } else
- job->reply->reply_payload_rcv_len =
- rsp->un.genreq64.bdl.bdeSize;
+ } else {
+ job->reply->reply_payload_rcv_len = 0;
+ }
+ }
+ lpfc_free_bsg_buffers(phba, cmp);
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
+ kfree(bmp);
lpfc_sli_release_iocbq(phba, cmdiocbq);
lpfc_nlp_put(ndlp);
- kfree(bmp);
kfree(dd_data);
- /* make error code available to userspace */
- job->reply->result = rc;
- job->dd_data = NULL;
- /* complete the job back to userspace */
- job->job_done(job);
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+
+ /* Complete the job if the job is still active */
+
+ if (job) {
+ job->reply->result = rc;
+ job->job_done(job);
+ }
return;
}
@@ -1275,7 +1425,8 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
**/
static int
lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
- struct lpfc_dmabuf *bmp, int num_entry)
+ struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp,
+ int num_entry)
{
IOCB_t *icmd;
struct lpfc_iocbq *ctiocb = NULL;
@@ -1318,7 +1469,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
icmd->ulpClass = CLASS3;
if (phba->sli_rev == LPFC_SLI_REV4) {
/* Do not issue unsol response if oxid not marked as valid */
- if (!(phba->ct_ctx[tag].flags & UNSOL_VALID)) {
+ if (phba->ct_ctx[tag].valid != UNSOL_VALID) {
rc = IOCB_ERROR;
goto issue_ct_rsp_exit;
}
@@ -1336,7 +1487,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
/* Check if the ndlp is active */
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
- rc = -IOCB_ERROR;
+ rc = IOCB_ERROR;
goto issue_ct_rsp_exit;
}
@@ -1344,7 +1495,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
* we respond
*/
if (!lpfc_nlp_get(ndlp)) {
- rc = -IOCB_ERROR;
+ rc = IOCB_ERROR;
goto issue_ct_rsp_exit;
}
@@ -1352,7 +1503,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
/* The exchange is done, mark the entry as invalid */
- phba->ct_ctx[tag].flags &= ~UNSOL_VALID;
+ phba->ct_ctx[tag].valid = UNSOL_INVALID;
} else
icmd->ulpContext = (ushort) tag;
@@ -1366,17 +1517,18 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
ctiocb->iocb_cmpl = NULL;
ctiocb->iocb_flag |= LPFC_IO_LIBDFC;
ctiocb->vport = phba->pport;
+ ctiocb->context1 = dd_data;
+ ctiocb->context2 = cmp;
ctiocb->context3 = bmp;
-
+ ctiocb->context_un.ndlp = ndlp;
ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
- ctiocb->context2 = dd_data;
- ctiocb->context1 = ndlp;
+
dd_data->type = TYPE_IOCB;
+ dd_data->set_job = job;
dd_data->context_un.iocb.cmdiocbq = ctiocb;
- dd_data->context_un.iocb.rspiocbq = NULL;
- dd_data->context_un.iocb.set_job = job;
- dd_data->context_un.iocb.bmp = bmp;
dd_data->context_un.iocb.ndlp = ndlp;
+ dd_data->context_un.iocb.rmp = NULL;
+ job->dd_data = dd_data;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
@@ -1413,11 +1565,8 @@ lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job)
struct send_mgmt_resp *mgmt_resp = (struct send_mgmt_resp *)
job->request->rqst_data.h_vendor.vendor_cmd;
struct ulp_bde64 *bpl;
- struct lpfc_dmabuf *bmp = NULL;
- struct scatterlist *sgel = NULL;
- int request_nseg;
- int numbde;
- dma_addr_t busaddr;
+ struct lpfc_dmabuf *bmp = NULL, *cmp = NULL;
+ int bpl_entries;
uint32_t tag = mgmt_resp->tag;
unsigned long reqbfrcnt =
(unsigned long)job->request_payload.payload_len;
@@ -1445,30 +1594,28 @@ lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job)
INIT_LIST_HEAD(&bmp->list);
bpl = (struct ulp_bde64 *) bmp->virt;
- request_nseg = pci_map_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- for_each_sg(job->request_payload.sg_list, sgel, request_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
+ bpl_entries = (LPFC_BPL_SIZE/sizeof(struct ulp_bde64));
+ cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
+ 1, bpl, &bpl_entries);
+ if (!cmp) {
+ rc = -ENOMEM;
+ goto send_mgmt_rsp_free_bmp;
}
+ lpfc_bsg_copy_data(cmp, &job->request_payload,
+ job->request_payload.payload_len, 1);
- rc = lpfc_issue_ct_rsp(phba, job, tag, bmp, request_nseg);
+ rc = lpfc_issue_ct_rsp(phba, job, tag, cmp, bmp, bpl_entries);
if (rc == IOCB_SUCCESS)
return 0; /* done for now */
- /* TBD need to handle a timeout */
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
rc = -EACCES;
- lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
+
+ lpfc_free_bsg_buffers(phba, cmp);
send_mgmt_rsp_free_bmp:
+ if (bmp->virt)
+ lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(bmp);
send_mgmt_rsp_exit:
/* make error code available to userspace */
@@ -1518,7 +1665,7 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
scsi_block_requests(shost);
}
- while (pring->txcmplq_cnt) {
+ while (!list_empty(&pring->txcmplq)) {
if (i++ > 500) /* wait up to 5 seconds */
break;
msleep(10);
@@ -2442,7 +2589,8 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
evt->wait_time_stamp = jiffies;
time_left = wait_event_interruptible_timeout(
evt->wq, !list_empty(&evt->events_to_see),
- ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
+ msecs_to_jiffies(1000 *
+ ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));
if (list_empty(&evt->events_to_see))
ret_val = (time_left) ? -EINTR : -ETIMEDOUT;
else {
@@ -3017,7 +3165,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
evt->waiting = 1;
time_left = wait_event_interruptible_timeout(
evt->wq, !list_empty(&evt->events_to_see),
- ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
+ msecs_to_jiffies(1000 *
+ ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));
evt->waiting = 0;
if (list_empty(&evt->events_to_see)) {
rc = (time_left) ? -EINTR : -ETIMEDOUT;
@@ -3152,13 +3301,7 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
unsigned long flags;
uint8_t *pmb, *pmb_buf;
- spin_lock_irqsave(&phba->ct_ev_lock, flags);
dd_data = pmboxq->context1;
- /* job already timed out? */
- if (!dd_data) {
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- return;
- }
/*
* The outgoing buffer is readily referred from the dma buffer,
@@ -3168,29 +3311,33 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));
- job = dd_data->context_un.mbox.set_job;
+ /* Determine if job has been aborted */
+
+ spin_lock_irqsave(&phba->ct_ev_lock, flags);
+ job = dd_data->set_job;
+ if (job) {
+ /* Prevent timeout handling from trying to abort job */
+ job->dd_data = NULL;
+ }
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+
+ /* Copy the mailbox data to the job if it is still active */
+
if (job) {
size = job->reply_payload.payload_len;
job->reply->reply_payload_rcv_len =
sg_copy_from_buffer(job->reply_payload.sg_list,
job->reply_payload.sg_cnt,
pmb_buf, size);
- /* need to hold the lock until we set job->dd_data to NULL
- * to hold off the timeout handler returning to the mid-layer
- * while we are still processing the job.
- */
- job->dd_data = NULL;
- dd_data->context_un.mbox.set_job = NULL;
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- } else {
- dd_data->context_un.mbox.set_job = NULL;
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
}
+ dd_data->set_job = NULL;
mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);
lpfc_bsg_dma_page_free(phba, dd_data->context_un.mbox.dmabuffers);
kfree(dd_data);
+ /* Complete the job if the job is still active */
+
if (job) {
job->reply->result = 0;
job->job_done(job);
@@ -3245,6 +3392,7 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
case MBX_DOWN_LOAD:
case MBX_UPDATE_CFG:
case MBX_KILL_BOARD:
+ case MBX_READ_TOPOLOGY:
case MBX_LOAD_AREA:
case MBX_LOAD_EXP_ROM:
case MBX_BEACON:
@@ -3275,7 +3423,6 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
}
break;
case MBX_READ_SPARM64:
- case MBX_READ_TOPOLOGY:
case MBX_REG_LOGIN:
case MBX_REG_LOGIN64:
case MBX_CONFIG_PORT:
@@ -3336,19 +3483,22 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
struct lpfc_sli_config_mbox *sli_cfg_mbx;
uint8_t *pmbx;
- spin_lock_irqsave(&phba->ct_ev_lock, flags);
dd_data = pmboxq->context1;
- /* has the job already timed out? */
- if (!dd_data) {
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- job = NULL;
- goto job_done_out;
+
+ /* Determine if job has been aborted */
+ spin_lock_irqsave(&phba->ct_ev_lock, flags);
+ job = dd_data->set_job;
+ if (job) {
+ /* Prevent timeout handling from trying to abort job */
+ job->dd_data = NULL;
}
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
/*
* The outgoing buffer is readily referred from the dma buffer,
* just need to get header part from mailboxq structure.
*/
+
pmb = (uint8_t *)&pmboxq->u.mb;
pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
/* Copy the byte swapped response mailbox back to the user */
@@ -3365,21 +3515,18 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
sli_cfg_mbx->un.sli_config_emb0_subsys.mse[0].buf_len);
}
- job = dd_data->context_un.mbox.set_job;
+ /* Complete the job if the job is still active */
+
if (job) {
size = job->reply_payload.payload_len;
job->reply->reply_payload_rcv_len =
sg_copy_from_buffer(job->reply_payload.sg_list,
job->reply_payload.sg_cnt,
pmb_buf, size);
+
/* result for successful */
job->reply->result = 0;
- job->dd_data = NULL;
- /* need to hold the lock util we set job->dd_data to NULL
- * to hold off the timeout handler from midlayer to take
- * any action.
- */
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"2937 SLI_CONFIG ext-buffer maibox command "
"(x%x/x%x) complete bsg job done, bsize:%d\n",
@@ -3390,20 +3537,18 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
phba->mbox_ext_buf_ctx.mboxType,
dma_ebuf, sta_pos_addr,
phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);
- } else
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
-
-job_done_out:
- if (!job)
+ } else {
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
"2938 SLI_CONFIG ext-buffer maibox "
"command (x%x/x%x) failure, rc:x%x\n",
phba->mbox_ext_buf_ctx.nembType,
phba->mbox_ext_buf_ctx.mboxType, rc);
+ }
+
+
/* state change */
phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_DONE;
kfree(dd_data);
-
return job;
}
@@ -3420,8 +3565,10 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{
struct fc_bsg_job *job;
+ job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
+
/* handle the BSG job with mailbox command */
- if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS)
+ if (!job)
pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
@@ -3429,15 +3576,13 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
"complete, ctxState:x%x, mbxStatus:x%x\n",
phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
- job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
-
if (pmboxq->u.mb.mbxStatus || phba->mbox_ext_buf_ctx.numBuf == 1)
lpfc_bsg_mbox_ext_session_reset(phba);
/* free base driver mailbox structure memory */
mempool_free(pmboxq, phba->mbox_mem_pool);
- /* complete the bsg job if we have it */
+ /* if the job is still active, call job done */
if (job)
job->job_done(job);
@@ -3457,8 +3602,10 @@ lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{
struct fc_bsg_job *job;
+ job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
+
/* handle the BSG job with the mailbox command */
- if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS)
+ if (!job)
pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
@@ -3466,13 +3613,11 @@ lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
"complete, ctxState:x%x, mbxStatus:x%x\n",
phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
- job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
-
/* free all memory, including dma buffers */
mempool_free(pmboxq, phba->mbox_mem_pool);
lpfc_bsg_mbox_ext_session_reset(phba);
- /* complete the bsg job if we have it */
+ /* if the job is still active, call job done */
if (job)
job->job_done(job);
@@ -3718,9 +3863,9 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* context fields to callback function */
pmboxq->context1 = dd_data;
dd_data->type = TYPE_MBOX;
+ dd_data->set_job = job;
dd_data->context_un.mbox.pmboxq = pmboxq;
dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;
- dd_data->context_un.mbox.set_job = job;
job->dd_data = dd_data;
/* state change */
@@ -3887,14 +4032,14 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* context fields to callback function */
pmboxq->context1 = dd_data;
dd_data->type = TYPE_MBOX;
+ dd_data->set_job = job;
dd_data->context_un.mbox.pmboxq = pmboxq;
dd_data->context_un.mbox.mb = (MAILBOX_t *)mbx;
- dd_data->context_un.mbox.set_job = job;
job->dd_data = dd_data;
/* state change */
- phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
+ phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
@@ -3910,6 +4055,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
}
/* wait for additoinal external buffers */
+
job->reply->result = 0;
job->job_done(job);
return SLI_CONFIG_HANDLED;
@@ -4227,9 +4373,9 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* context fields to callback function */
pmboxq->context1 = dd_data;
dd_data->type = TYPE_MBOX;
+ dd_data->set_job = job;
dd_data->context_un.mbox.pmboxq = pmboxq;
dd_data->context_un.mbox.mb = (MAILBOX_t *)pbuf;
- dd_data->context_un.mbox.set_job = job;
job->dd_data = dd_data;
/* state change */
@@ -4414,7 +4560,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
uint8_t *from;
uint32_t size;
-
/* in case no data is transferred */
job->reply->reply_payload_rcv_len = 0;
@@ -4640,9 +4785,9 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* setup context field to pass wait_queue pointer to wake function */
pmboxq->context1 = dd_data;
dd_data->type = TYPE_MBOX;
+ dd_data->set_job = job;
dd_data->context_un.mbox.pmboxq = pmboxq;
dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;
- dd_data->context_un.mbox.set_job = job;
dd_data->context_un.mbox.ext = ext;
dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset;
dd_data->context_un.mbox.inExtWLen = mbox_req->inExtWLen;
@@ -4700,7 +4845,7 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
if (job->request_len <
sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) {
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
- "2737 Mix-and-match backward compability "
+ "2737 Mix-and-match backward compatibility "
"between MBOX_REQ old size:%d and "
"new request size:%d\n",
(int)(job->request_len -
@@ -4756,75 +4901,79 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
struct bsg_job_data *dd_data;
struct fc_bsg_job *job;
IOCB_t *rsp;
- struct lpfc_dmabuf *bmp;
+ struct lpfc_dmabuf *bmp, *cmp, *rmp;
struct lpfc_bsg_menlo *menlo;
unsigned long flags;
struct menlo_response *menlo_resp;
+ unsigned int rsp_size;
int rc = 0;
- spin_lock_irqsave(&phba->ct_ev_lock, flags);
dd_data = cmdiocbq->context1;
- if (!dd_data) {
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- return;
- }
-
+ cmp = cmdiocbq->context2;
+ bmp = cmdiocbq->context3;
menlo = &dd_data->context_un.menlo;
- job = menlo->set_job;
- job->dd_data = NULL; /* so timeout handler does not reply */
-
- spin_lock(&phba->hbalock);
- cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
- if (cmdiocbq->context2 && rspiocbq)
- memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
- &rspiocbq->iocb, sizeof(IOCB_t));
- spin_unlock(&phba->hbalock);
-
- bmp = menlo->bmp;
- rspiocbq = menlo->rspiocbq;
+ rmp = menlo->rmp;
rsp = &rspiocbq->iocb;
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ /* Determine if job has been aborted */
+ spin_lock_irqsave(&phba->ct_ev_lock, flags);
+ job = dd_data->set_job;
+ if (job) {
+ /* Prevent timeout handling from trying to abort job */
+ job->dd_data = NULL;
+ }
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- /* always return the xri, this would be used in the case
- * of a menlo download to allow the data to be sent as a continuation
- * of the exchange.
- */
- menlo_resp = (struct menlo_response *)
- job->reply->reply_data.vendor_reply.vendor_rsp;
- menlo_resp->xri = rsp->ulpContext;
- if (rsp->ulpStatus) {
- if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
- switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
- case IOERR_SEQUENCE_TIMEOUT:
- rc = -ETIMEDOUT;
- break;
- case IOERR_INVALID_RPI:
- rc = -EFAULT;
- break;
- default:
+ /* Copy the job data or set the failing status for the job */
+
+ if (job) {
+ /* always return the xri, this would be used in the case
+ * of a menlo download to allow the data to be sent as a
+ * continuation of the exchange.
+ */
+
+ menlo_resp = (struct menlo_response *)
+ job->reply->reply_data.vendor_reply.vendor_rsp;
+ menlo_resp->xri = rsp->ulpContext;
+ if (rsp->ulpStatus) {
+ if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+ switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
+ case IOERR_SEQUENCE_TIMEOUT:
+ rc = -ETIMEDOUT;
+ break;
+ case IOERR_INVALID_RPI:
+ rc = -EFAULT;
+ break;
+ default:
+ rc = -EACCES;
+ break;
+ }
+ } else {
rc = -EACCES;
- break;
}
- } else
- rc = -EACCES;
- } else
- job->reply->reply_payload_rcv_len =
- rsp->un.genreq64.bdl.bdeSize;
+ } else {
+ rsp_size = rsp->un.genreq64.bdl.bdeSize;
+ job->reply->reply_payload_rcv_len =
+ lpfc_bsg_copy_data(rmp, &job->reply_payload,
+ rsp_size, 0);
+ }
+
+ }
- lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
- lpfc_sli_release_iocbq(phba, rspiocbq);
lpfc_sli_release_iocbq(phba, cmdiocbq);
+ lpfc_free_bsg_buffers(phba, cmp);
+ lpfc_free_bsg_buffers(phba, rmp);
+ lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(bmp);
kfree(dd_data);
- /* make error code available to userspace */
- job->reply->result = rc;
- /* complete the job back to userspace */
- job->job_done(job);
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+
+ /* Complete the job if active */
+
+ if (job) {
+ job->reply->result = rc;
+ job->job_done(job);
+ }
+
return;
}
@@ -4842,17 +4991,14 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
{
struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- struct lpfc_iocbq *cmdiocbq, *rspiocbq;
- IOCB_t *cmd, *rsp;
+ struct lpfc_iocbq *cmdiocbq;
+ IOCB_t *cmd;
int rc = 0;
struct menlo_command *menlo_cmd;
struct menlo_response *menlo_resp;
- struct lpfc_dmabuf *bmp = NULL;
+ struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
int request_nseg;
int reply_nseg;
- struct scatterlist *sgel = NULL;
- int numbde;
- dma_addr_t busaddr;
struct bsg_job_data *dd_data;
struct ulp_bde64 *bpl = NULL;
@@ -4907,50 +5053,38 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
goto free_dd;
}
- cmdiocbq = lpfc_sli_get_iocbq(phba);
- if (!cmdiocbq) {
+ bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
+ if (!bmp->virt) {
rc = -ENOMEM;
goto free_bmp;
}
- rspiocbq = lpfc_sli_get_iocbq(phba);
- if (!rspiocbq) {
- rc = -ENOMEM;
- goto free_cmdiocbq;
- }
-
- rsp = &rspiocbq->iocb;
+ INIT_LIST_HEAD(&bmp->list);
- bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
- if (!bmp->virt) {
+ bpl = (struct ulp_bde64 *)bmp->virt;
+ request_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64);
+ cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
+ 1, bpl, &request_nseg);
+ if (!cmp) {
rc = -ENOMEM;
- goto free_rspiocbq;
+ goto free_bmp;
}
+ lpfc_bsg_copy_data(cmp, &job->request_payload,
+ job->request_payload.payload_len, 1);
- INIT_LIST_HEAD(&bmp->list);
- bpl = (struct ulp_bde64 *) bmp->virt;
- request_nseg = pci_map_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- for_each_sg(job->request_payload.sg_list, sgel, request_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
+ bpl += request_nseg;
+ reply_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64) - request_nseg;
+ rmp = lpfc_alloc_bsg_buffers(phba, job->reply_payload.payload_len, 0,
+ bpl, &reply_nseg);
+ if (!rmp) {
+ rc = -ENOMEM;
+ goto free_cmp;
}
- reply_nseg = pci_map_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
- for_each_sg(job->reply_payload.sg_list, sgel, reply_nseg, numbde) {
- busaddr = sg_dma_address(sgel);
- bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
- bpl->tus.f.bdeSize = sg_dma_len(sgel);
- bpl->tus.w = cpu_to_le32(bpl->tus.w);
- bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr));
- bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr));
- bpl++;
+ cmdiocbq = lpfc_sli_get_iocbq(phba);
+ if (!cmdiocbq) {
+ rc = -ENOMEM;
+ goto free_rmp;
}
cmd = &cmdiocbq->iocb;
@@ -4972,11 +5106,10 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
cmdiocbq->vport = phba->pport;
/* We want the firmware to timeout before we do */
cmd->ulpTimeout = MENLO_TIMEOUT - 5;
- cmdiocbq->context3 = bmp;
- cmdiocbq->context2 = rspiocbq;
cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp;
cmdiocbq->context1 = dd_data;
- cmdiocbq->context2 = rspiocbq;
+ cmdiocbq->context2 = cmp;
+ cmdiocbq->context3 = bmp;
if (menlo_cmd->cmd == LPFC_BSG_VENDOR_MENLO_CMD) {
cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
cmd->ulpPU = MENLO_PU; /* 3 */
@@ -4990,29 +5123,25 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
}
dd_data->type = TYPE_MENLO;
+ dd_data->set_job = job;
dd_data->context_un.menlo.cmdiocbq = cmdiocbq;
- dd_data->context_un.menlo.rspiocbq = rspiocbq;
- dd_data->context_un.menlo.set_job = job;
- dd_data->context_un.menlo.bmp = bmp;
+ dd_data->context_un.menlo.rmp = rmp;
+ job->dd_data = dd_data;
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
MENLO_TIMEOUT - 5);
if (rc == IOCB_SUCCESS)
return 0; /* done for now */
- /* iocb failed so cleanup */
- pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
- job->request_payload.sg_cnt, DMA_TO_DEVICE);
- pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
- job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
-
- lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-
-free_rspiocbq:
- lpfc_sli_release_iocbq(phba, rspiocbq);
-free_cmdiocbq:
lpfc_sli_release_iocbq(phba, cmdiocbq);
+
+free_rmp:
+ lpfc_free_bsg_buffers(phba, rmp);
+free_cmp:
+ lpfc_free_bsg_buffers(phba, cmp);
free_bmp:
+ if (bmp->virt)
+ lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
kfree(bmp);
free_dd:
kfree(dd_data);
@@ -5121,70 +5250,94 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb;
- struct lpfc_bsg_event *evt;
- struct lpfc_bsg_iocb *iocb;
- struct lpfc_bsg_mbox *mbox;
- struct lpfc_bsg_menlo *menlo;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
struct bsg_job_data *dd_data;
unsigned long flags;
+ int rc = 0;
+ LIST_HEAD(completions);
+ struct lpfc_iocbq *check_iocb, *next_iocb;
+
+ /* if job's driver data is NULL, the command completed or is in the
+ * the process of completing. In this case, return status to request
+ * so the timeout is retried. This avoids double completion issues
+ * and the request will be pulled off the timer queue when the
+ * command's completion handler executes. Otherwise, prevent the
+ * command's completion handler from executing the job done callback
+ * and continue processing to abort the outstanding the command.
+ */
spin_lock_irqsave(&phba->ct_ev_lock, flags);
dd_data = (struct bsg_job_data *)job->dd_data;
- /* timeout and completion crossed paths if no dd_data */
- if (!dd_data) {
+ if (dd_data) {
+ dd_data->set_job = NULL;
+ job->dd_data = NULL;
+ } else {
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- return 0;
+ return -EAGAIN;
}
switch (dd_data->type) {
case TYPE_IOCB:
- iocb = &dd_data->context_un.iocb;
- cmdiocb = iocb->cmdiocbq;
- /* hint to completion handler that the job timed out */
- job->reply->result = -EAGAIN;
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- /* this will call our completion handler */
+ /* Check to see if IOCB was issued to the port or not. If not,
+ * remove it from the txq queue and call cancel iocbs.
+ * Otherwise, call abort iotag
+ */
+
+ cmdiocb = dd_data->context_un.iocb.cmdiocbq;
spin_lock_irq(&phba->hbalock);
- lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
+ list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
+ list) {
+ if (check_iocb == cmdiocb) {
+ list_move_tail(&check_iocb->list, &completions);
+ break;
+ }
+ }
+ if (list_empty(&completions))
+ lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+ if (!list_empty(&completions)) {
+ lpfc_sli_cancel_iocbs(phba, &completions,
+ IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
+ }
break;
+
case TYPE_EVT:
- evt = dd_data->context_un.evt;
- /* this event has no job anymore */
- evt->set_job = NULL;
- job->dd_data = NULL;
- job->reply->reply_payload_rcv_len = 0;
- /* Return -EAGAIN which is our way of signallying the
- * app to retry.
- */
- job->reply->result = -EAGAIN;
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- job->job_done(job);
break;
+
case TYPE_MBOX:
- mbox = &dd_data->context_un.mbox;
- /* this mbox has no job anymore */
- mbox->set_job = NULL;
- job->dd_data = NULL;
- job->reply->reply_payload_rcv_len = 0;
- job->reply->result = -EAGAIN;
- /* the mbox completion handler can now be run */
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- job->job_done(job);
+ /* Update the ext buf ctx state if needed */
+
if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)
phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
break;
case TYPE_MENLO:
- menlo = &dd_data->context_un.menlo;
- cmdiocb = menlo->cmdiocbq;
- /* hint to completion handler that the job timed out */
- job->reply->result = -EAGAIN;
- spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
- /* this will call our completion handler */
+ /* Check to see if IOCB was issued to the port or not. If not,
+ * remove it from the txq queue and call cancel iocbs.
+ * Otherwise, call abort iotag.
+ */
+
+ cmdiocb = dd_data->context_un.menlo.cmdiocbq;
spin_lock_irq(&phba->hbalock);
- lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
+ list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
+ list) {
+ if (check_iocb == cmdiocb) {
+ list_move_tail(&check_iocb->list, &completions);
+ break;
+ }
+ }
+ if (list_empty(&completions))
+ lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+ if (!list_empty(&completions)) {
+ lpfc_sli_cancel_iocbs(phba, &completions,
+ IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
+ }
break;
default:
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -5195,5 +5348,5 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
* otherwise an error message will be displayed on the console
* so always return success (zero)
*/
- return 0;
+ return rc;
}
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 69d66e3..cda076a 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2011 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -106,6 +106,7 @@ void lpfc_cleanup_discovery_resources(struct lpfc_vport *);
void lpfc_cleanup(struct lpfc_vport *);
void lpfc_disc_timeout(unsigned long);
+int lpfc_unregister_fcf_prep(struct lpfc_hba *);
struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
void lpfc_worker_wake_up(struct lpfc_hba *);
@@ -164,8 +165,7 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *);
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
-void lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
- struct lpfc_iocbq *);
+int lpfc_ct_handle_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_fdmi_tmo(unsigned long);
@@ -427,6 +427,7 @@ int lpfc_bsg_request(struct fc_bsg_job *);
int lpfc_bsg_timeout(struct fc_bsg_job *);
int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
+int lpfc_bsg_ct_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *,
@@ -469,3 +470,4 @@ int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
+void lpfc_sli4_offline_eratt(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 65f9fb6..6839117 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2010 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -164,37 +164,24 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/**
- * lpfc_sli4_ct_abort_unsol_event - Default handle for sli4 unsol abort
+ * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler
* @phba: Pointer to HBA context object.
- * @pring: Pointer to the driver internal I/O ring.
- * @piocbq: Pointer to the IOCBQ.
+ * @dmabuf: pointer to a dmabuf that describes the FC sequence
*
- * This function serves as the default handler for the sli4 unsolicited
- * abort event. It shall be invoked when there is no application interface
- * registered unsolicited abort handler. This handler does nothing but
- * just simply releases the dma buffer used by the unsol abort event.
+ * This function serves as the upper level protocol abort handler for CT
+ * protocol.
+ *
+ * Return 1 if abort has been handled, 0 otherwise.
**/
-void
-lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *phba,
- struct lpfc_sli_ring *pring,
- struct lpfc_iocbq *piocbq)
+int
+lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
{
- IOCB_t *icmd = &piocbq->iocb;
- struct lpfc_dmabuf *bdeBuf;
- uint32_t size;
+ int handled;
- /* Forward abort event to any process registered to receive ct event */
- if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0)
- return;
+ /* CT upper level goes through BSG */
+ handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf);
- /* If there is no BDE associated with IOCB, there is nothing to do */
- if (icmd->ulpBdeCount == 0)
- return;
- bdeBuf = piocbq->context2;
- piocbq->context2 = NULL;
- size = icmd->un.cont64[0].tus.f.bdeSize;
- lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
- lpfc_in_buf_free(phba, bdeBuf);
+ return handled;
}
static void
@@ -1824,7 +1811,8 @@ lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
if (init_utsname()->nodename[0] != '\0')
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
else
- mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
+ mod_timer(&vport->fc_fdmitmo, jiffies +
+ msecs_to_jiffies(1000 * 60));
}
return;
}
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index f63f5ff..60084e6 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1165,22 +1165,8 @@ out:
static loff_t
lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
{
- struct lpfc_debug *debug;
- loff_t pos = -1;
-
- debug = file->private_data;
-
- switch (whence) {
- case 0:
- pos = off;
- break;
- case 1:
- pos = file->f_pos + off;
- break;
- case 2:
- pos = debug->len - off;
- }
- return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
+ struct lpfc_debug *debug = file->private_data;
+ return fixed_size_llseek(file, off, whence, debug->len);
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index b9440de..6b8ee74 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -29,6 +29,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
+
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -238,7 +239,10 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
icmd->un.elsreq64.remoteID = did; /* DID */
icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
- icmd->ulpTimeout = phba->fc_ratov * 2;
+ if (elscmd == ELS_CMD_FLOGI)
+ icmd->ulpTimeout = FF_DEF_RATOV * 2;
+ else
+ icmd->ulpTimeout = phba->fc_ratov * 2;
} else {
icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
@@ -308,16 +312,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
/* Xmit ELS command <elsCmd> to remote NPORT <did> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0116 Xmit ELS command x%x to remote "
- "NPORT x%x I/O tag: x%x, port state: x%x\n",
+ "NPORT x%x I/O tag: x%x, port state:x%x"
+ " fc_flag:x%x\n",
elscmd, did, elsiocb->iotag,
- vport->port_state);
+ vport->port_state,
+ vport->fc_flag);
} else {
/* Xmit ELS response <elsCmd> to remote NPORT <did> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0117 Xmit ELS response x%x to remote "
- "NPORT x%x I/O tag: x%x, size: x%x\n",
+ "NPORT x%x I/O tag: x%x, size: x%x "
+ "port_state x%x fc_flag x%x\n",
elscmd, ndlp->nlp_DID, elsiocb->iotag,
- cmdSize);
+ cmdSize, vport->port_state,
+ vport->fc_flag);
}
return elsiocb;
@@ -484,6 +492,7 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
vport->port_state = LPFC_FABRIC_CFG_LINK;
memcpy(dmabuf->virt, &phba->fc_fabparam, sizeof(vport->fc_sparam));
lpfc_reg_vfi(mboxq, vport, dmabuf->phys);
+
mboxq->mbox_cmpl = lpfc_mbx_cmpl_reg_vfi;
mboxq->vport = vport;
mboxq->context1 = dmabuf;
@@ -700,6 +709,20 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
}
+ /*
+ * For FC we need to do some special processing because of the SLI
+ * Port's default settings of the Common Service Parameters.
+ */
+ if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) {
+ /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
+ if ((phba->sli_rev == LPFC_SLI_REV4) && fabric_param_changed)
+ lpfc_unregister_fcf_prep(phba);
+
+ /* This should just update the VFI CSPs*/
+ if (vport->fc_flag & FC_VFI_REGISTERED)
+ lpfc_issue_reg_vfi(vport);
+ }
+
if (fabric_param_changed &&
!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
@@ -894,6 +917,23 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT;
spin_unlock_irq(shost->host_lock);
+ /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
+ if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) {
+ lpfc_unregister_fcf_prep(phba);
+
+ /* The FC_VFI_REGISTERED flag will get clear in the cmpl
+ * handler for unreg_vfi, but if we don't force the
+ * FC_VFI_REGISTERED flag then the reg_vfi mailbox could be
+ * built with the update bit set instead of just the vp bit to
+ * change the Nport ID. We need to have the vp set and the
+ * Upd cleared on topology changes.
+ */
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_VFI_REGISTERED;
+ spin_unlock_irq(shost->host_lock);
+ phba->fc_topology_changed = 0;
+ lpfc_issue_reg_vfi(vport);
+ }
/* Start discovery - this should just do CLEAR_LA */
lpfc_disc_start(vport);
@@ -1015,9 +1055,19 @@ stop_rr_fcf_flogi:
vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
if ((phba->sli_rev == LPFC_SLI_REV4) &&
(!(vport->fc_flag & FC_VFI_REGISTERED) ||
- (vport->fc_prevDID != vport->fc_myDID))) {
- if (vport->fc_flag & FC_VFI_REGISTERED)
- lpfc_sli4_unreg_all_rpis(vport);
+ (vport->fc_prevDID != vport->fc_myDID) ||
+ phba->fc_topology_changed)) {
+ if (vport->fc_flag & FC_VFI_REGISTERED) {
+ if (phba->fc_topology_changed) {
+ lpfc_unregister_fcf_prep(phba);
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_VFI_REGISTERED;
+ spin_unlock_irq(shost->host_lock);
+ phba->fc_topology_changed = 0;
+ } else {
+ lpfc_sli4_unreg_all_rpis(vport);
+ }
+ }
lpfc_issue_reg_vfi(vport);
lpfc_nlp_put(ndlp);
goto out;
@@ -1039,10 +1089,11 @@ stop_rr_fcf_flogi:
/* FLOGI completes successfully */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "0101 FLOGI completes successfully "
- "Data: x%x x%x x%x x%x\n",
+ "0101 FLOGI completes successfully, I/O tag:x%x, "
+ "Data: x%x x%x x%x x%x x%x x%x\n", cmdiocb->iotag,
irsp->un.ulpWord[4], sp->cmn.e_d_tov,
- sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
+ sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution,
+ vport->port_state, vport->fc_flag);
if (vport->port_state == LPFC_FLOGI) {
/*
@@ -3122,6 +3173,13 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
case IOERR_SEQUENCE_TIMEOUT:
case IOERR_INVALID_RPI:
+ if (cmd == ELS_CMD_PLOGI &&
+ did == NameServer_DID) {
+ /* Continue forever if plogi to */
+ /* the nameserver fails */
+ maxretry = 0;
+ delay = 100;
+ }
retry = 1;
break;
}
@@ -5025,6 +5083,8 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct ls_rjt stat;
uint32_t cmd, did;
int rc;
+ uint32_t fc_flag = 0;
+ uint32_t port_state = 0;
cmd = *lp++;
sp = (struct serv_parm *) lp;
@@ -5091,16 +5151,25 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
* will be.
*/
vport->fc_myDID = PT2PT_LocalID;
- }
+ } else
+ vport->fc_myDID = PT2PT_RemoteID;
/*
* The vport state should go to LPFC_FLOGI only
* AFTER we issue a FLOGI, not receive one.
*/
spin_lock_irq(shost->host_lock);
+ fc_flag = vport->fc_flag;
+ port_state = vport->port_state;
vport->fc_flag |= FC_PT2PT;
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+ vport->port_state = LPFC_FLOGI;
spin_unlock_irq(shost->host_lock);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "3311 Rcv Flogi PS x%x new PS x%x "
+ "fc_flag x%x new fc_flag x%x\n",
+ port_state, vport->port_state,
+ fc_flag, vport->fc_flag);
/*
* We temporarily set fc_myDID to make it look like we are
@@ -6218,8 +6287,9 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
spin_unlock_irq(&phba->hbalock);
}
- if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
- mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+ if (!list_empty(&phba->sli.ring[LPFC_ELS_RING].txcmplq))
+ mod_timer(&vport->els_tmofunc,
+ jiffies + msecs_to_jiffies(1000 * timeout));
}
/**
@@ -6272,7 +6342,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
continue;
list_move_tail(&piocb->list, &completions);
- pring->txq_cnt--;
}
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
@@ -6332,7 +6401,6 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
cmd->ulpCommand == CMD_ABORT_XRI_CN)
continue;
list_move_tail(&piocb->list, &completions);
- pring->txq_cnt--;
}
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
if (piocb->iocb_flag & LPFC_IO_LIBDFC)
@@ -6517,7 +6585,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_nodelist *ndlp;
struct ls_rjt stat;
uint32_t *payload;
- uint32_t cmd, did, newnode, rjt_err = 0;
+ uint32_t cmd, did, newnode;
+ uint8_t rjt_exp, rjt_err = 0;
IOCB_t *icmd = &elsiocb->iocb;
if (!vport || !(elsiocb->context2))
@@ -6591,7 +6660,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/* ELS command <elsCmd> received from NPORT <did> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0112 ELS command x%x received from NPORT x%x "
- "Data: x%x\n", cmd, did, vport->port_state);
+ "Data: x%x x%x x%x x%x\n",
+ cmd, did, vport->port_state, vport->fc_flag,
+ vport->fc_myDID, vport->fc_prevDID);
switch (cmd) {
case ELS_CMD_PLOGI:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -6600,27 +6671,52 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->fc_stat.elsRcvPLOGI++;
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+ if (phba->sli_rev == LPFC_SLI_REV4 &&
+ (phba->pport->fc_flag & FC_PT2PT)) {
+ vport->fc_prevDID = vport->fc_myDID;
+ /* Our DID needs to be updated before registering
+ * the vfi. This is done in lpfc_rcv_plogi but
+ * that is called after the reg_vfi.
+ */
+ vport->fc_myDID = elsiocb->iocb.un.rcvels.parmRo;
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "3312 Remote port assigned DID x%x "
+ "%x\n", vport->fc_myDID,
+ vport->fc_prevDID);
+ }
lpfc_send_els_event(vport, ndlp, payload);
/* If Nport discovery is delayed, reject PLOGIs */
if (vport->fc_flag & FC_DISC_DELAYED) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
+ shost = lpfc_shost_from_vport(vport);
if (vport->port_state < LPFC_DISC_AUTH) {
if (!(phba->pport->fc_flag & FC_PT2PT) ||
(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
/* We get here, and drop thru, if we are PT2PT with
* another NPort and the other side has initiated
* the PLOGI before responding to our FLOGI.
*/
+ if (phba->sli_rev == LPFC_SLI_REV4 &&
+ (phba->fc_topology_changed ||
+ vport->fc_myDID != vport->fc_prevDID)) {
+ lpfc_unregister_fcf_prep(phba);
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_VFI_REGISTERED;
+ spin_unlock_irq(shost->host_lock);
+ phba->fc_topology_changed = 0;
+ lpfc_issue_reg_vfi(vport);
+ }
}
- shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
spin_unlock_irq(shost->host_lock);
@@ -6648,6 +6744,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
lpfc_send_els_event(vport, ndlp, payload);
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
@@ -6661,6 +6758,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
lpfc_send_els_event(vport, ndlp, payload);
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
@@ -6680,6 +6778,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->fc_stat.elsRcvADISC++;
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb,
@@ -6693,6 +6792,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->fc_stat.elsRcvPDISC++;
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb,
@@ -6730,6 +6830,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
phba->fc_stat.elsRcvPRLI++;
if (vport->port_state < LPFC_DISC_AUTH) {
rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_NOTHING_MORE;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
@@ -6813,6 +6914,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (newnode)
lpfc_nlp_put(ndlp);
break;
+ case ELS_CMD_REC:
+ /* receive this due to exchange closed */
+ rjt_err = LSRJT_UNABLE_TPC;
+ rjt_exp = LSEXP_INVALID_OX_RX;
+ break;
default:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
"RCV ELS cmd: cmd:x%x did:x%x/ste:x%x",
@@ -6820,6 +6926,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/* Unsupported ELS command, reject */
rjt_err = LSRJT_CMD_UNSUPPORTED;
+ rjt_exp = LSEXP_NOTHING_MORE;
/* Unknown ELS command <elsCmd> received from NPORT <did> */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -6834,7 +6941,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (rjt_err) {
memset(&stat, 0, sizeof(stat));
stat.un.b.lsRjtRsnCode = rjt_err;
- stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+ stat.un.b.lsRjtRsnCodeExp = rjt_exp;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
NULL);
}
@@ -6968,8 +7075,11 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
spin_lock_irq(shost->host_lock);
if (vport->fc_flag & FC_DISC_DELAYED) {
spin_unlock_irq(shost->host_lock);
+ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ "3334 Delay fc port discovery for %d seconds\n",
+ phba->fc_ratov);
mod_timer(&vport->delayed_disc_tmo,
- jiffies + HZ * phba->fc_ratov);
+ jiffies + msecs_to_jiffies(1000 * phba->fc_ratov));
return;
}
spin_unlock_irq(shost->host_lock);
@@ -7253,7 +7363,7 @@ lpfc_retry_pport_discovery(struct lpfc_hba *phba)
return;
shost = lpfc_shost_from_vport(phba->pport);
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
@@ -7757,7 +7867,8 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
/* Start a timer to unblock fabric iocbs after 100ms */
if (!blocked)
- mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
+ mod_timer(&phba->fabric_block_timer,
+ jiffies + msecs_to_jiffies(100));
return;
}
@@ -8044,7 +8155,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
rxid, 1);
/* Check if TXQ queue needs to be serviced */
- if (pring->txq_cnt)
+ if (!(list_empty(&pring->txq)))
lpfc_worker_wake_up(phba);
return;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index d7096ad..60d6ca2 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -160,11 +160,12 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
if (!list_empty(&evtp->evt_listp))
return;
+ evtp->evt_arg1 = lpfc_nlp_get(ndlp);
+
spin_lock_irq(&phba->hbalock);
/* We need to hold the node by incrementing the reference
* count until this queued work is done
*/
- evtp->evt_arg1 = lpfc_nlp_get(ndlp);
if (evtp->evt_arg1) {
evtp->evt = LPFC_EVT_DEV_LOSS;
list_add_tail(&evtp->evt_listp, &phba->work_list);
@@ -691,12 +692,15 @@ lpfc_work_done(struct lpfc_hba *phba)
/* Set the lpfc data pending flag */
set_bit(LPFC_DATA_READY, &phba->data_flags);
} else {
- pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
- lpfc_sli_handle_slow_ring_event(phba, pring,
- (status &
- HA_RXMASK));
+ if (phba->link_state >= LPFC_LINK_UP) {
+ pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+ lpfc_sli_handle_slow_ring_event(phba, pring,
+ (status &
+ HA_RXMASK));
+ }
}
- if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt)
+ if ((phba->sli_rev == LPFC_SLI_REV4) &
+ (!list_empty(&pring->txq)))
lpfc_drain_txq(phba);
/*
* Turn on Ring interrupts
@@ -1005,9 +1009,6 @@ lpfc_linkup(struct lpfc_hba *phba)
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
lpfc_linkup_port(vports[i]);
lpfc_destroy_vport_work_array(phba, vports);
- if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
- (phba->sli_rev < LPFC_SLI_REV4))
- lpfc_issue_clear_la(phba, phba->pport);
return 0;
}
@@ -1433,7 +1434,8 @@ lpfc_register_fcf(struct lpfc_hba *phba)
if (phba->fcf.fcf_flag & FCF_REGISTERED) {
phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
phba->hba_flag &= ~FCF_TS_INPROG;
- if (phba->pport->port_state != LPFC_FLOGI) {
+ if (phba->pport->port_state != LPFC_FLOGI &&
+ phba->pport->fc_flag & FC_FABRIC) {
phba->hba_flag |= FCF_RR_INPROG;
spin_unlock_irq(&phba->hbalock);
lpfc_initial_flogi(phba->pport);
@@ -1732,7 +1734,7 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf)
* use through a sequence of @fcf_cnt eligible FCF records with equal
* probability. To perform integer manunipulation of random numbers with
* size unit32_t, the lower 16 bits of the 32-bit random number returned
- * from random32() are taken as the random random number generated.
+ * from prandom_u32() are taken as the random random number generated.
*
* Returns true when outcome is for the newly read FCF record should be
* chosen; otherwise, return false when outcome is for keeping the previously
@@ -1744,7 +1746,7 @@ lpfc_sli4_new_fcf_random_select(struct lpfc_hba *phba, uint32_t fcf_cnt)
uint32_t rand_num;
/* Get 16-bit uniform random number */
- rand_num = (0xFFFF & random32());
+ rand_num = 0xFFFF & prandom_u32();
/* Decision with probability 1/fcf_cnt */
if ((fcf_cnt * rand_num) < 0xFFFF)
@@ -1792,6 +1794,8 @@ lpfc_sli4_fcf_rec_mbox_parse(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
virt_addr = mboxq->sge_array->addr[0];
shdr = (union lpfc_sli4_cfg_shdr *)virt_addr;
+ lpfc_sli_pcimem_bcopy(shdr, shdr,
+ sizeof(union lpfc_sli4_cfg_shdr));
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status) {
@@ -2265,8 +2269,11 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
"2836 New FCF matches in-use "
- "FCF (x%x)\n",
- phba->fcf.current_rec.fcf_indx);
+ "FCF (x%x), port_state:x%x, "
+ "fc_flag:x%x\n",
+ phba->fcf.current_rec.fcf_indx,
+ phba->pport->port_state,
+ phba->pport->fc_flag);
goto out;
} else
lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
@@ -2380,7 +2387,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
phba->fcf.eligible_fcf_cnt = 1;
/* Seeding the random number generator for random selection */
seed = (uint32_t)(0xFFFFFFFF & jiffies);
- srandom32(seed);
+ prandom_seed(seed);
}
spin_unlock_irq(&phba->hbalock);
goto read_next_fcf;
@@ -2791,7 +2798,19 @@ void
lpfc_issue_init_vpi(struct lpfc_vport *vport)
{
LPFC_MBOXQ_t *mboxq;
- int rc;
+ int rc, vpi;
+
+ if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) {
+ vpi = lpfc_alloc_vpi(vport->phba);
+ if (!vpi) {
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_MBOX,
+ "3303 Failed to obtain vport vpi\n");
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ return;
+ }
+ vport->vpi = vpi;
+ }
mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
@@ -2888,6 +2907,16 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
goto out_free_mem;
}
+
+ /* If the VFI is already registered, there is nothing else to do
+ * Unless this was a VFI update and we are in PT2PT mode, then
+ * we should drop through to set the port state to ready.
+ */
+ if (vport->fc_flag & FC_VFI_REGISTERED)
+ if (!(phba->sli_rev == LPFC_SLI_REV4 &&
+ vport->fc_flag & FC_PT2PT))
+ goto out_free_mem;
+
/* The VPI is implicitly registered when the VFI is registered */
spin_lock_irq(shost->host_lock);
vport->vpi_state |= LPFC_VPI_REGISTERED;
@@ -2903,6 +2932,13 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
goto out_free_mem;
}
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+ "3313 cmpl reg vfi port_state:%x fc_flag:%x myDid:%x "
+ "alpacnt:%d LinkState:%x topology:%x\n",
+ vport->port_state, vport->fc_flag, vport->fc_myDID,
+ vport->phba->alpa_map[0],
+ phba->link_state, phba->fc_topology);
+
if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
/*
* For private loop or for NPort pt2pt,
@@ -2915,7 +2951,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
/* Use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
/* Start discovery */
- lpfc_disc_start(vport);
+ if (vport->fc_flag & FC_PT2PT)
+ vport->port_state = LPFC_VPORT_READY;
+ else
+ lpfc_disc_start(vport);
} else {
lpfc_start_fdiscs(phba);
lpfc_do_scr_ns_plogi(phba, vport);
@@ -2980,6 +3019,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
struct lpfc_dmabuf *mp;
int rc;
struct fcf_record *fcf_record;
+ uint32_t fc_flags = 0;
spin_lock_irq(&phba->hbalock);
switch (bf_get(lpfc_mbx_read_top_link_spd, la)) {
@@ -2996,6 +3036,15 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
break;
}
+ if (phba->fc_topology &&
+ phba->fc_topology != bf_get(lpfc_mbx_read_top_topology, la)) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3314 Toplogy changed was 0x%x is 0x%x\n",
+ phba->fc_topology,
+ bf_get(lpfc_mbx_read_top_topology, la));
+ phba->fc_topology_changed = 1;
+ }
+
phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
@@ -3011,11 +3060,8 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
"1309 Link Up Event npiv not supported in loop "
"topology\n");
/* Get Loop Map information */
- if (bf_get(lpfc_mbx_read_top_il, la)) {
- spin_lock(shost->host_lock);
- vport->fc_flag |= FC_LBIT;
- spin_unlock(shost->host_lock);
- }
+ if (bf_get(lpfc_mbx_read_top_il, la))
+ fc_flags |= FC_LBIT;
vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la);
i = la->lilpBde64.tus.f.bdeSize;
@@ -3064,12 +3110,16 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
}
vport->fc_myDID = phba->fc_pref_DID;
- spin_lock(shost->host_lock);
- vport->fc_flag |= FC_LBIT;
- spin_unlock(shost->host_lock);
+ fc_flags |= FC_LBIT;
}
spin_unlock_irq(&phba->hbalock);
+ if (fc_flags) {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag |= fc_flags;
+ spin_unlock_irq(shost->host_lock);
+ }
+
lpfc_linkup(phba);
sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!sparam_mbox)
@@ -3237,8 +3287,7 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
vport->fc_flag &= ~FC_BYPASSED_MODE;
spin_unlock_irq(shost->host_lock);
- if ((phba->fc_eventTag < la->eventTag) ||
- (phba->fc_eventTag == la->eventTag)) {
+ if (phba->fc_eventTag <= la->eventTag) {
phba->fc_stat.LinkMultiEvent++;
if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)
if (phba->fc_eventTag != 0)
@@ -3246,16 +3295,18 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
phba->fc_eventTag = la->eventTag;
- spin_lock_irq(&phba->hbalock);
- if (bf_get(lpfc_mbx_read_top_mm, la))
- phba->sli.sli_flag |= LPFC_MENLO_MAINT;
- else
- phba->sli.sli_flag &= ~LPFC_MENLO_MAINT;
- spin_unlock_irq(&phba->hbalock);
+ if (phba->sli_rev < LPFC_SLI_REV4) {
+ spin_lock_irq(&phba->hbalock);
+ if (bf_get(lpfc_mbx_read_top_mm, la))
+ phba->sli.sli_flag |= LPFC_MENLO_MAINT;
+ else
+ phba->sli.sli_flag &= ~LPFC_MENLO_MAINT;
+ spin_unlock_irq(&phba->hbalock);
+ }
phba->link_events++;
if ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) &&
- (!bf_get(lpfc_mbx_read_top_mm, la))) {
+ !(phba->sli.sli_flag & LPFC_MENLO_MAINT)) {
phba->fc_stat.LinkUp++;
if (phba->link_flag & LS_LOOPBACK_MODE) {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -3300,8 +3351,8 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
bf_get(lpfc_mbx_read_top_fa, la));
lpfc_mbx_issue_link_down(phba);
}
- if ((bf_get(lpfc_mbx_read_top_mm, la)) &&
- (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)) {
+ if ((phba->sli.sli_flag & LPFC_MENLO_MAINT) &&
+ ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP))) {
if (phba->link_state != LPFC_LINK_DOWN) {
phba->fc_stat.LinkDown++;
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -3329,8 +3380,9 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
}
- if (bf_get(lpfc_mbx_read_top_fa, la)) {
- if (bf_get(lpfc_mbx_read_top_mm, la))
+ if ((phba->sli_rev < LPFC_SLI_REV4) &&
+ bf_get(lpfc_mbx_read_top_fa, la)) {
+ if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
lpfc_issue_clear_la(phba, vport);
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
"1311 fa %d\n",
@@ -4221,7 +4273,7 @@ lpfc_set_disctmo(struct lpfc_vport *vport)
tmo, vport->port_state, vport->fc_flag);
}
- mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
+ mod_timer(&vport->fc_disctmo, jiffies + msecs_to_jiffies(1000 * tmo));
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_DISC_TMO;
spin_unlock_irq(shost->host_lock);
@@ -4354,7 +4406,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
with an error */
list_move_tail(&iocb->list,
&completions);
- pring->txq_cnt--;
}
}
spin_unlock_irq(&phba->hbalock);
@@ -4936,8 +4987,12 @@ lpfc_disc_start(struct lpfc_vport *vport)
uint32_t clear_la_pending;
int did_changed;
- if (!lpfc_is_link_up(phba))
+ if (!lpfc_is_link_up(phba)) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+ "3315 Link is not up %x\n",
+ phba->link_state);
return;
+ }
if (phba->link_state == LPFC_CLEAR_LA)
clear_la_pending = 1;
@@ -4970,11 +5025,13 @@ lpfc_disc_start(struct lpfc_vport *vport)
if (num_sent)
return;
- /* Register the VPI for SLI3, NON-NPIV only. */
+ /* Register the VPI for SLI3, NPIV only. */
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
!(vport->fc_flag & FC_PT2PT) &&
!(vport->fc_flag & FC_RSCN_MODE) &&
(phba->sli_rev < LPFC_SLI_REV4)) {
+ if (vport->port_type == LPFC_PHYSICAL_PORT)
+ lpfc_issue_clear_la(phba, vport);
lpfc_issue_reg_vpi(phba, vport);
return;
}
@@ -5055,7 +5112,6 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
(icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
list_move_tail(&iocb->list, &completions);
- pring->txq_cnt--;
}
}
@@ -5398,7 +5454,8 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if (vport->cfg_fdmi_on == 1)
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
else
- mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
+ mod_timer(&vport->fc_fdmitmo,
+ jiffies + msecs_to_jiffies(1000 * 60));
/* decrement the node reference count held for this callback
* function.
@@ -5843,7 +5900,7 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
struct lpfc_vport **vports;
struct lpfc_nodelist *ndlp;
struct Scsi_Host *shost;
- int i, rc;
+ int i = 0, rc;
/* Unregister RPIs */
if (lpfc_fcf_inuse(phba))
@@ -5871,6 +5928,20 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
spin_unlock_irq(shost->host_lock);
}
lpfc_destroy_vport_work_array(phba, vports);
+ if (i == 0 && (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED))) {
+ ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+ if (ndlp)
+ lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
+ lpfc_cleanup_pending_mbox(phba->pport);
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_sli4_unreg_all_rpis(phba->pport);
+ lpfc_mbx_unreg_vpi(phba->pport);
+ shost = lpfc_shost_from_vport(phba->pport);
+ spin_lock_irq(shost->host_lock);
+ phba->pport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+ phba->pport->vpi_state &= ~LPFC_VPI_REGISTERED;
+ spin_unlock_irq(shost->host_lock);
+ }
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_all_cmd(phba);
@@ -6087,12 +6158,44 @@ lpfc_read_fcf_conn_tbl(struct lpfc_hba *phba,
memcpy(&conn_entry->conn_rec, &conn_rec[i],
sizeof(struct lpfc_fcf_conn_rec));
conn_entry->conn_rec.vlan_tag =
- le16_to_cpu(conn_entry->conn_rec.vlan_tag) & 0xFFF;
+ conn_entry->conn_rec.vlan_tag;
conn_entry->conn_rec.flags =
- le16_to_cpu(conn_entry->conn_rec.flags);
+ conn_entry->conn_rec.flags;
list_add_tail(&conn_entry->list,
&phba->fcf_conn_rec_list);
}
+
+ if (!list_empty(&phba->fcf_conn_rec_list)) {
+ i = 0;
+ list_for_each_entry(conn_entry, &phba->fcf_conn_rec_list,
+ list) {
+ conn_rec = &conn_entry->conn_rec;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3345 FCF connection list rec[%02d]: "
+ "flags:x%04x, vtag:x%04x, "
+ "fabric_name:x%02x:%02x:%02x:%02x:"
+ "%02x:%02x:%02x:%02x, "
+ "switch_name:x%02x:%02x:%02x:%02x:"
+ "%02x:%02x:%02x:%02x\n", i++,
+ conn_rec->flags, conn_rec->vlan_tag,
+ conn_rec->fabric_name[0],
+ conn_rec->fabric_name[1],
+ conn_rec->fabric_name[2],
+ conn_rec->fabric_name[3],
+ conn_rec->fabric_name[4],
+ conn_rec->fabric_name[5],
+ conn_rec->fabric_name[6],
+ conn_rec->fabric_name[7],
+ conn_rec->switch_name[0],
+ conn_rec->switch_name[1],
+ conn_rec->switch_name[2],
+ conn_rec->switch_name[3],
+ conn_rec->switch_name[4],
+ conn_rec->switch_name[5],
+ conn_rec->switch_name[6],
+ conn_rec->switch_name[7]);
+ }
+ }
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 7398ca8..6f927d3 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2011 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -538,6 +538,7 @@ struct fc_vft_header {
#define ELS_CMD_ECHO 0x10000000
#define ELS_CMD_TEST 0x11000000
#define ELS_CMD_RRQ 0x12000000
+#define ELS_CMD_REC 0x13000000
#define ELS_CMD_PRLI 0x20100014
#define ELS_CMD_PRLO 0x21100014
#define ELS_CMD_PRLO_ACC 0x02100014
@@ -574,6 +575,7 @@ struct fc_vft_header {
#define ELS_CMD_ECHO 0x10
#define ELS_CMD_TEST 0x11
#define ELS_CMD_RRQ 0x12
+#define ELS_CMD_REC 0x13
#define ELS_CMD_PRLI 0x14001020
#define ELS_CMD_PRLO 0x14001021
#define ELS_CMD_PRLO_ACC 0x14001002
@@ -1665,6 +1667,7 @@ enum lpfc_protgrp_type {
#define BG_OP_IN_CSUM_OUT_CSUM 0x5
#define BG_OP_IN_CRC_OUT_CSUM 0x6
#define BG_OP_IN_CSUM_OUT_CRC 0x7
+#define BG_OP_RAW_MODE 0x8
struct lpfc_pde5 {
uint32_t word0;
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index a47cfbd..4ec3d7c 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2009-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2009-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -106,6 +106,7 @@ struct lpfc_sli_intf {
#define LPFC_SLI4_MB_WORD_COUNT 64
#define LPFC_MAX_MQ_PAGE 8
+#define LPFC_MAX_WQ_PAGE_V0 4
#define LPFC_MAX_WQ_PAGE 8
#define LPFC_MAX_CQ_PAGE 4
#define LPFC_MAX_EQ_PAGE 8
@@ -199,6 +200,11 @@ struct lpfc_sli_intf {
#define LPFC_MAX_IMAX 5000000
#define LPFC_DEF_IMAX 50000
+#define LPFC_MIN_CPU_MAP 0
+#define LPFC_MAX_CPU_MAP 2
+#define LPFC_HBA_CPU_MAP 1
+#define LPFC_DRIVER_CPU_MAP 2 /* Default */
+
/* PORT_CAPABILITIES constants. */
#define LPFC_MAX_SUPPORTED_PAGES 8
@@ -620,7 +626,7 @@ struct lpfc_register {
#define lpfc_sliport_status_rdy_SHIFT 23
#define lpfc_sliport_status_rdy_MASK 0x1
#define lpfc_sliport_status_rdy_WORD word0
-#define MAX_IF_TYPE_2_RESETS 1000
+#define MAX_IF_TYPE_2_RESETS 6
#define LPFC_CTL_PORT_CTL_OFFSET 0x408
#define lpfc_sliport_ctrl_end_SHIFT 30
@@ -703,24 +709,41 @@ struct lpfc_register {
* BAR0. The offsets are the same so the driver must account for
* any base address difference.
*/
-#define LPFC_RQ_DOORBELL 0x00A0
-#define lpfc_rq_doorbell_num_posted_SHIFT 16
-#define lpfc_rq_doorbell_num_posted_MASK 0x3FFF
-#define lpfc_rq_doorbell_num_posted_WORD word0
-#define lpfc_rq_doorbell_id_SHIFT 0
-#define lpfc_rq_doorbell_id_MASK 0xFFFF
-#define lpfc_rq_doorbell_id_WORD word0
-
-#define LPFC_WQ_DOORBELL 0x0040
-#define lpfc_wq_doorbell_num_posted_SHIFT 24
-#define lpfc_wq_doorbell_num_posted_MASK 0x00FF
-#define lpfc_wq_doorbell_num_posted_WORD word0
-#define lpfc_wq_doorbell_index_SHIFT 16
-#define lpfc_wq_doorbell_index_MASK 0x00FF
-#define lpfc_wq_doorbell_index_WORD word0
-#define lpfc_wq_doorbell_id_SHIFT 0
-#define lpfc_wq_doorbell_id_MASK 0xFFFF
-#define lpfc_wq_doorbell_id_WORD word0
+#define LPFC_ULP0_RQ_DOORBELL 0x00A0
+#define LPFC_ULP1_RQ_DOORBELL 0x00C0
+#define lpfc_rq_db_list_fm_num_posted_SHIFT 24
+#define lpfc_rq_db_list_fm_num_posted_MASK 0x00FF
+#define lpfc_rq_db_list_fm_num_posted_WORD word0
+#define lpfc_rq_db_list_fm_index_SHIFT 16
+#define lpfc_rq_db_list_fm_index_MASK 0x00FF
+#define lpfc_rq_db_list_fm_index_WORD word0
+#define lpfc_rq_db_list_fm_id_SHIFT 0
+#define lpfc_rq_db_list_fm_id_MASK 0xFFFF
+#define lpfc_rq_db_list_fm_id_WORD word0
+#define lpfc_rq_db_ring_fm_num_posted_SHIFT 16
+#define lpfc_rq_db_ring_fm_num_posted_MASK 0x3FFF
+#define lpfc_rq_db_ring_fm_num_posted_WORD word0
+#define lpfc_rq_db_ring_fm_id_SHIFT 0
+#define lpfc_rq_db_ring_fm_id_MASK 0xFFFF
+#define lpfc_rq_db_ring_fm_id_WORD word0
+
+#define LPFC_ULP0_WQ_DOORBELL 0x0040
+#define LPFC_ULP1_WQ_DOORBELL 0x0060
+#define lpfc_wq_db_list_fm_num_posted_SHIFT 24
+#define lpfc_wq_db_list_fm_num_posted_MASK 0x00FF
+#define lpfc_wq_db_list_fm_num_posted_WORD word0
+#define lpfc_wq_db_list_fm_index_SHIFT 16
+#define lpfc_wq_db_list_fm_index_MASK 0x00FF
+#define lpfc_wq_db_list_fm_index_WORD word0
+#define lpfc_wq_db_list_fm_id_SHIFT 0
+#define lpfc_wq_db_list_fm_id_MASK 0xFFFF
+#define lpfc_wq_db_list_fm_id_WORD word0
+#define lpfc_wq_db_ring_fm_num_posted_SHIFT 16
+#define lpfc_wq_db_ring_fm_num_posted_MASK 0x3FFF
+#define lpfc_wq_db_ring_fm_num_posted_WORD word0
+#define lpfc_wq_db_ring_fm_id_SHIFT 0
+#define lpfc_wq_db_ring_fm_id_MASK 0xFFFF
+#define lpfc_wq_db_ring_fm_id_WORD word0
#define LPFC_EQCQ_DOORBELL 0x0120
#define lpfc_eqcq_doorbell_se_SHIFT 31
@@ -1131,12 +1154,22 @@ struct lpfc_mbx_wq_create {
struct { /* Version 0 Request */
uint32_t word0;
#define lpfc_mbx_wq_create_num_pages_SHIFT 0
-#define lpfc_mbx_wq_create_num_pages_MASK 0x0000FFFF
+#define lpfc_mbx_wq_create_num_pages_MASK 0x000000FF
#define lpfc_mbx_wq_create_num_pages_WORD word0
+#define lpfc_mbx_wq_create_dua_SHIFT 8
+#define lpfc_mbx_wq_create_dua_MASK 0x00000001
+#define lpfc_mbx_wq_create_dua_WORD word0
#define lpfc_mbx_wq_create_cq_id_SHIFT 16
#define lpfc_mbx_wq_create_cq_id_MASK 0x0000FFFF
#define lpfc_mbx_wq_create_cq_id_WORD word0
- struct dma_address page[LPFC_MAX_WQ_PAGE];
+ struct dma_address page[LPFC_MAX_WQ_PAGE_V0];
+ uint32_t word9;
+#define lpfc_mbx_wq_create_bua_SHIFT 0
+#define lpfc_mbx_wq_create_bua_MASK 0x00000001
+#define lpfc_mbx_wq_create_bua_WORD word9
+#define lpfc_mbx_wq_create_ulp_num_SHIFT 8
+#define lpfc_mbx_wq_create_ulp_num_MASK 0x000000FF
+#define lpfc_mbx_wq_create_ulp_num_WORD word9
} request;
struct { /* Version 1 Request */
uint32_t word0; /* Word 0 is the same as in v0 */
@@ -1160,6 +1193,17 @@ struct lpfc_mbx_wq_create {
#define lpfc_mbx_wq_create_q_id_SHIFT 0
#define lpfc_mbx_wq_create_q_id_MASK 0x0000FFFF
#define lpfc_mbx_wq_create_q_id_WORD word0
+ uint32_t doorbell_offset;
+ uint32_t word2;
+#define lpfc_mbx_wq_create_bar_set_SHIFT 0
+#define lpfc_mbx_wq_create_bar_set_MASK 0x0000FFFF
+#define lpfc_mbx_wq_create_bar_set_WORD word2
+#define WQ_PCI_BAR_0_AND_1 0x00
+#define WQ_PCI_BAR_2_AND_3 0x01
+#define WQ_PCI_BAR_4_AND_5 0x02
+#define lpfc_mbx_wq_create_db_format_SHIFT 16
+#define lpfc_mbx_wq_create_db_format_MASK 0x0000FFFF
+#define lpfc_mbx_wq_create_db_format_WORD word2
} response;
} u;
};
@@ -1223,14 +1267,31 @@ struct lpfc_mbx_rq_create {
#define lpfc_mbx_rq_create_num_pages_SHIFT 0
#define lpfc_mbx_rq_create_num_pages_MASK 0x0000FFFF
#define lpfc_mbx_rq_create_num_pages_WORD word0
+#define lpfc_mbx_rq_create_dua_SHIFT 16
+#define lpfc_mbx_rq_create_dua_MASK 0x00000001
+#define lpfc_mbx_rq_create_dua_WORD word0
+#define lpfc_mbx_rq_create_bqu_SHIFT 17
+#define lpfc_mbx_rq_create_bqu_MASK 0x00000001
+#define lpfc_mbx_rq_create_bqu_WORD word0
+#define lpfc_mbx_rq_create_ulp_num_SHIFT 24
+#define lpfc_mbx_rq_create_ulp_num_MASK 0x000000FF
+#define lpfc_mbx_rq_create_ulp_num_WORD word0
struct rq_context context;
struct dma_address page[LPFC_MAX_WQ_PAGE];
} request;
struct {
uint32_t word0;
-#define lpfc_mbx_rq_create_q_id_SHIFT 0
-#define lpfc_mbx_rq_create_q_id_MASK 0x0000FFFF
-#define lpfc_mbx_rq_create_q_id_WORD word0
+#define lpfc_mbx_rq_create_q_id_SHIFT 0
+#define lpfc_mbx_rq_create_q_id_MASK 0x0000FFFF
+#define lpfc_mbx_rq_create_q_id_WORD word0
+ uint32_t doorbell_offset;
+ uint32_t word2;
+#define lpfc_mbx_rq_create_bar_set_SHIFT 0
+#define lpfc_mbx_rq_create_bar_set_MASK 0x0000FFFF
+#define lpfc_mbx_rq_create_bar_set_WORD word2
+#define lpfc_mbx_rq_create_db_format_SHIFT 16
+#define lpfc_mbx_rq_create_db_format_MASK 0x0000FFFF
+#define lpfc_mbx_rq_create_db_format_WORD word2
} response;
} u;
};
@@ -1388,6 +1449,33 @@ struct lpfc_mbx_get_rsrc_extent_info {
} u;
};
+struct lpfc_mbx_query_fw_config {
+ struct mbox_header header;
+ struct {
+ uint32_t config_number;
+#define LPFC_FC_FCOE 0x00000007
+ uint32_t asic_revision;
+ uint32_t physical_port;
+ uint32_t function_mode;
+#define LPFC_FCOE_INI_MODE 0x00000040
+#define LPFC_FCOE_TGT_MODE 0x00000080
+#define LPFC_DUA_MODE 0x00000800
+ uint32_t ulp0_mode;
+#define LPFC_ULP_FCOE_INIT_MODE 0x00000040
+#define LPFC_ULP_FCOE_TGT_MODE 0x00000080
+ uint32_t ulp0_nap_words[12];
+ uint32_t ulp1_mode;
+ uint32_t ulp1_nap_words[12];
+ uint32_t function_capabilities;
+ uint32_t cqid_base;
+ uint32_t cqid_tot;
+ uint32_t eqid_base;
+ uint32_t eqid_tot;
+ uint32_t ulp0_nap2_words[2];
+ uint32_t ulp1_nap2_words[2];
+ } rsp;
+};
+
struct lpfc_id_range {
uint32_t word5;
#define lpfc_mbx_rsrc_id_word4_0_SHIFT 0
@@ -1803,51 +1891,6 @@ struct lpfc_mbx_redisc_fcf_tbl {
#define lpfc_mbx_redisc_fcf_index_WORD word12
};
-struct lpfc_mbx_query_fw_cfg {
- struct mbox_header header;
- uint32_t config_number;
- uint32_t asic_rev;
- uint32_t phys_port;
- uint32_t function_mode;
-/* firmware Function Mode */
-#define lpfc_function_mode_toe_SHIFT 0
-#define lpfc_function_mode_toe_MASK 0x00000001
-#define lpfc_function_mode_toe_WORD function_mode
-#define lpfc_function_mode_nic_SHIFT 1
-#define lpfc_function_mode_nic_MASK 0x00000001
-#define lpfc_function_mode_nic_WORD function_mode
-#define lpfc_function_mode_rdma_SHIFT 2
-#define lpfc_function_mode_rdma_MASK 0x00000001
-#define lpfc_function_mode_rdma_WORD function_mode
-#define lpfc_function_mode_vm_SHIFT 3
-#define lpfc_function_mode_vm_MASK 0x00000001
-#define lpfc_function_mode_vm_WORD function_mode
-#define lpfc_function_mode_iscsi_i_SHIFT 4
-#define lpfc_function_mode_iscsi_i_MASK 0x00000001
-#define lpfc_function_mode_iscsi_i_WORD function_mode
-#define lpfc_function_mode_iscsi_t_SHIFT 5
-#define lpfc_function_mode_iscsi_t_MASK 0x00000001
-#define lpfc_function_mode_iscsi_t_WORD function_mode
-#define lpfc_function_mode_fcoe_i_SHIFT 6
-#define lpfc_function_mode_fcoe_i_MASK 0x00000001
-#define lpfc_function_mode_fcoe_i_WORD function_mode
-#define lpfc_function_mode_fcoe_t_SHIFT 7
-#define lpfc_function_mode_fcoe_t_MASK 0x00000001
-#define lpfc_function_mode_fcoe_t_WORD function_mode
-#define lpfc_function_mode_dal_SHIFT 8
-#define lpfc_function_mode_dal_MASK 0x00000001
-#define lpfc_function_mode_dal_WORD function_mode
-#define lpfc_function_mode_lro_SHIFT 9
-#define lpfc_function_mode_lro_MASK 0x00000001
-#define lpfc_function_mode_lro_WORD function_mode
-#define lpfc_function_mode_flex10_SHIFT 10
-#define lpfc_function_mode_flex10_MASK 0x00000001
-#define lpfc_function_mode_flex10_WORD function_mode
-#define lpfc_function_mode_ncsi_SHIFT 11
-#define lpfc_function_mode_ncsi_MASK 0x00000001
-#define lpfc_function_mode_ncsi_WORD function_mode
-};
-
/* Status field for embedded SLI_CONFIG mailbox command */
#define STATUS_SUCCESS 0x0
#define STATUS_FAILED 0x1
@@ -1920,6 +1963,9 @@ struct lpfc_mbx_init_vfi {
struct lpfc_mbx_reg_vfi {
uint32_t word1;
+#define lpfc_reg_vfi_upd_SHIFT 29
+#define lpfc_reg_vfi_upd_MASK 0x00000001
+#define lpfc_reg_vfi_upd_WORD word1
#define lpfc_reg_vfi_vp_SHIFT 28
#define lpfc_reg_vfi_vp_MASK 0x00000001
#define lpfc_reg_vfi_vp_WORD word1
@@ -2965,7 +3011,7 @@ struct lpfc_mqe {
struct lpfc_mbx_read_config rd_config;
struct lpfc_mbx_request_features req_ftrs;
struct lpfc_mbx_post_hdr_tmpl hdr_tmpl;
- struct lpfc_mbx_query_fw_cfg query_fw_cfg;
+ struct lpfc_mbx_query_fw_config query_fw_cfg;
struct lpfc_mbx_supp_pages supp_pages;
struct lpfc_mbx_pc_sli4_params sli4_params;
struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index c20eec7..e0b20fa 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/miscdevice.h>
+#include <linux/percpu.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -58,6 +59,10 @@ char *_dump_buf_dif;
unsigned long _dump_buf_dif_order;
spinlock_t _dump_buf_lock;
+/* Used when mapping IRQ vectors in a driver centric manner */
+uint16_t *lpfc_used_cpu;
+uint32_t lpfc_present_cpu;
+
static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
static int lpfc_post_rcv_buf(struct lpfc_hba *);
static int lpfc_sli4_queue_verify(struct lpfc_hba *);
@@ -541,13 +546,16 @@ lpfc_config_port_post(struct lpfc_hba *phba)
/* Set up ring-0 (ELS) timer */
timeout = phba->fc_ratov * 2;
- mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+ mod_timer(&vport->els_tmofunc,
+ jiffies + msecs_to_jiffies(1000 * timeout));
/* Set up heart beat (HB) timer */
- mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+ mod_timer(&phba->hb_tmofunc,
+ jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
phba->hb_outstanding = 0;
phba->last_completion_time = jiffies;
/* Set up error attention (ERATT) polling timer */
- mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
+ mod_timer(&phba->eratt_poll,
+ jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
if (phba->hba_flag & LINK_DISABLED) {
lpfc_printf_log(phba,
@@ -839,7 +847,6 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba)
* way, nothing should be on txcmplq as it will NEVER complete.
*/
list_splice_init(&pring->txcmplq, &completions);
- pring->txcmplq_cnt = 0;
spin_unlock_irq(&phba->hbalock);
/* Cancel all the IOCBs from the completions list */
@@ -909,9 +916,9 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
psb->pCmd = NULL;
psb->status = IOSTAT_SUCCESS;
}
- spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
- list_splice(&aborts, &phba->lpfc_scsi_buf_list);
- spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+ spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
+ list_splice(&aborts, &phba->lpfc_scsi_buf_list_put);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
return 0;
}
@@ -1022,7 +1029,8 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
!(phba->link_state == LPFC_HBA_ERROR) &&
!(phba->pport->load_flag & FC_UNLOADING))
mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+ jiffies +
+ msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
return;
}
@@ -1065,15 +1073,18 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
spin_lock_irq(&phba->pport->work_port_lock);
- if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
- jiffies)) {
+ if (time_after(phba->last_completion_time +
+ msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL),
+ jiffies)) {
spin_unlock_irq(&phba->pport->work_port_lock);
if (!phba->hb_outstanding)
mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+ jiffies +
+ msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
else
mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+ jiffies +
+ msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT));
return;
}
spin_unlock_irq(&phba->pport->work_port_lock);
@@ -1105,7 +1116,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
if (!pmboxq) {
mod_timer(&phba->hb_tmofunc,
jiffies +
- HZ * LPFC_HB_MBOX_INTERVAL);
+ msecs_to_jiffies(1000 *
+ LPFC_HB_MBOX_INTERVAL));
return;
}
@@ -1121,7 +1133,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
phba->mbox_mem_pool);
mod_timer(&phba->hb_tmofunc,
jiffies +
- HZ * LPFC_HB_MBOX_INTERVAL);
+ msecs_to_jiffies(1000 *
+ LPFC_HB_MBOX_INTERVAL));
return;
}
phba->skipped_hb = 0;
@@ -1137,7 +1150,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
phba->skipped_hb = jiffies;
mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+ jiffies +
+ msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT));
return;
} else {
/*
@@ -1151,7 +1165,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
jiffies_to_msecs(jiffies
- phba->last_completion_time));
mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+ jiffies +
+ msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT));
}
}
}
@@ -1192,7 +1207,7 @@ lpfc_offline_eratt(struct lpfc_hba *phba)
* This routine is called to bring a SLI4 HBA offline when HBA hardware error
* other than Port Error 6 has been detected.
**/
-static void
+void
lpfc_sli4_offline_eratt(struct lpfc_hba *phba)
{
lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT);
@@ -2634,6 +2649,7 @@ lpfc_online(struct lpfc_hba *phba)
struct lpfc_vport *vport;
struct lpfc_vport **vports;
int i;
+ bool vpis_cleared = false;
if (!phba)
return 0;
@@ -2657,6 +2673,10 @@ lpfc_online(struct lpfc_hba *phba)
lpfc_unblock_mgmt_io(phba);
return 1;
}
+ spin_lock_irq(&phba->hbalock);
+ if (!phba->sli4_hba.max_cfg_param.vpi_used)
+ vpis_cleared = true;
+ spin_unlock_irq(&phba->hbalock);
} else {
if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */
lpfc_unblock_mgmt_io(phba);
@@ -2673,8 +2693,13 @@ lpfc_online(struct lpfc_hba *phba)
vports[i]->fc_flag &= ~FC_OFFLINE_MODE;
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
- if (phba->sli_rev == LPFC_SLI_REV4)
+ if (phba->sli_rev == LPFC_SLI_REV4) {
vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+ if ((vpis_cleared) &&
+ (vports[i]->port_type !=
+ LPFC_PHYSICAL_PORT))
+ vports[i]->vpi = 0;
+ }
spin_unlock_irq(shost->host_lock);
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -2834,16 +2859,30 @@ lpfc_scsi_free(struct lpfc_hba *phba)
struct lpfc_iocbq *io, *io_next;
spin_lock_irq(&phba->hbalock);
+
/* Release all the lpfc_scsi_bufs maintained by this host. */
- spin_lock(&phba->scsi_buf_list_lock);
- list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
+
+ spin_lock(&phba->scsi_buf_list_put_lock);
+ list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_put,
+ list) {
list_del(&sb->list);
pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
sb->dma_handle);
kfree(sb);
phba->total_scsi_bufs--;
}
- spin_unlock(&phba->scsi_buf_list_lock);
+ spin_unlock(&phba->scsi_buf_list_put_lock);
+
+ spin_lock(&phba->scsi_buf_list_get_lock);
+ list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_get,
+ list) {
+ list_del(&sb->list);
+ pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
+ sb->dma_handle);
+ kfree(sb);
+ phba->total_scsi_bufs--;
+ }
+ spin_unlock(&phba->scsi_buf_list_get_lock);
/* Release all the lpfc_iocbq entries maintained by this host. */
list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) {
@@ -2915,9 +2954,9 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
sglq_entry->state = SGL_FREED;
list_add_tail(&sglq_entry->list, &els_sgl_list);
}
- spin_lock(&phba->hbalock);
+ spin_lock_irq(&phba->hbalock);
list_splice_init(&els_sgl_list, &phba->sli4_hba.lpfc_sgl_list);
- spin_unlock(&phba->hbalock);
+ spin_unlock_irq(&phba->hbalock);
} else if (els_xri_cnt < phba->sli4_hba.els_xri_cnt) {
/* els xri-sgl shrinked */
xri_cnt = phba->sli4_hba.els_xri_cnt - els_xri_cnt;
@@ -2979,9 +3018,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
phba->sli4_hba.scsi_xri_cnt,
phba->sli4_hba.scsi_xri_max);
- spin_lock_irq(&phba->scsi_buf_list_lock);
- list_splice_init(&phba->lpfc_scsi_buf_list, &scsi_sgl_list);
- spin_unlock_irq(&phba->scsi_buf_list_lock);
+ spin_lock_irq(&phba->scsi_buf_list_get_lock);
+ spin_lock_irq(&phba->scsi_buf_list_put_lock);
+ list_splice_init(&phba->lpfc_scsi_buf_list_get, &scsi_sgl_list);
+ list_splice(&phba->lpfc_scsi_buf_list_put, &scsi_sgl_list);
+ spin_unlock_irq(&phba->scsi_buf_list_put_lock);
+ spin_unlock_irq(&phba->scsi_buf_list_get_lock);
if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) {
/* max scsi xri shrinked below the allocated scsi buffers */
@@ -2995,9 +3037,9 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
psb->dma_handle);
kfree(psb);
}
- spin_lock_irq(&phba->scsi_buf_list_lock);
+ spin_lock_irq(&phba->scsi_buf_list_get_lock);
phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt;
- spin_unlock_irq(&phba->scsi_buf_list_lock);
+ spin_unlock_irq(&phba->scsi_buf_list_get_lock);
}
/* update xris associated to remaining allocated scsi buffers */
@@ -3015,9 +3057,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
psb->cur_iocbq.sli4_lxritag = lxri;
psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
}
- spin_lock(&phba->scsi_buf_list_lock);
- list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list);
- spin_unlock(&phba->scsi_buf_list_lock);
+ spin_lock_irq(&phba->scsi_buf_list_get_lock);
+ spin_lock_irq(&phba->scsi_buf_list_put_lock);
+ list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list_get);
+ INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
+ spin_unlock_irq(&phba->scsi_buf_list_put_lock);
+ spin_unlock_irq(&phba->scsi_buf_list_get_lock);
return 0;
@@ -3165,14 +3210,10 @@ destroy_port(struct lpfc_vport *vport)
int
lpfc_get_instance(void)
{
- int instance = 0;
+ int ret;
- /* Assign an unused number */
- if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
- return -1;
- if (idr_get_new(&lpfc_hba_index, NULL, &instance))
- return -1;
- return instance;
+ ret = idr_alloc(&lpfc_hba_index, NULL, 0, 0, GFP_KERNEL);
+ return ret < 0 ? -1 : ret;
}
/**
@@ -3202,14 +3243,15 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
stat = 1;
goto finished;
}
- if (time >= 30 * HZ) {
+ if (time >= msecs_to_jiffies(30 * 1000)) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0461 Scanning longer than 30 "
"seconds. Continuing initialization\n");
stat = 1;
goto finished;
}
- if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
+ if (time >= msecs_to_jiffies(15 * 1000) &&
+ phba->link_state <= LPFC_LINK_DOWN) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0465 Link down longer than 15 "
"seconds. Continuing initialization\n");
@@ -3221,7 +3263,7 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
goto finished;
if (vport->num_disc_nodes || vport->fc_prli_sent)
goto finished;
- if (vport->fc_map_cnt == 0 && time < 2 * HZ)
+ if (vport->fc_map_cnt == 0 && time < msecs_to_jiffies(2 * 1000))
goto finished;
if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
goto finished;
@@ -4193,7 +4235,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
* If there are other active VLinks present,
* re-instantiate the Vlink using FDISC.
*/
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+ mod_timer(&ndlp->nlp_delayfunc,
+ jiffies + msecs_to_jiffies(1000));
shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
@@ -4685,23 +4728,52 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
return -ENOMEM;
/*
- * Since the sg_tablesize is module parameter, the sg_dma_buf_size
+ * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size
* used to create the sg_dma_buf_pool must be dynamically calculated.
- * 2 segments are added since the IOCB needs a command and response bde.
*/
- phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
- sizeof(struct fcp_rsp) +
- ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64));
+ /* Initialize the host templates the configured values. */
+ lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+ lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+
+ /* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */
if (phba->cfg_enable_bg) {
- phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT;
- phba->cfg_sg_dma_buf_size +=
- phba->cfg_prot_sg_seg_cnt * sizeof(struct ulp_bde64);
+ /*
+ * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd,
+ * the FCP rsp, and a BDE for each. Sice we have no control
+ * over how many protection data segments the SCSI Layer
+ * will hand us (ie: there could be one for every block
+ * in the IO), we just allocate enough BDEs to accomidate
+ * our max amount and we need to limit lpfc_sg_seg_cnt to
+ * minimize the risk of running out.
+ */
+ phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+ sizeof(struct fcp_rsp) +
+ (LPFC_MAX_SG_SEG_CNT * sizeof(struct ulp_bde64));
+
+ if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SEG_CNT_DIF)
+ phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT_DIF;
+
+ /* Total BDEs in BPL for scsi_sg_list and scsi_sg_prot_list */
+ phba->cfg_total_seg_cnt = LPFC_MAX_SG_SEG_CNT;
+ } else {
+ /*
+ * The scsi_buf for a regular I/O will hold the FCP cmnd,
+ * the FCP rsp, a BDE for each, and a BDE for up to
+ * cfg_sg_seg_cnt data segments.
+ */
+ phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+ sizeof(struct fcp_rsp) +
+ ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64));
+
+ /* Total BDEs in BPL for scsi_sg_list */
+ phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2;
}
- /* Also reinitialize the host templates with new values. */
- lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
- lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
+ "9088 sg_tablesize:%d dmabuf_size:%d total_bde:%d\n",
+ phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size,
+ phba->cfg_total_seg_cnt);
phba->max_vpi = LPFC_MAX_VPI;
/* This will be set to correct value after config_port mbox */
@@ -4767,13 +4839,13 @@ lpfc_sli_driver_resource_unset(struct lpfc_hba *phba)
static int
lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
{
+ struct lpfc_vector_map_info *cpup;
struct lpfc_sli *psli;
LPFC_MBOXQ_t *mboxq;
- int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size;
+ int rc, i, hbq_count, max_buf_size;
uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
struct lpfc_mqe *mqe;
- int longs, sli_family;
- int sges_per_segment;
+ int longs;
/* Before proceed, wait for POST done and device ready */
rc = lpfc_sli4_post_status_check(phba);
@@ -4841,11 +4913,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
phba->fc_map[1] = LPFC_FCOE_FCF_MAP1;
phba->fc_map[2] = LPFC_FCOE_FCF_MAP2;
- /* With BlockGuard we can have multiple SGEs per Data Segemnt */
- sges_per_segment = 1;
- if (phba->cfg_enable_bg)
- sges_per_segment = 2;
-
/*
* For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands
* we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple.
@@ -4856,43 +4923,71 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
sizeof(struct lpfc_sli_ring), GFP_KERNEL);
if (!phba->sli.ring)
return -ENOMEM;
+
+ /*
+ * It doesn't matter what family our adapter is in, we are
+ * limited to 2 Pages, 512 SGEs, for our SGL.
+ * There are going to be 2 reserved SGEs: 1 FCP cmnd + 1 FCP rsp
+ */
+ max_buf_size = (2 * SLI4_PAGE_SIZE);
+ if (phba->cfg_sg_seg_cnt > LPFC_MAX_SGL_SEG_CNT - 2)
+ phba->cfg_sg_seg_cnt = LPFC_MAX_SGL_SEG_CNT - 2;
+
/*
- * Since the sg_tablesize is module parameter, the sg_dma_buf_size
+ * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size
* used to create the sg_dma_buf_pool must be dynamically calculated.
- * 2 segments are added since the IOCB needs a command and response bde.
- * To insure that the scsi sgl does not cross a 4k page boundary only
- * sgl sizes of must be a power of 2.
*/
- buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) +
- (((phba->cfg_sg_seg_cnt * sges_per_segment) + 2) *
- sizeof(struct sli4_sge)));
-
- sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf);
- max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
- switch (sli_family) {
- case LPFC_SLI_INTF_FAMILY_BE2:
- case LPFC_SLI_INTF_FAMILY_BE3:
- /* There is a single hint for BE - 2 pages per BPL. */
- if (bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf) ==
- LPFC_SLI_INTF_SLI_HINT1_1)
- max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
- break;
- case LPFC_SLI_INTF_FAMILY_LNCR_A0:
- case LPFC_SLI_INTF_FAMILY_LNCR_B0:
- default:
- break;
+
+ if (phba->cfg_enable_bg) {
+ /*
+ * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd,
+ * the FCP rsp, and a SGE for each. Sice we have no control
+ * over how many protection data segments the SCSI Layer
+ * will hand us (ie: there could be one for every block
+ * in the IO), we just allocate enough SGEs to accomidate
+ * our max amount and we need to limit lpfc_sg_seg_cnt to
+ * minimize the risk of running out.
+ */
+ phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+ sizeof(struct fcp_rsp) + max_buf_size;
+
+ /* Total SGEs for scsi_sg_list and scsi_sg_prot_list */
+ phba->cfg_total_seg_cnt = LPFC_MAX_SGL_SEG_CNT;
+
+ if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SLI4_SEG_CNT_DIF)
+ phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SLI4_SEG_CNT_DIF;
+ } else {
+ /*
+ * The scsi_buf for a regular I/O will hold the FCP cmnd,
+ * the FCP rsp, a SGE for each, and a SGE for up to
+ * cfg_sg_seg_cnt data segments.
+ */
+ phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+ sizeof(struct fcp_rsp) +
+ ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge));
+
+ /* Total SGEs for scsi_sg_list */
+ phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2;
+ /*
+ * NOTE: if (phba->cfg_sg_seg_cnt + 2) <= 256 we only need
+ * to post 1 page for the SGL.
+ */
}
- for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE;
- dma_buf_size < max_buf_size && buf_size > dma_buf_size;
- dma_buf_size = dma_buf_size << 1)
- ;
- if (dma_buf_size == max_buf_size)
- phba->cfg_sg_seg_cnt = (dma_buf_size -
- sizeof(struct fcp_cmnd) - sizeof(struct fcp_rsp) -
- (2 * sizeof(struct sli4_sge))) /
- sizeof(struct sli4_sge);
- phba->cfg_sg_dma_buf_size = dma_buf_size;
+ /* Initialize the host templates with the updated values. */
+ lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+ lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+
+ if (phba->cfg_sg_dma_buf_size <= LPFC_MIN_SG_SLI4_BUF_SZ)
+ phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ;
+ else
+ phba->cfg_sg_dma_buf_size =
+ SLI4_PAGE_ALIGN(phba->cfg_sg_dma_buf_size);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
+ "9087 sg_tablesize:%d dmabuf_size:%d total_sge:%d\n",
+ phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size,
+ phba->cfg_total_seg_cnt);
/* Initialize buffer queue management fields */
hbq_count = lpfc_sli_hbq_count();
@@ -5082,6 +5177,41 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
goto out_free_fcp_eq_hdl;
}
+ phba->sli4_hba.cpu_map = kzalloc((sizeof(struct lpfc_vector_map_info) *
+ phba->sli4_hba.num_present_cpu),
+ GFP_KERNEL);
+ if (!phba->sli4_hba.cpu_map) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3327 Failed allocate memory for msi-x "
+ "interrupt vector mapping\n");
+ rc = -ENOMEM;
+ goto out_free_msix;
+ }
+ if (lpfc_used_cpu == NULL) {
+ lpfc_used_cpu = kzalloc((sizeof(uint16_t) * lpfc_present_cpu),
+ GFP_KERNEL);
+ if (!lpfc_used_cpu) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3335 Failed allocate memory for msi-x "
+ "interrupt vector mapping\n");
+ kfree(phba->sli4_hba.cpu_map);
+ rc = -ENOMEM;
+ goto out_free_msix;
+ }
+ for (i = 0; i < lpfc_present_cpu; i++)
+ lpfc_used_cpu[i] = LPFC_VECTOR_MAP_EMPTY;
+ }
+
+ /* Initialize io channels for round robin */
+ cpup = phba->sli4_hba.cpu_map;
+ rc = 0;
+ for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
+ cpup->channel_id = rc;
+ rc++;
+ if (rc >= phba->cfg_fcp_io_channel)
+ rc = 0;
+ }
+
/*
* Enable sr-iov virtual functions if supported and configured
* through the module parameter.
@@ -5101,6 +5231,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
return 0;
+out_free_msix:
+ kfree(phba->sli4_hba.msix_entries);
out_free_fcp_eq_hdl:
kfree(phba->sli4_hba.fcp_eq_hdl);
out_free_fcf_rr_bmask:
@@ -5130,6 +5262,11 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
{
struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
+ /* Free memory allocated for msi-x interrupt vector to CPU mapping */
+ kfree(phba->sli4_hba.cpu_map);
+ phba->sli4_hba.num_present_cpu = 0;
+ phba->sli4_hba.num_online_cpu = 0;
+
/* Free memory allocated for msi-x interrupt vector entries */
kfree(phba->sli4_hba.msix_entries);
@@ -5238,8 +5375,10 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
init_waitqueue_head(&phba->work_waitq);
/* Initialize the scsi buffer list used by driver for scsi IO */
- spin_lock_init(&phba->scsi_buf_list_lock);
- INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
+ spin_lock_init(&phba->scsi_buf_list_get_lock);
+ INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_get);
+ spin_lock_init(&phba->scsi_buf_list_put_lock);
+ INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
/* Initialize the fabric iocb list */
INIT_LIST_HEAD(&phba->fabric_iocb_list);
@@ -6233,9 +6372,11 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
phba->sli4_hba.conf_regs_memmap_p +
LPFC_CTL_PORT_SEM_OFFSET;
phba->sli4_hba.RQDBregaddr =
- phba->sli4_hba.conf_regs_memmap_p + LPFC_RQ_DOORBELL;
+ phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_ULP0_RQ_DOORBELL;
phba->sli4_hba.WQDBregaddr =
- phba->sli4_hba.conf_regs_memmap_p + LPFC_WQ_DOORBELL;
+ phba->sli4_hba.conf_regs_memmap_p +
+ LPFC_ULP0_WQ_DOORBELL;
phba->sli4_hba.EQCQDBregaddr =
phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;
phba->sli4_hba.MQDBregaddr =
@@ -6289,9 +6430,11 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf)
return -ENODEV;
phba->sli4_hba.RQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
- vf * LPFC_VFR_PAGE_SIZE + LPFC_RQ_DOORBELL);
+ vf * LPFC_VFR_PAGE_SIZE +
+ LPFC_ULP0_RQ_DOORBELL);
phba->sli4_hba.WQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
- vf * LPFC_VFR_PAGE_SIZE + LPFC_WQ_DOORBELL);
+ vf * LPFC_VFR_PAGE_SIZE +
+ LPFC_ULP0_WQ_DOORBELL);
phba->sli4_hba.EQCQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL);
phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
@@ -6671,7 +6814,6 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
uint32_t cpu;
uint32_t i = 0;
-
/*
* Sanity check for configured queue parameters against the run-time
* device parameters
@@ -6680,15 +6822,20 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
/* Sanity check on HBA EQ parameters */
cfg_fcp_io_channel = phba->cfg_fcp_io_channel;
- /* It doesn't make sense to have more io channels then CPUs */
- for_each_online_cpu(cpu) {
- i++;
+ /* It doesn't make sense to have more io channels then online CPUs */
+ for_each_present_cpu(cpu) {
+ if (cpu_online(cpu))
+ i++;
}
+ phba->sli4_hba.num_online_cpu = i;
+ phba->sli4_hba.num_present_cpu = lpfc_present_cpu;
+
if (i < cfg_fcp_io_channel) {
lpfc_printf_log(phba,
KERN_ERR, LOG_INIT,
"3188 Reducing IO channels to match number of "
- "CPUs: from %d to %d\n", cfg_fcp_io_channel, i);
+ "online CPUs: from %d to %d\n",
+ cfg_fcp_io_channel, i);
cfg_fcp_io_channel = i;
}
@@ -6987,6 +7134,19 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
phba->sli4_hba.fcp_wq = NULL;
}
+ if (phba->pci_bar0_memmap_p) {
+ iounmap(phba->pci_bar0_memmap_p);
+ phba->pci_bar0_memmap_p = NULL;
+ }
+ if (phba->pci_bar2_memmap_p) {
+ iounmap(phba->pci_bar2_memmap_p);
+ phba->pci_bar2_memmap_p = NULL;
+ }
+ if (phba->pci_bar4_memmap_p) {
+ iounmap(phba->pci_bar4_memmap_p);
+ phba->pci_bar4_memmap_p = NULL;
+ }
+
/* Release FCP CQ mapping array */
if (phba->sli4_hba.fcp_cq_map != NULL) {
kfree(phba->sli4_hba.fcp_cq_map);
@@ -7050,6 +7210,53 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
int rc = -ENOMEM;
int fcp_eqidx, fcp_cqidx, fcp_wqidx;
int fcp_cq_index = 0;
+ uint32_t shdr_status, shdr_add_status;
+ union lpfc_sli4_cfg_shdr *shdr;
+ LPFC_MBOXQ_t *mboxq;
+ uint32_t length;
+
+ /* Check for dual-ULP support */
+ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3249 Unable to allocate memory for "
+ "QUERY_FW_CFG mailbox command\n");
+ return -ENOMEM;
+ }
+ length = (sizeof(struct lpfc_mbx_query_fw_config) -
+ sizeof(struct lpfc_sli4_cfg_mhdr));
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_QUERY_FW_CFG,
+ length, LPFC_SLI4_MBX_EMBED);
+
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+
+ shdr = (union lpfc_sli4_cfg_shdr *)
+ &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3250 QUERY_FW_CFG mailbox failed with status "
+ "x%x add_status x%x, mbx status x%x\n",
+ shdr_status, shdr_add_status, rc);
+ if (rc != MBX_TIMEOUT)
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ rc = -ENXIO;
+ goto out_error;
+ }
+
+ phba->sli4_hba.fw_func_mode =
+ mboxq->u.mqe.un.query_fw_cfg.rsp.function_mode;
+ phba->sli4_hba.ulp0_mode = mboxq->u.mqe.un.query_fw_cfg.rsp.ulp0_mode;
+ phba->sli4_hba.ulp1_mode = mboxq->u.mqe.un.query_fw_cfg.rsp.ulp1_mode;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3251 QUERY_FW_CFG: func_mode:x%x, ulp0_mode:x%x, "
+ "ulp1_mode:x%x\n", phba->sli4_hba.fw_func_mode,
+ phba->sli4_hba.ulp0_mode, phba->sli4_hba.ulp1_mode);
+
+ if (rc != MBX_TIMEOUT)
+ mempool_free(mboxq, phba->mbox_mem_pool);
/*
* Set up HBA Event Queues (EQs)
@@ -7657,82 +7864,15 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
out:
/* Catch the not-ready port failure after a port reset. */
- if (num_resets >= MAX_IF_TYPE_2_RESETS)
- rc = -ENODEV;
-
- return rc;
-}
-
-/**
- * lpfc_sli4_send_nop_mbox_cmds - Send sli-4 nop mailbox commands
- * @phba: pointer to lpfc hba data structure.
- * @cnt: number of nop mailbox commands to send.
- *
- * This routine is invoked to send a number @cnt of NOP mailbox command and
- * wait for each command to complete.
- *
- * Return: the number of NOP mailbox command completed.
- **/
-static int
-lpfc_sli4_send_nop_mbox_cmds(struct lpfc_hba *phba, uint32_t cnt)
-{
- LPFC_MBOXQ_t *mboxq;
- int length, cmdsent;
- uint32_t mbox_tmo;
- uint32_t rc = 0;
- uint32_t shdr_status, shdr_add_status;
- union lpfc_sli4_cfg_shdr *shdr;
-
- if (cnt == 0) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
- "2518 Requested to send 0 NOP mailbox cmd\n");
- return cnt;
- }
-
- mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mboxq) {
+ if (num_resets >= MAX_IF_TYPE_2_RESETS) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2519 Unable to allocate memory for issuing "
- "NOP mailbox command\n");
- return 0;
- }
-
- /* Set up NOP SLI4_CONFIG mailbox-ioctl command */
- length = (sizeof(struct lpfc_mbx_nop) -
- sizeof(struct lpfc_sli4_cfg_mhdr));
-
- for (cmdsent = 0; cmdsent < cnt; cmdsent++) {
- lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
- LPFC_MBOX_OPCODE_NOP, length,
- LPFC_SLI4_MBX_EMBED);
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
- rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
- }
- if (rc == MBX_TIMEOUT)
- break;
- /* Check return status */
- shdr = (union lpfc_sli4_cfg_shdr *)
- &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
- shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
- &shdr->response);
- if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
- "2520 NOP mailbox command failed "
- "status x%x add_status x%x mbx "
- "status x%x\n", shdr_status,
- shdr_add_status, rc);
- break;
- }
+ "3317 HBA not functional: IP Reset Failed "
+ "after (%d) retries, try: "
+ "echo fw_reset > board_mode\n", num_resets);
+ rc = -ENODEV;
}
- if (rc != MBX_TIMEOUT)
- mempool_free(mboxq, phba->mbox_mem_pool);
-
- return cmdsent;
+ return rc;
}
/**
@@ -8195,6 +8335,269 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba)
}
/**
+ * lpfc_find_next_cpu - Find next available CPU that matches the phys_id
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * Find next available CPU to use for IRQ to CPU affinity.
+ */
+static int
+lpfc_find_next_cpu(struct lpfc_hba *phba, uint32_t phys_id)
+{
+ struct lpfc_vector_map_info *cpup;
+ int cpu;
+
+ cpup = phba->sli4_hba.cpu_map;
+ for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+ /* CPU must be online */
+ if (cpu_online(cpu)) {
+ if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) &&
+ (lpfc_used_cpu[cpu] == LPFC_VECTOR_MAP_EMPTY) &&
+ (cpup->phys_id == phys_id)) {
+ return cpu;
+ }
+ }
+ cpup++;
+ }
+
+ /*
+ * If we get here, we have used ALL CPUs for the specific
+ * phys_id. Now we need to clear out lpfc_used_cpu and start
+ * reusing CPUs.
+ */
+
+ for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+ if (lpfc_used_cpu[cpu] == phys_id)
+ lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY;
+ }
+
+ cpup = phba->sli4_hba.cpu_map;
+ for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+ /* CPU must be online */
+ if (cpu_online(cpu)) {
+ if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) &&
+ (cpup->phys_id == phys_id)) {
+ return cpu;
+ }
+ }
+ cpup++;
+ }
+ return LPFC_VECTOR_MAP_EMPTY;
+}
+
+/**
+ * lpfc_sli4_set_affinity - Set affinity for HBA IRQ vectors
+ * @phba: pointer to lpfc hba data structure.
+ * @vectors: number of HBA vectors
+ *
+ * Affinitize MSIX IRQ vectors to CPUs. Try to equally spread vector
+ * affinization across multple physical CPUs (numa nodes).
+ * In addition, this routine will assign an IO channel for each CPU
+ * to use when issuing I/Os.
+ */
+static int
+lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
+{
+ int i, idx, saved_chann, used_chann, cpu, phys_id;
+ int max_phys_id, num_io_channel, first_cpu;
+ struct lpfc_vector_map_info *cpup;
+#ifdef CONFIG_X86
+ struct cpuinfo_x86 *cpuinfo;
+#endif
+ struct cpumask *mask;
+ uint8_t chann[LPFC_FCP_IO_CHAN_MAX+1];
+
+ /* If there is no mapping, just return */
+ if (!phba->cfg_fcp_cpu_map)
+ return 1;
+
+ /* Init cpu_map array */
+ memset(phba->sli4_hba.cpu_map, 0xff,
+ (sizeof(struct lpfc_vector_map_info) *
+ phba->sli4_hba.num_present_cpu));
+
+ max_phys_id = 0;
+ phys_id = 0;
+ num_io_channel = 0;
+ first_cpu = LPFC_VECTOR_MAP_EMPTY;
+
+ /* Update CPU map with physical id and core id of each CPU */
+ cpup = phba->sli4_hba.cpu_map;
+ for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+#ifdef CONFIG_X86
+ cpuinfo = &cpu_data(cpu);
+ cpup->phys_id = cpuinfo->phys_proc_id;
+ cpup->core_id = cpuinfo->cpu_core_id;
+#else
+ /* No distinction between CPUs for other platforms */
+ cpup->phys_id = 0;
+ cpup->core_id = 0;
+#endif
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3328 CPU physid %d coreid %d\n",
+ cpup->phys_id, cpup->core_id);
+
+ if (cpup->phys_id > max_phys_id)
+ max_phys_id = cpup->phys_id;
+ cpup++;
+ }
+
+ /* Now associate the HBA vectors with specific CPUs */
+ for (idx = 0; idx < vectors; idx++) {
+ cpup = phba->sli4_hba.cpu_map;
+ cpu = lpfc_find_next_cpu(phba, phys_id);
+ if (cpu == LPFC_VECTOR_MAP_EMPTY) {
+
+ /* Try for all phys_id's */
+ for (i = 1; i < max_phys_id; i++) {
+ phys_id++;
+ if (phys_id > max_phys_id)
+ phys_id = 0;
+ cpu = lpfc_find_next_cpu(phba, phys_id);
+ if (cpu == LPFC_VECTOR_MAP_EMPTY)
+ continue;
+ goto found;
+ }
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3329 Cannot set affinity:"
+ "Error mapping vector %d (%d)\n",
+ idx, vectors);
+ return 0;
+ }
+found:
+ cpup += cpu;
+ if (phba->cfg_fcp_cpu_map == LPFC_DRIVER_CPU_MAP)
+ lpfc_used_cpu[cpu] = phys_id;
+
+ /* Associate vector with selected CPU */
+ cpup->irq = phba->sli4_hba.msix_entries[idx].vector;
+
+ /* Associate IO channel with selected CPU */
+ cpup->channel_id = idx;
+ num_io_channel++;
+
+ if (first_cpu == LPFC_VECTOR_MAP_EMPTY)
+ first_cpu = cpu;
+
+ /* Now affinitize to the selected CPU */
+ mask = &cpup->maskbits;
+ cpumask_clear(mask);
+ cpumask_set_cpu(cpu, mask);
+ i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx].
+ vector, mask);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3330 Set Affinity: CPU %d channel %d "
+ "irq %d (%x)\n",
+ cpu, cpup->channel_id,
+ phba->sli4_hba.msix_entries[idx].vector, i);
+
+ /* Spread vector mapping across multple physical CPU nodes */
+ phys_id++;
+ if (phys_id > max_phys_id)
+ phys_id = 0;
+ }
+
+ /*
+ * Finally fill in the IO channel for any remaining CPUs.
+ * At this point, all IO channels have been assigned to a specific
+ * MSIx vector, mapped to a specific CPU.
+ * Base the remaining IO channel assigned, to IO channels already
+ * assigned to other CPUs on the same phys_id.
+ */
+ for (i = 0; i <= max_phys_id; i++) {
+ /*
+ * If there are no io channels already mapped to
+ * this phys_id, just round robin thru the io_channels.
+ * Setup chann[] for round robin.
+ */
+ for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++)
+ chann[idx] = idx;
+
+ saved_chann = 0;
+ used_chann = 0;
+
+ /*
+ * First build a list of IO channels already assigned
+ * to this phys_id before reassigning the same IO
+ * channels to the remaining CPUs.
+ */
+ cpup = phba->sli4_hba.cpu_map;
+ cpu = first_cpu;
+ cpup += cpu;
+ for (idx = 0; idx < phba->sli4_hba.num_present_cpu;
+ idx++) {
+ if (cpup->phys_id == i) {
+ /*
+ * Save any IO channels that are
+ * already mapped to this phys_id.
+ */
+ if (cpup->irq != LPFC_VECTOR_MAP_EMPTY) {
+ chann[saved_chann] =
+ cpup->channel_id;
+ saved_chann++;
+ goto out;
+ }
+
+ /* See if we are using round-robin */
+ if (saved_chann == 0)
+ saved_chann =
+ phba->cfg_fcp_io_channel;
+
+ /* Associate next IO channel with CPU */
+ cpup->channel_id = chann[used_chann];
+ num_io_channel++;
+ used_chann++;
+ if (used_chann == saved_chann)
+ used_chann = 0;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3331 Set IO_CHANN "
+ "CPU %d channel %d\n",
+ idx, cpup->channel_id);
+ }
+out:
+ cpu++;
+ if (cpu >= phba->sli4_hba.num_present_cpu) {
+ cpup = phba->sli4_hba.cpu_map;
+ cpu = 0;
+ } else {
+ cpup++;
+ }
+ }
+ }
+
+ if (phba->sli4_hba.num_online_cpu != phba->sli4_hba.num_present_cpu) {
+ cpup = phba->sli4_hba.cpu_map;
+ for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
+ if (cpup->channel_id == LPFC_VECTOR_MAP_EMPTY) {
+ cpup->channel_id = 0;
+ num_io_channel++;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3332 Assign IO_CHANN "
+ "CPU %d channel %d\n",
+ idx, cpup->channel_id);
+ }
+ cpup++;
+ }
+ }
+
+ /* Sanity check */
+ if (num_io_channel != phba->sli4_hba.num_present_cpu)
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3333 Set affinity mismatch:"
+ "%d chann != %d cpus: %d vactors\n",
+ num_io_channel, phba->sli4_hba.num_present_cpu,
+ vectors);
+
+ phba->cfg_fcp_io_sched = LPFC_FCP_SCHED_BY_CPU;
+ return 1;
+}
+
+
+/**
* lpfc_sli4_enable_msix - Enable MSI-X interrupt mode to SLI-4 device
* @phba: pointer to lpfc hba data structure.
*
@@ -8245,9 +8648,7 @@ enable_msix_vectors:
phba->sli4_hba.msix_entries[index].vector,
phba->sli4_hba.msix_entries[index].entry);
- /*
- * Assign MSI-X vectors to interrupt handlers
- */
+ /* Assign MSI-X vectors to interrupt handlers */
for (index = 0; index < vectors; index++) {
memset(&phba->sli4_hba.handler_name[index], 0, 16);
sprintf((char *)&phba->sli4_hba.handler_name[index],
@@ -8275,6 +8676,8 @@ enable_msix_vectors:
phba->cfg_fcp_io_channel, vectors);
phba->cfg_fcp_io_channel = vectors;
}
+
+ lpfc_sli4_set_affinity(phba, vectors);
return rc;
cfg_fail_out:
@@ -8503,37 +8906,6 @@ lpfc_unset_hba(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_unset_hba - Unset SLI4 hba device initialization.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to unset the HBA device initialization steps to
- * a device with SLI-4 interface spec.
- **/
-static void
-lpfc_sli4_unset_hba(struct lpfc_hba *phba)
-{
- struct lpfc_vport *vport = phba->pport;
- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-
- spin_lock_irq(shost->host_lock);
- vport->load_flag |= FC_UNLOADING;
- spin_unlock_irq(shost->host_lock);
-
- phba->pport->work_port_events = 0;
-
- /* Stop the SLI4 device port */
- lpfc_stop_port(phba);
-
- lpfc_sli4_disable_intr(phba);
-
- /* Reset SLI4 HBA FCoE function */
- lpfc_pci_function_reset(phba);
- lpfc_sli4_queue_destroy(phba);
-
- return;
-}
-
-/**
* lpfc_sli4_xri_exchange_busy_wait - Wait for device XRI exchange busy
* @phba: Pointer to HBA context object.
*
@@ -8813,7 +9185,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
* 0 - driver can claim the device
* negative value - driver can not claim the device
**/
-static int __devinit
+static int
lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
{
struct lpfc_hba *phba;
@@ -8980,7 +9352,7 @@ out_free_phba:
* removed from PCI bus, it performs all the necessary cleanup for the HBA
* device to be removed from the PCI subsystem properly.
**/
-static void __devexit
+static void
lpfc_pci_remove_one_s3(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -9230,15 +9602,15 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
/* Block all SCSI devices' I/Os on the host */
lpfc_scsi_dev_block(phba);
+ /* Flush all driver's outstanding SCSI I/Os as we are to reset */
+ lpfc_sli_flush_fcp_rings(phba);
+
/* stop all timers */
lpfc_stop_hba_timers(phba);
/* Disable interrupt and pci device */
lpfc_sli_disable_intr(phba);
pci_disable_device(phba->pcidev);
-
- /* Flush all driver's outstanding SCSI I/Os as we are to reset */
- lpfc_sli_flush_fcp_rings(phba);
}
/**
@@ -9587,7 +9959,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
* 0 - driver can claim the device
* negative value - driver can not claim the device
**/
-static int __devinit
+static int
lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
{
struct lpfc_hba *phba;
@@ -9595,7 +9967,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
struct Scsi_Host *shost = NULL;
int error, ret;
uint32_t cfg_mode, intr_mode;
- int mcnt;
int adjusted_fcp_io_channel;
/* Allocate memory for HBA structure */
@@ -9684,57 +10055,34 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
/* Now, trying to enable interrupt and bring up the device */
cfg_mode = phba->cfg_use_msi;
- while (true) {
- /* Put device to a known state before enabling interrupt */
- lpfc_stop_port(phba);
- /* Configure and enable interrupt */
- intr_mode = lpfc_sli4_enable_intr(phba, cfg_mode);
- if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0426 Failed to enable interrupt.\n");
- error = -ENODEV;
- goto out_free_sysfs_attr;
- }
- /* Default to single EQ for non-MSI-X */
- if (phba->intr_type != MSIX)
- adjusted_fcp_io_channel = 1;
- else
- adjusted_fcp_io_channel = phba->cfg_fcp_io_channel;
- phba->cfg_fcp_io_channel = adjusted_fcp_io_channel;
- /* Set up SLI-4 HBA */
- if (lpfc_sli4_hba_setup(phba)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1421 Failed to set up hba\n");
- error = -ENODEV;
- goto out_disable_intr;
- }
- /* Send NOP mbx cmds for non-INTx mode active interrupt test */
- if (intr_mode != 0)
- mcnt = lpfc_sli4_send_nop_mbox_cmds(phba,
- LPFC_ACT_INTR_CNT);
-
- /* Check active interrupts received only for MSI/MSI-X */
- if (intr_mode == 0 ||
- phba->sli.slistat.sli_intr >= LPFC_ACT_INTR_CNT) {
- /* Log the current active interrupt mode */
- phba->intr_mode = intr_mode;
- lpfc_log_intr_mode(phba, intr_mode);
- break;
- }
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "0451 Configure interrupt mode (%d) "
- "failed active interrupt test.\n",
- intr_mode);
- /* Unset the previous SLI-4 HBA setup. */
- /*
- * TODO: Is this operation compatible with IF TYPE 2
- * devices? All port state is deleted and cleared.
- */
- lpfc_sli4_unset_hba(phba);
- /* Try next level of interrupt mode */
- cfg_mode = --intr_mode;
+ /* Put device to a known state before enabling interrupt */
+ lpfc_stop_port(phba);
+ /* Configure and enable interrupt */
+ intr_mode = lpfc_sli4_enable_intr(phba, cfg_mode);
+ if (intr_mode == LPFC_INTR_ERROR) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0426 Failed to enable interrupt.\n");
+ error = -ENODEV;
+ goto out_free_sysfs_attr;
}
+ /* Default to single EQ for non-MSI-X */
+ if (phba->intr_type != MSIX)
+ adjusted_fcp_io_channel = 1;
+ else
+ adjusted_fcp_io_channel = phba->cfg_fcp_io_channel;
+ phba->cfg_fcp_io_channel = adjusted_fcp_io_channel;
+ /* Set up SLI-4 HBA */
+ if (lpfc_sli4_hba_setup(phba)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1421 Failed to set up hba\n");
+ error = -ENODEV;
+ goto out_disable_intr;
+ }
+
+ /* Log the current active interrupt mode */
+ phba->intr_mode = intr_mode;
+ lpfc_log_intr_mode(phba, intr_mode);
/* Perform post initialization setup */
lpfc_post_init_setup(phba);
@@ -9779,7 +10127,7 @@ out_free_phba:
* removed from PCI bus, it performs all the necessary cleanup for the HBA
* device to be removed from the PCI subsystem properly.
**/
-static void __devexit
+static void
lpfc_pci_remove_one_s4(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -10007,6 +10355,9 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
/* Block all SCSI devices' I/Os on the host */
lpfc_scsi_dev_block(phba);
+ /* Flush all driver's outstanding SCSI I/Os as we are to reset */
+ lpfc_sli_flush_fcp_rings(phba);
+
/* stop all timers */
lpfc_stop_hba_timers(phba);
@@ -10014,9 +10365,6 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
lpfc_sli4_disable_intr(phba);
lpfc_sli4_queue_destroy(phba);
pci_disable_device(phba->pcidev);
-
- /* Flush all driver's outstanding SCSI I/Os as we are to reset */
- lpfc_sli_flush_fcp_rings(phba);
}
/**
@@ -10205,7 +10553,7 @@ lpfc_io_resume_s4(struct pci_dev *pdev)
* 0 - driver can claim the device
* negative value - driver can not claim the device
**/
-static int __devinit
+static int
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
{
int rc;
@@ -10233,7 +10581,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
* remove routine, which will perform all the necessary cleanup for the
* device to be removed from the PCI subsystem properly.
**/
-static void __devexit
+static void
lpfc_pci_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -10435,36 +10783,6 @@ lpfc_io_resume(struct pci_dev *pdev)
return;
}
-/**
- * lpfc_mgmt_open - method called when 'lpfcmgmt' is opened from userspace
- * @inode: pointer to the inode representing the lpfcmgmt device
- * @filep: pointer to the file representing the open lpfcmgmt device
- *
- * This routine puts a reference count on the lpfc module whenever the
- * character device is opened
- **/
-static int
-lpfc_mgmt_open(struct inode *inode, struct file *filep)
-{
- try_module_get(THIS_MODULE);
- return 0;
-}
-
-/**
- * lpfc_mgmt_release - method called when 'lpfcmgmt' is closed in userspace
- * @inode: pointer to the inode representing the lpfcmgmt device
- * @filep: pointer to the file representing the open lpfcmgmt device
- *
- * This routine removes a reference count from the lpfc module when the
- * character device is closed
- **/
-static int
-lpfc_mgmt_release(struct inode *inode, struct file *filep)
-{
- module_put(THIS_MODULE);
- return 0;
-}
-
static struct pci_device_id lpfc_id_table[] = {
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
PCI_ANY_ID, PCI_ANY_ID, },
@@ -10575,15 +10893,14 @@ static struct pci_driver lpfc_driver = {
.name = LPFC_DRIVER_NAME,
.id_table = lpfc_id_table,
.probe = lpfc_pci_probe_one,
- .remove = __devexit_p(lpfc_pci_remove_one),
+ .remove = lpfc_pci_remove_one,
.suspend = lpfc_pci_suspend_one,
.resume = lpfc_pci_resume_one,
.err_handler = &lpfc_err_handler,
};
static const struct file_operations lpfc_mgmt_fop = {
- .open = lpfc_mgmt_open,
- .release = lpfc_mgmt_release,
+ .owner = THIS_MODULE,
};
static struct miscdevice lpfc_mgmt_dev = {
@@ -10607,6 +10924,7 @@ static struct miscdevice lpfc_mgmt_dev = {
static int __init
lpfc_init(void)
{
+ int cpu;
int error = 0;
printk(LPFC_MODULE_DESC "\n");
@@ -10633,6 +10951,13 @@ lpfc_init(void)
return -ENOMEM;
}
}
+
+ /* Initialize in case vector mapping is needed */
+ lpfc_used_cpu = NULL;
+ lpfc_present_cpu = 0;
+ for_each_present_cpu(cpu)
+ lpfc_present_cpu++;
+
error = pci_register_driver(&lpfc_driver);
if (error) {
fc_release_transport(lpfc_transport_template);
@@ -10671,6 +10996,7 @@ lpfc_exit(void)
(1L << _dump_buf_dif_order), _dump_buf_dif);
free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order);
}
+ kfree(lpfc_used_cpu);
}
module_init(lpfc_init);
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index baf53e6..2a4e5d2 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -37,6 +37,7 @@
#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
#define LOG_FIP 0x00020000 /* FIP events */
#define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */
+#define LOG_SCSI_CMD 0x00080000 /* ALL SCSI commands */
#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index efc9cd9..b1c510f 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2009 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -2126,33 +2126,44 @@ void
lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
{
struct lpfc_mbx_reg_vfi *reg_vfi;
+ struct lpfc_hba *phba = vport->phba;
memset(mbox, 0, sizeof(*mbox));
reg_vfi = &mbox->u.mqe.un.reg_vfi;
bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI);
bf_set(lpfc_reg_vfi_vp, reg_vfi, 1);
bf_set(lpfc_reg_vfi_vfi, reg_vfi,
- vport->phba->sli4_hba.vfi_ids[vport->vfi]);
- bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi);
- bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->phba->vpi_ids[vport->vpi]);
+ phba->sli4_hba.vfi_ids[vport->vfi]);
+ bf_set(lpfc_reg_vfi_fcfi, reg_vfi, phba->fcf.fcfi);
+ bf_set(lpfc_reg_vfi_vpi, reg_vfi, phba->vpi_ids[vport->vpi]);
memcpy(reg_vfi->wwn, &vport->fc_portname, sizeof(struct lpfc_name));
reg_vfi->wwn[0] = cpu_to_le32(reg_vfi->wwn[0]);
reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]);
- reg_vfi->e_d_tov = vport->phba->fc_edtov;
- reg_vfi->r_a_tov = vport->phba->fc_ratov;
+ reg_vfi->e_d_tov = phba->fc_edtov;
+ reg_vfi->r_a_tov = phba->fc_ratov;
reg_vfi->bde.addrHigh = putPaddrHigh(phys);
reg_vfi->bde.addrLow = putPaddrLow(phys);
reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam);
reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID);
+
+ /* Only FC supports upd bit */
+ if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) &&
+ (vport->fc_flag & FC_VFI_REGISTERED) &&
+ (!phba->fc_topology_changed)) {
+ bf_set(lpfc_reg_vfi_vp, reg_vfi, 0);
+ bf_set(lpfc_reg_vfi_upd, reg_vfi, 1);
+ }
lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX,
"3134 Register VFI, mydid:x%x, fcfi:%d, "
- " vfi:%d, vpi:%d, fc_pname:%x%x\n",
+ " vfi:%d, vpi:%d, fc_pname:%x%x fc_flag:x%x"
+ " port_state:x%x topology chg:%d\n",
vport->fc_myDID,
- vport->phba->fcf.fcfi,
- vport->phba->sli4_hba.vfi_ids[vport->vfi],
- vport->phba->vpi_ids[vport->vpi],
- reg_vfi->wwn[0], reg_vfi->wwn[1]);
+ phba->fcf.fcfi,
+ phba->sli4_hba.vfi_ids[vport->vfi],
+ phba->vpi_ids[vport->vpi],
+ reg_vfi->wwn[0], reg_vfi->wwn[1], vport->fc_flag,
+ vport->port_state, phba->fc_topology_changed);
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index cd86069..812d0cd 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -64,18 +64,26 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align)
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
int i;
- if (phba->sli_rev == LPFC_SLI_REV4)
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+ /* Calculate alignment */
+ if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE)
+ i = phba->cfg_sg_dma_buf_size;
+ else
+ i = SLI4_PAGE_SIZE;
+
phba->lpfc_scsi_dma_buf_pool =
pci_pool_create("lpfc_scsi_dma_buf_pool",
phba->pcidev,
phba->cfg_sg_dma_buf_size,
- phba->cfg_sg_dma_buf_size,
+ i,
0);
- else
+ } else {
phba->lpfc_scsi_dma_buf_pool =
pci_pool_create("lpfc_scsi_dma_buf_pool",
phba->pcidev, phba->cfg_sg_dma_buf_size,
align, 0);
+ }
+
if (!phba->lpfc_scsi_dma_buf_pool)
goto fail;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index d8fadcb..6aaf39a 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -226,7 +226,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
/* It matches, so deque and call compl with anp error */
list_move_tail(&iocb->list, &completions);
- pring->txq_cnt--;
}
}
@@ -333,9 +332,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* PLOGI chkparm OK */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
+ "0114 PLOGI chkparm OK Data: x%x x%x x%x "
+ "x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
- ndlp->nlp_rpi);
+ ndlp->nlp_rpi, vport->port_state,
+ vport->fc_flag);
if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)
ndlp->nlp_fcp_info |= CLASS2;
@@ -575,7 +576,7 @@ out:
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
/* 1 sec timeout */
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
@@ -632,7 +633,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
* If there are other active VLinks present,
* re-instantiate the Vlink using FDISC.
*/
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+ mod_timer(&ndlp->nlp_delayfunc,
+ jiffies + msecs_to_jiffies(1000));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
@@ -649,7 +651,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
!(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
/* Only try to re-login if this is NOT a Fabric Node */
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+ mod_timer(&ndlp->nlp_delayfunc,
+ jiffies + msecs_to_jiffies(1000 * 1));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
@@ -970,7 +973,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
/* Put ndlp in npr state set plogi timer for 1 sec */
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
@@ -1115,6 +1118,13 @@ out:
"0261 Cannot Register NameServer login\n");
}
+ /*
+ ** In case the node reference counter does not go to zero, ensure that
+ ** the stale state for the node is not processed.
+ */
+
+ ndlp->nlp_prev_state = ndlp->nlp_state;
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DEFER_RM;
spin_unlock_irq(shost->host_lock);
@@ -1297,7 +1307,8 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
if ((irsp->ulpStatus) ||
(!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
/* 1 sec timeout */
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+ mod_timer(&ndlp->nlp_delayfunc,
+ jiffies + msecs_to_jiffies(1000));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
@@ -1503,7 +1514,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
}
/* Put ndlp in npr state set plogi timer for 1 sec */
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+ mod_timer(&ndlp->nlp_delayfunc,
+ jiffies + msecs_to_jiffies(1000 * 1));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
@@ -2139,7 +2151,8 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
- mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+ mod_timer(&ndlp->nlp_delayfunc,
+ jiffies + msecs_to_jiffies(1000 * 1));
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
@@ -2159,13 +2172,16 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
IOCB_t *irsp;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
cmdiocb = (struct lpfc_iocbq *) arg;
rspiocb = cmdiocb->context_un.rsp_iocb;
irsp = &rspiocb->iocb;
if (irsp->ulpStatus) {
+ spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DEFER_RM;
+ spin_unlock_irq(shost->host_lock);
return NLP_STE_FREED_NODE;
}
return ndlp->nlp_state;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 60e5a177..243de1d 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -24,6 +24,8 @@
#include <linux/export.h>
#include <linux/delay.h>
#include <asm/unaligned.h>
+#include <linux/crc-t10dif.h>
+#include <net/checksum.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -48,7 +50,7 @@
#define LPFC_RESET_WAIT 2
#define LPFC_ABORT_WAIT 2
-int _dump_buf_done;
+int _dump_buf_done = 1;
static char *dif_op_str[] = {
"PROT_NORMAL",
@@ -70,6 +72,8 @@ static void
lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
static void
lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
+static int
+lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc);
static void
lpfc_debug_save_data(struct lpfc_hba *phba, struct scsi_cmnd *cmnd)
@@ -128,6 +132,30 @@ lpfc_debug_save_dif(struct lpfc_hba *phba, struct scsi_cmnd *cmnd)
}
}
+static inline unsigned
+lpfc_cmd_blksize(struct scsi_cmnd *sc)
+{
+ return sc->device->sector_size;
+}
+
+#define LPFC_CHECK_PROTECT_GUARD 1
+#define LPFC_CHECK_PROTECT_REF 2
+static inline unsigned
+lpfc_cmd_protect(struct scsi_cmnd *sc, int flag)
+{
+ return 1;
+}
+
+static inline unsigned
+lpfc_cmd_guard_csum(struct scsi_cmnd *sc)
+{
+ if (lpfc_prot_group_type(NULL, sc) == LPFC_PG_TYPE_NO_DIF)
+ return 0;
+ if (scsi_host_get_guard(sc->device->host) == SHOST_DIX_GUARD_IP)
+ return 1;
+ return 0;
+}
+
/**
* lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge.
* @phba: Pointer to HBA object.
@@ -288,6 +316,26 @@ lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
}
/**
+ * lpfc_change_queue_type() - Change a device's scsi tag queuing type
+ * @sdev: Pointer the scsi device whose queue depth is to change
+ * @tag_type: Identifier for queue tag type
+ */
+static int
+lpfc_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;
+}
+
+/**
* lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
* @phba: The Hba for which this call is being executed.
*
@@ -514,7 +562,16 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
dma_addr_t pdma_phys_fcp_rsp;
dma_addr_t pdma_phys_bpl;
uint16_t iotag;
- int bcnt;
+ int bcnt, bpl_size;
+
+ bpl_size = phba->cfg_sg_dma_buf_size -
+ (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+ "9067 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n",
+ num_to_alloc, phba->cfg_sg_dma_buf_size,
+ (int)sizeof(struct fcp_cmnd),
+ (int)sizeof(struct fcp_rsp), bpl_size);
for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
@@ -712,7 +769,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
psb->exch_busy = 0;
spin_unlock_irqrestore(&phba->hbalock, iflag);
- if (pring->txq_cnt)
+ if (!list_empty(&pring->txq))
lpfc_worker_wake_up(phba);
return;
@@ -739,7 +796,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
struct list_head *post_sblist, int sb_count)
{
struct lpfc_scsi_buf *psb, *psb_next;
- int status;
+ int status, sgl_size;
int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0;
dma_addr_t pdma_phys_bpl1;
int last_xritag = NO_XRI;
@@ -751,6 +808,9 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
if (sb_count <= 0)
return -EINVAL;
+ sgl_size = phba->cfg_sg_dma_buf_size -
+ (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+
list_for_each_entry_safe(psb, psb_next, post_sblist, list) {
list_del_init(&psb->list);
block_cnt++;
@@ -783,7 +843,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
post_cnt = block_cnt;
} else if (block_cnt == 1) {
/* last single sgl with non-contiguous xri */
- if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
+ if (sgl_size > SGL_PAGE_SIZE)
pdma_phys_bpl1 = psb->dma_phys_bpl +
SGL_PAGE_SIZE;
else
@@ -865,9 +925,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
int num_posted, rc = 0;
/* get all SCSI buffers need to repost to a local list */
- spin_lock(&phba->scsi_buf_list_lock);
- list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist);
- spin_unlock(&phba->scsi_buf_list_lock);
+ spin_lock_irq(&phba->scsi_buf_list_get_lock);
+ spin_lock_irq(&phba->scsi_buf_list_put_lock);
+ list_splice_init(&phba->lpfc_scsi_buf_list_get, &post_sblist);
+ list_splice(&phba->lpfc_scsi_buf_list_put, &post_sblist);
+ spin_unlock_irq(&phba->scsi_buf_list_put_lock);
+ spin_unlock_irq(&phba->scsi_buf_list_get_lock);
/* post the list of scsi buffer sgls to port if available */
if (!list_empty(&post_sblist)) {
@@ -903,13 +966,22 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
IOCB_t *iocb;
dma_addr_t pdma_phys_fcp_cmd;
dma_addr_t pdma_phys_fcp_rsp;
- dma_addr_t pdma_phys_bpl, pdma_phys_bpl1;
+ dma_addr_t pdma_phys_bpl;
uint16_t iotag, lxri = 0;
- int bcnt, num_posted;
+ int bcnt, num_posted, sgl_size;
LIST_HEAD(prep_sblist);
LIST_HEAD(post_sblist);
LIST_HEAD(scsi_sblist);
+ sgl_size = phba->cfg_sg_dma_buf_size -
+ (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+ "9068 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n",
+ num_to_alloc, phba->cfg_sg_dma_buf_size, sgl_size,
+ (int)sizeof(struct fcp_cmnd),
+ (int)sizeof(struct fcp_rsp));
+
for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
if (!psb)
@@ -928,6 +1000,15 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
}
memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
+ /* Page alignment is CRITICAL, double check to be sure */
+ if (((unsigned long)(psb->data) &
+ (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0) {
+ pci_pool_free(phba->lpfc_scsi_dma_buf_pool,
+ psb->data, psb->dma_handle);
+ kfree(psb);
+ break;
+ }
+
/* Allocate iotag for psb->cur_iocbq. */
iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq);
if (iotag == 0) {
@@ -948,17 +1029,14 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
psb->fcp_bpl = psb->data;
- psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size)
- - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+ psb->fcp_cmnd = (psb->data + sgl_size);
psb->fcp_rsp = (struct fcp_rsp *)((uint8_t *)psb->fcp_cmnd +
sizeof(struct fcp_cmnd));
/* Initialize local short-hand pointers. */
sgl = (struct sli4_sge *)psb->fcp_bpl;
pdma_phys_bpl = psb->dma_handle;
- pdma_phys_fcp_cmd =
- (psb->dma_handle + phba->cfg_sg_dma_buf_size)
- - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+ pdma_phys_fcp_cmd = (psb->dma_handle + sgl_size);
pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd);
/*
@@ -1000,17 +1078,13 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
iocb->ulpLe = 1;
iocb->ulpClass = CLASS3;
psb->cur_iocbq.context1 = psb;
- if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
- pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
- else
- pdma_phys_bpl1 = 0;
psb->dma_phys_bpl = pdma_phys_bpl;
/* add the scsi buffer to a post list */
list_add_tail(&psb->list, &post_sblist);
- spin_lock_irq(&phba->scsi_buf_list_lock);
+ spin_lock_irq(&phba->scsi_buf_list_get_lock);
phba->sli4_hba.scsi_xri_cnt++;
- spin_unlock_irq(&phba->scsi_buf_list_lock);
+ spin_unlock_irq(&phba->scsi_buf_list_get_lock);
}
lpfc_printf_log(phba, KERN_INFO, LOG_BG,
"3021 Allocate %d out of %d requested new SCSI "
@@ -1059,17 +1133,23 @@ static struct lpfc_scsi_buf*
lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
struct lpfc_scsi_buf * lpfc_cmd = NULL;
- struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
- unsigned long iflag = 0;
-
- spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
- list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
- if (lpfc_cmd) {
- lpfc_cmd->seg_cnt = 0;
- lpfc_cmd->nonsg_phys = 0;
- lpfc_cmd->prot_seg_cnt = 0;
+ struct list_head *scsi_buf_list_get = &phba->lpfc_scsi_buf_list_get;
+ unsigned long gflag = 0;
+ unsigned long pflag = 0;
+
+ spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag);
+ list_remove_head(scsi_buf_list_get, lpfc_cmd, struct lpfc_scsi_buf,
+ list);
+ if (!lpfc_cmd) {
+ spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag);
+ list_splice(&phba->lpfc_scsi_buf_list_put,
+ &phba->lpfc_scsi_buf_list_get);
+ INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
+ list_remove_head(scsi_buf_list_get, lpfc_cmd,
+ struct lpfc_scsi_buf, list);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag);
}
- spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag);
return lpfc_cmd;
}
/**
@@ -1086,29 +1166,41 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
static struct lpfc_scsi_buf*
lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
- struct lpfc_scsi_buf *lpfc_cmd ;
- unsigned long iflag = 0;
+ struct lpfc_scsi_buf *lpfc_cmd, *lpfc_cmd_next;
+ unsigned long gflag = 0;
+ unsigned long pflag = 0;
int found = 0;
- spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
- list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
- list) {
+ spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag);
+ list_for_each_entry_safe(lpfc_cmd, lpfc_cmd_next,
+ &phba->lpfc_scsi_buf_list_get, list) {
if (lpfc_test_rrq_active(phba, ndlp,
lpfc_cmd->cur_iocbq.sli4_lxritag))
continue;
list_del(&lpfc_cmd->list);
found = 1;
- lpfc_cmd->seg_cnt = 0;
- lpfc_cmd->nonsg_phys = 0;
- lpfc_cmd->prot_seg_cnt = 0;
break;
}
- spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
- iflag);
+ if (!found) {
+ spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag);
+ list_splice(&phba->lpfc_scsi_buf_list_put,
+ &phba->lpfc_scsi_buf_list_get);
+ INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag);
+ list_for_each_entry_safe(lpfc_cmd, lpfc_cmd_next,
+ &phba->lpfc_scsi_buf_list_get, list) {
+ if (lpfc_test_rrq_active(
+ phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag))
+ continue;
+ list_del(&lpfc_cmd->list);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag);
if (!found)
return NULL;
- else
- return lpfc_cmd;
+ return lpfc_cmd;
}
/**
* lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
@@ -1140,10 +1232,15 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
{
unsigned long iflag = 0;
- spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+ psb->seg_cnt = 0;
+ psb->nonsg_phys = 0;
+ psb->prot_seg_cnt = 0;
+
+ spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
psb->pCmd = NULL;
- list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
- spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+ psb->cur_iocbq.iocb_flag = LPFC_IO_FCP;
+ list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
}
/**
@@ -1161,6 +1258,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
{
unsigned long iflag = 0;
+ psb->seg_cnt = 0;
+ psb->nonsg_phys = 0;
+ psb->prot_seg_cnt = 0;
+
if (psb->exch_busy) {
spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
iflag);
@@ -1170,11 +1271,11 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock,
iflag);
} else {
-
- spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
psb->pCmd = NULL;
- list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
- spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+ psb->cur_iocbq.iocb_flag = LPFC_IO_FCP;
+ spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
+ list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
}
}
@@ -1248,6 +1349,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
"dma_map_sg. Config %d, seg_cnt %d\n",
__func__, phba->cfg_sg_seg_cnt,
lpfc_cmd->seg_cnt);
+ lpfc_cmd->seg_cnt = 0;
scsi_dma_unmap(scsi_cmnd);
return 1;
}
@@ -1330,12 +1432,6 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
return 0;
}
-static inline unsigned
-lpfc_cmd_blksize(struct scsi_cmnd *sc)
-{
- return sc->device->sector_size;
-}
-
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
/* Return if if error injection is detected by Initiator */
@@ -1768,10 +1864,9 @@ static int
lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
uint8_t *txop, uint8_t *rxop)
{
- uint8_t guard_type = scsi_host_get_guard(sc->device->host);
uint8_t ret = 0;
- if (guard_type == SHOST_DIX_GUARD_IP) {
+ if (lpfc_cmd_guard_csum(sc)) {
switch (scsi_get_prot_op(sc)) {
case SCSI_PROT_READ_INSERT:
case SCSI_PROT_WRITE_STRIP:
@@ -1849,10 +1944,9 @@ static int
lpfc_bg_err_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
uint8_t *txop, uint8_t *rxop)
{
- uint8_t guard_type = scsi_host_get_guard(sc->device->host);
uint8_t ret = 0;
- if (guard_type == SHOST_DIX_GUARD_IP) {
+ if (lpfc_cmd_guard_csum(sc)) {
switch (scsi_get_prot_op(sc)) {
case SCSI_PROT_READ_INSERT:
case SCSI_PROT_WRITE_STRIP:
@@ -1993,9 +2087,21 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR);
bf_set(pde6_optx, pde6, txop);
bf_set(pde6_oprx, pde6, rxop);
+
+ /*
+ * We only need to check the data on READs, for WRITEs
+ * protection data is automatically generated, not checked.
+ */
if (datadir == DMA_FROM_DEVICE) {
- bf_set(pde6_ce, pde6, checking);
- bf_set(pde6_re, pde6, checking);
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD))
+ bf_set(pde6_ce, pde6, checking);
+ else
+ bf_set(pde6_ce, pde6, 0);
+
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ bf_set(pde6_re, pde6, checking);
+ else
+ bf_set(pde6_re, pde6, 0);
}
bf_set(pde6_ai, pde6, 1);
bf_set(pde6_ae, pde6, 0);
@@ -2125,6 +2231,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
split_offset = 0;
do {
+ /* Check to see if we ran out of space */
+ if (num_bde >= (phba->cfg_total_seg_cnt - 2))
+ return num_bde + 3;
+
/* setup PDE5 with what we have */
pde5 = (struct lpfc_pde5 *) bpl;
memset(pde5, 0, sizeof(struct lpfc_pde5));
@@ -2144,8 +2254,17 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR);
bf_set(pde6_optx, pde6, txop);
bf_set(pde6_oprx, pde6, rxop);
- bf_set(pde6_ce, pde6, checking);
- bf_set(pde6_re, pde6, checking);
+
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD))
+ bf_set(pde6_ce, pde6, checking);
+ else
+ bf_set(pde6_ce, pde6, 0);
+
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ bf_set(pde6_re, pde6, checking);
+ else
+ bf_set(pde6_re, pde6, 0);
+
bf_set(pde6_ai, pde6, 1);
bf_set(pde6_ae, pde6, 0);
bf_set(pde6_apptagval, pde6, 0);
@@ -2193,6 +2312,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
pgdone = 0;
subtotal = 0; /* total bytes processed for current prot grp */
while (!pgdone) {
+ /* Check to see if we ran out of space */
+ if (num_bde >= phba->cfg_total_seg_cnt)
+ return num_bde + 1;
+
if (!sgde) {
lpfc_printf_log(phba, KERN_ERR, LOG_BG,
"9065 BLKGRD:%s Invalid data segment\n",
@@ -2304,7 +2427,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
struct sli4_sge_diseed *diseed = NULL;
dma_addr_t physaddr;
int i = 0, num_sge = 0, status;
- int datadir = sc->sc_data_direction;
uint32_t reftag;
unsigned blksize;
uint8_t txop, rxop;
@@ -2342,13 +2464,26 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
diseed->ref_tag = cpu_to_le32(reftag);
diseed->ref_tag_tran = diseed->ref_tag;
+ /*
+ * We only need to check the data on READs, for WRITEs
+ * protection data is automatically generated, not checked.
+ */
+ if (sc->sc_data_direction == DMA_FROM_DEVICE) {
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD))
+ bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
+ else
+ bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
+
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
+ else
+ bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
+ }
+
/* setup DISEED with the rest of the info */
bf_set(lpfc_sli4_sge_dif_optx, diseed, txop);
bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop);
- if (datadir == DMA_FROM_DEVICE) {
- bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
- bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
- }
+
bf_set(lpfc_sli4_sge_dif_ai, diseed, 1);
bf_set(lpfc_sli4_sge_dif_me, diseed, 0);
@@ -2477,6 +2612,10 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
split_offset = 0;
do {
+ /* Check to see if we ran out of space */
+ if (num_sge >= (phba->cfg_total_seg_cnt - 2))
+ return num_sge + 3;
+
/* setup DISEED with what we have */
diseed = (struct sli4_sge_diseed *) sgl;
memset(diseed, 0, sizeof(struct sli4_sge_diseed));
@@ -2486,11 +2625,34 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
diseed->ref_tag = cpu_to_le32(reftag);
diseed->ref_tag_tran = diseed->ref_tag;
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD)) {
+ bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
+
+ } else {
+ bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
+ /*
+ * When in this mode, the hardware will replace
+ * the guard tag from the host with a
+ * newly generated good CRC for the wire.
+ * Switch to raw mode here to avoid this
+ * behavior. What the host sends gets put on the wire.
+ */
+ if (txop == BG_OP_IN_CRC_OUT_CRC) {
+ txop = BG_OP_RAW_MODE;
+ rxop = BG_OP_RAW_MODE;
+ }
+ }
+
+
+ if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
+ else
+ bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
+
/* setup DISEED with the rest of the info */
bf_set(lpfc_sli4_sge_dif_optx, diseed, txop);
bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop);
- bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
- bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
+
bf_set(lpfc_sli4_sge_dif_ai, diseed, 1);
bf_set(lpfc_sli4_sge_dif_me, diseed, 0);
@@ -2536,6 +2698,10 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
pgdone = 0;
subtotal = 0; /* total bytes processed for current prot grp */
while (!pgdone) {
+ /* Check to see if we ran out of space */
+ if (num_sge >= phba->cfg_total_seg_cnt)
+ return num_sge + 1;
+
if (!sgde) {
lpfc_printf_log(phba, KERN_ERR, LOG_BG,
"9086 BLKGRD:%s Invalid data segment\n",
@@ -2641,15 +2807,57 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc)
ret = LPFC_PG_TYPE_DIF_BUF;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
- "9021 Unsupported protection op:%d\n", op);
+ if (phba)
+ lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ "9021 Unsupported protection op:%d\n",
+ op);
break;
}
-
return ret;
}
/**
+ * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard
+ * @phba: The Hba for which this call is being executed.
+ * @lpfc_cmd: The scsi buffer which is going to be adjusted.
+ *
+ * Adjust the data length to account for how much data
+ * is actually on the wire.
+ *
+ * returns the adjusted data length
+ **/
+static int
+lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba,
+ struct lpfc_scsi_buf *lpfc_cmd)
+{
+ struct scsi_cmnd *sc = lpfc_cmd->pCmd;
+ int fcpdl;
+
+ fcpdl = scsi_bufflen(sc);
+
+ /* Check if there is protection data on the wire */
+ if (sc->sc_data_direction == DMA_FROM_DEVICE) {
+ /* Read check for protection data */
+ if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT)
+ return fcpdl;
+
+ } else {
+ /* Write check for protection data */
+ if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP)
+ return fcpdl;
+ }
+
+ /*
+ * If we are in DIF Type 1 mode every data block has a 8 byte
+ * DIF (trailer) attached to it. Must ajust FCP data length
+ * to account for the protection data.
+ */
+ fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8;
+
+ return fcpdl;
+}
+
+/**
* lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec
* @phba: The Hba for which this call is being executed.
* @lpfc_cmd: The scsi buffer which is going to be prep'ed.
@@ -2669,8 +2877,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
uint32_t num_bde = 0;
int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
int prot_group_type = 0;
- int diflen, fcpdl;
- unsigned blksize;
+ int fcpdl;
/*
* Start the lpfc command prep by bumping the bpl beyond fcp_cmnd
@@ -2691,28 +2898,28 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
return 1;
lpfc_cmd->seg_cnt = datasegcnt;
- if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9067 BLKGRD: %s: Too many sg segments"
- " from dma_map_sg. Config %d, seg_cnt"
- " %d\n",
- __func__, phba->cfg_sg_seg_cnt,
- lpfc_cmd->seg_cnt);
- scsi_dma_unmap(scsi_cmnd);
- return 1;
- }
+
+ /* First check if data segment count from SCSI Layer is good */
+ if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt)
+ goto err;
prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd);
switch (prot_group_type) {
case LPFC_PG_TYPE_NO_DIF:
+
+ /* Here we need to add a PDE5 and PDE6 to the count */
+ if ((lpfc_cmd->seg_cnt + 2) > phba->cfg_total_seg_cnt)
+ goto err;
+
num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl,
datasegcnt);
/* we should have 2 or more entries in buffer list */
if (num_bde < 2)
goto err;
break;
- case LPFC_PG_TYPE_DIF_BUF:{
+
+ case LPFC_PG_TYPE_DIF_BUF:
/*
* This type indicates that protection buffers are
* passed to the driver, so that needs to be prepared
@@ -2727,31 +2934,28 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
}
lpfc_cmd->prot_seg_cnt = protsegcnt;
- if (lpfc_cmd->prot_seg_cnt
- > phba->cfg_prot_sg_seg_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9068 BLKGRD: %s: Too many prot sg "
- "segments from dma_map_sg. Config %d,"
- "prot_seg_cnt %d\n", __func__,
- phba->cfg_prot_sg_seg_cnt,
- lpfc_cmd->prot_seg_cnt);
- dma_unmap_sg(&phba->pcidev->dev,
- scsi_prot_sglist(scsi_cmnd),
- scsi_prot_sg_count(scsi_cmnd),
- datadir);
- scsi_dma_unmap(scsi_cmnd);
- return 1;
- }
+
+ /*
+ * There is a minimun of 4 BPLs used for every
+ * protection data segment.
+ */
+ if ((lpfc_cmd->prot_seg_cnt * 4) >
+ (phba->cfg_total_seg_cnt - 2))
+ goto err;
num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl,
datasegcnt, protsegcnt);
/* we should have 3 or more entries in buffer list */
- if (num_bde < 3)
+ if ((num_bde < 3) ||
+ (num_bde > phba->cfg_total_seg_cnt))
goto err;
break;
- }
+
case LPFC_PG_TYPE_INVALID:
default:
+ scsi_dma_unmap(scsi_cmnd);
+ lpfc_cmd->seg_cnt = 0;
+
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"9022 Unexpected protection group %i\n",
prot_group_type);
@@ -2770,18 +2974,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
iocb_cmd->ulpBdeCount = 1;
iocb_cmd->ulpLe = 1;
- fcpdl = scsi_bufflen(scsi_cmnd);
-
- if (scsi_get_prot_type(scsi_cmnd) == SCSI_PROT_DIF_TYPE1) {
- /*
- * We are in DIF Type 1 mode
- * Every data block has a 8 byte DIF (trailer)
- * attached to it. Must ajust FCP data length
- */
- blksize = lpfc_cmd_blksize(scsi_cmnd);
- diflen = (fcpdl / blksize) * 8;
- fcpdl += diflen;
- }
+ fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
/*
@@ -2792,14 +2985,234 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
return 0;
err:
+ if (lpfc_cmd->seg_cnt)
+ scsi_dma_unmap(scsi_cmnd);
+ if (lpfc_cmd->prot_seg_cnt)
+ dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd),
+ scsi_prot_sg_count(scsi_cmnd),
+ scsi_cmnd->sc_data_direction);
+
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
- "9023 Could not setup all needed BDE's"
- "prot_group_type=%d, num_bde=%d\n",
+ "9023 Cannot setup S/G List for HBA"
+ "IO segs %d/%d BPL %d SCSI %d: %d %d\n",
+ lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
+ phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
prot_group_type, num_bde);
+
+ lpfc_cmd->seg_cnt = 0;
+ lpfc_cmd->prot_seg_cnt = 0;
return 1;
}
/*
+ * This function calcuates the T10 DIF guard tag
+ * on the specified data using a CRC algorithmn
+ * using crc_t10dif.
+ */
+uint16_t
+lpfc_bg_crc(uint8_t *data, int count)
+{
+ uint16_t crc = 0;
+ uint16_t x;
+
+ crc = crc_t10dif(data, count);
+ x = cpu_to_be16(crc);
+ return x;
+}
+
+/*
+ * This function calcuates the T10 DIF guard tag
+ * on the specified data using a CSUM algorithmn
+ * using ip_compute_csum.
+ */
+uint16_t
+lpfc_bg_csum(uint8_t *data, int count)
+{
+ uint16_t ret;
+
+ ret = ip_compute_csum(data, count);
+ return ret;
+}
+
+/*
+ * This function examines the protection data to try to determine
+ * what type of T10-DIF error occurred.
+ */
+void
+lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
+{
+ struct scatterlist *sgpe; /* s/g prot entry */
+ struct scatterlist *sgde; /* s/g data entry */
+ struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
+ struct scsi_dif_tuple *src = NULL;
+ uint8_t *data_src = NULL;
+ uint16_t guard_tag, guard_type;
+ uint16_t start_app_tag, app_tag;
+ uint32_t start_ref_tag, ref_tag;
+ int prot, protsegcnt;
+ int err_type, len, data_len;
+ int chk_ref, chk_app, chk_guard;
+ uint16_t sum;
+ unsigned blksize;
+
+ err_type = BGS_GUARD_ERR_MASK;
+ sum = 0;
+ guard_tag = 0;
+
+ /* First check to see if there is protection data to examine */
+ prot = scsi_get_prot_op(cmd);
+ if ((prot == SCSI_PROT_READ_STRIP) ||
+ (prot == SCSI_PROT_WRITE_INSERT) ||
+ (prot == SCSI_PROT_NORMAL))
+ goto out;
+
+ /* Currently the driver just supports ref_tag and guard_tag checking */
+ chk_ref = 1;
+ chk_app = 0;
+ chk_guard = 0;
+
+ /* Setup a ptr to the protection data provided by the SCSI host */
+ sgpe = scsi_prot_sglist(cmd);
+ protsegcnt = lpfc_cmd->prot_seg_cnt;
+
+ if (sgpe && protsegcnt) {
+
+ /*
+ * We will only try to verify guard tag if the segment
+ * data length is a multiple of the blksize.
+ */
+ sgde = scsi_sglist(cmd);
+ blksize = lpfc_cmd_blksize(cmd);
+ data_src = (uint8_t *)sg_virt(sgde);
+ data_len = sgde->length;
+ if ((data_len & (blksize - 1)) == 0)
+ chk_guard = 1;
+ guard_type = scsi_host_get_guard(cmd->device->host);
+
+ src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+ start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */
+ start_app_tag = src->app_tag;
+ len = sgpe->length;
+ while (src && protsegcnt) {
+ while (len) {
+
+ /*
+ * First check to see if a protection data
+ * check is valid
+ */
+ if ((src->ref_tag == 0xffffffff) ||
+ (src->app_tag == 0xffff)) {
+ start_ref_tag++;
+ goto skipit;
+ }
+
+ /* First Guard Tag checking */
+ if (chk_guard) {
+ guard_tag = src->guard_tag;
+ if (lpfc_cmd_guard_csum(cmd))
+ sum = lpfc_bg_csum(data_src,
+ blksize);
+ else
+ sum = lpfc_bg_crc(data_src,
+ blksize);
+ if ((guard_tag != sum)) {
+ err_type = BGS_GUARD_ERR_MASK;
+ goto out;
+ }
+ }
+
+ /* Reference Tag checking */
+ ref_tag = be32_to_cpu(src->ref_tag);
+ if (chk_ref && (ref_tag != start_ref_tag)) {
+ err_type = BGS_REFTAG_ERR_MASK;
+ goto out;
+ }
+ start_ref_tag++;
+
+ /* App Tag checking */
+ app_tag = src->app_tag;
+ if (chk_app && (app_tag != start_app_tag)) {
+ err_type = BGS_APPTAG_ERR_MASK;
+ goto out;
+ }
+skipit:
+ len -= sizeof(struct scsi_dif_tuple);
+ if (len < 0)
+ len = 0;
+ src++;
+
+ data_src += blksize;
+ data_len -= blksize;
+
+ /*
+ * Are we at the end of the Data segment?
+ * The data segment is only used for Guard
+ * tag checking.
+ */
+ if (chk_guard && (data_len == 0)) {
+ chk_guard = 0;
+ sgde = sg_next(sgde);
+ if (!sgde)
+ goto out;
+
+ data_src = (uint8_t *)sg_virt(sgde);
+ data_len = sgde->length;
+ if ((data_len & (blksize - 1)) == 0)
+ chk_guard = 1;
+ }
+ }
+
+ /* Goto the next Protection data segment */
+ sgpe = sg_next(sgpe);
+ if (sgpe) {
+ src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+ len = sgpe->length;
+ } else {
+ src = NULL;
+ }
+ protsegcnt--;
+ }
+ }
+out:
+ if (err_type == BGS_GUARD_ERR_MASK) {
+ scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+ 0x10, 0x1);
+ cmd->result = DRIVER_SENSE << 24
+ | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
+ phba->bg_guard_err_cnt++;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9069 BLKGRD: LBA %lx grd_tag error %x != %x\n",
+ (unsigned long)scsi_get_lba(cmd),
+ sum, guard_tag);
+
+ } else if (err_type == BGS_REFTAG_ERR_MASK) {
+ scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+ 0x10, 0x3);
+ cmd->result = DRIVER_SENSE << 24
+ | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
+
+ phba->bg_reftag_err_cnt++;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9066 BLKGRD: LBA %lx ref_tag error %x != %x\n",
+ (unsigned long)scsi_get_lba(cmd),
+ ref_tag, start_ref_tag);
+
+ } else if (err_type == BGS_APPTAG_ERR_MASK) {
+ scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+ 0x10, 0x2);
+ cmd->result = DRIVER_SENSE << 24
+ | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
+
+ phba->bg_apptag_err_cnt++;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9041 BLKGRD: LBA %lx app_tag error %x != %x\n",
+ (unsigned long)scsi_get_lba(cmd),
+ app_tag, start_app_tag);
+ }
+}
+
+
+/*
* This function checks for BlockGuard errors detected by
* the HBA. In case of errors, the ASC/ASCQ fields in the
* sense buffer will be set accordingly, paired with
@@ -2822,12 +3235,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
uint32_t bgstat = bgf->bgstat;
uint64_t failing_sector = 0;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9069 BLKGRD: BG ERROR in cmd"
- " 0x%x lba 0x%llx blk cnt 0x%x "
- "bgstat=0x%x bghm=0x%x\n",
- cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd),
- blk_rq_sectors(cmd->request), bgstat, bghm);
-
spin_lock(&_dump_buf_lock);
if (!_dump_buf_done) {
lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9070 BLKGRD: Saving"
@@ -2850,18 +3257,24 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
if (lpfc_bgs_get_invalid_prof(bgstat)) {
cmd->result = ScsiResult(DID_ERROR, 0);
- lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9072 BLKGRD: Invalid"
- " BlockGuard profile. bgstat:0x%x\n",
- bgstat);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9072 BLKGRD: Invalid BG Profile in cmd"
+ " 0x%x lba 0x%llx blk cnt 0x%x "
+ "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+ (unsigned long long)scsi_get_lba(cmd),
+ blk_rq_sectors(cmd->request), bgstat, bghm);
ret = (-1);
goto out;
}
if (lpfc_bgs_get_uninit_dif_block(bgstat)) {
cmd->result = ScsiResult(DID_ERROR, 0);
- lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9073 BLKGRD: "
- "Invalid BlockGuard DIF Block. bgstat:0x%x\n",
- bgstat);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9073 BLKGRD: Invalid BG PDIF Block in cmd"
+ " 0x%x lba 0x%llx blk cnt 0x%x "
+ "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+ (unsigned long long)scsi_get_lba(cmd),
+ blk_rq_sectors(cmd->request), bgstat, bghm);
ret = (-1);
goto out;
}
@@ -2874,8 +3287,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
cmd->result = DRIVER_SENSE << 24
| ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
phba->bg_guard_err_cnt++;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9055 BLKGRD: guard_tag error\n");
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9055 BLKGRD: Guard Tag error in cmd"
+ " 0x%x lba 0x%llx blk cnt 0x%x "
+ "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+ (unsigned long long)scsi_get_lba(cmd),
+ blk_rq_sectors(cmd->request), bgstat, bghm);
}
if (lpfc_bgs_get_reftag_err(bgstat)) {
@@ -2887,8 +3304,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
| ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
phba->bg_reftag_err_cnt++;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9056 BLKGRD: ref_tag error\n");
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9056 BLKGRD: Ref Tag error in cmd"
+ " 0x%x lba 0x%llx blk cnt 0x%x "
+ "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+ (unsigned long long)scsi_get_lba(cmd),
+ blk_rq_sectors(cmd->request), bgstat, bghm);
}
if (lpfc_bgs_get_apptag_err(bgstat)) {
@@ -2900,8 +3321,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
| ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
phba->bg_apptag_err_cnt++;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9061 BLKGRD: app_tag error\n");
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9061 BLKGRD: App Tag error in cmd"
+ " 0x%x lba 0x%llx blk cnt 0x%x "
+ "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+ (unsigned long long)scsi_get_lba(cmd),
+ blk_rq_sectors(cmd->request), bgstat, bghm);
}
if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
@@ -2940,11 +3365,16 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
if (!ret) {
/* No error was reported - problem in FW? */
- cmd->result = ScsiResult(DID_ERROR, 0);
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9057 BLKGRD: Unknown error reported!\n");
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9057 BLKGRD: Unknown error in cmd"
+ " 0x%x lba 0x%llx blk cnt 0x%x "
+ "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+ (unsigned long long)scsi_get_lba(cmd),
+ blk_rq_sectors(cmd->request), bgstat, bghm);
+
+ /* Calcuate what type of error it was */
+ lpfc_calc_bg_err(phba, lpfc_cmd);
}
-
out:
return ret;
}
@@ -3008,6 +3438,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
"dma_map_sg. Config %d, seg_cnt %d\n",
__func__, phba->cfg_sg_seg_cnt,
lpfc_cmd->seg_cnt);
+ lpfc_cmd->seg_cnt = 0;
scsi_dma_unmap(scsi_cmnd);
return 1;
}
@@ -3074,45 +3505,6 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
}
/**
- * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard
- * @phba: The Hba for which this call is being executed.
- * @lpfc_cmd: The scsi buffer which is going to be adjusted.
- *
- * Adjust the data length to account for how much data
- * is actually on the wire.
- *
- * returns the adjusted data length
- **/
-static int
-lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba,
- struct lpfc_scsi_buf *lpfc_cmd)
-{
- struct scsi_cmnd *sc = lpfc_cmd->pCmd;
- int diflen, fcpdl;
- unsigned blksize;
-
- fcpdl = scsi_bufflen(sc);
-
- /* Check if there is protection data on the wire */
- if (sc->sc_data_direction == DMA_FROM_DEVICE) {
- /* Read */
- if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT)
- return fcpdl;
-
- } else {
- /* Write */
- if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP)
- return fcpdl;
- }
-
- /* If protection data on the wire, adjust the count accordingly */
- blksize = lpfc_cmd_blksize(sc);
- diflen = (fcpdl / blksize) * 8;
- fcpdl += diflen;
- return fcpdl;
-}
-
-/**
* lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec
* @phba: The Hba for which this call is being executed.
* @lpfc_cmd: The scsi buffer which is going to be mapped.
@@ -3129,14 +3521,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
struct sli4_sge *sgl = (struct sli4_sge *)(lpfc_cmd->fcp_bpl);
IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
- uint32_t num_bde = 0;
+ uint32_t num_sge = 0;
int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
int prot_group_type = 0;
int fcpdl;
/*
* Start the lpfc command prep by bumping the sgl beyond fcp_cmnd
- * fcp_rsp regions to the first data bde entry
+ * fcp_rsp regions to the first data sge entry
*/
if (scsi_sg_count(scsi_cmnd)) {
/*
@@ -3159,28 +3551,28 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
sgl += 1;
lpfc_cmd->seg_cnt = datasegcnt;
- if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9087 BLKGRD: %s: Too many sg segments"
- " from dma_map_sg. Config %d, seg_cnt"
- " %d\n",
- __func__, phba->cfg_sg_seg_cnt,
- lpfc_cmd->seg_cnt);
- scsi_dma_unmap(scsi_cmnd);
- return 1;
- }
+
+ /* First check if data segment count from SCSI Layer is good */
+ if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt)
+ goto err;
prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd);
switch (prot_group_type) {
case LPFC_PG_TYPE_NO_DIF:
- num_bde = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl,
+ /* Here we need to add a DISEED to the count */
+ if ((lpfc_cmd->seg_cnt + 1) > phba->cfg_total_seg_cnt)
+ goto err;
+
+ num_sge = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl,
datasegcnt);
+
/* we should have 2 or more entries in buffer list */
- if (num_bde < 2)
+ if (num_sge < 2)
goto err;
break;
- case LPFC_PG_TYPE_DIF_BUF:{
+
+ case LPFC_PG_TYPE_DIF_BUF:
/*
* This type indicates that protection buffers are
* passed to the driver, so that needs to be prepared
@@ -3195,31 +3587,28 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
}
lpfc_cmd->prot_seg_cnt = protsegcnt;
- if (lpfc_cmd->prot_seg_cnt
- > phba->cfg_prot_sg_seg_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9088 BLKGRD: %s: Too many prot sg "
- "segments from dma_map_sg. Config %d,"
- "prot_seg_cnt %d\n", __func__,
- phba->cfg_prot_sg_seg_cnt,
- lpfc_cmd->prot_seg_cnt);
- dma_unmap_sg(&phba->pcidev->dev,
- scsi_prot_sglist(scsi_cmnd),
- scsi_prot_sg_count(scsi_cmnd),
- datadir);
- scsi_dma_unmap(scsi_cmnd);
- return 1;
- }
+ /*
+ * There is a minimun of 3 SGEs used for every
+ * protection data segment.
+ */
+ if ((lpfc_cmd->prot_seg_cnt * 3) >
+ (phba->cfg_total_seg_cnt - 2))
+ goto err;
- num_bde = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl,
+ num_sge = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl,
datasegcnt, protsegcnt);
+
/* we should have 3 or more entries in buffer list */
- if (num_bde < 3)
+ if ((num_sge < 3) ||
+ (num_sge > phba->cfg_total_seg_cnt))
goto err;
break;
- }
+
case LPFC_PG_TYPE_INVALID:
default:
+ scsi_dma_unmap(scsi_cmnd);
+ lpfc_cmd->seg_cnt = 0;
+
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"9083 Unexpected protection group %i\n",
prot_group_type);
@@ -3243,7 +3632,6 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
}
fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
-
fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
/*
@@ -3254,10 +3642,22 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
return 0;
err:
+ if (lpfc_cmd->seg_cnt)
+ scsi_dma_unmap(scsi_cmnd);
+ if (lpfc_cmd->prot_seg_cnt)
+ dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd),
+ scsi_prot_sg_count(scsi_cmnd),
+ scsi_cmnd->sc_data_direction);
+
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
- "9084 Could not setup all needed BDE's"
- "prot_group_type=%d, num_bde=%d\n",
- prot_group_type, num_bde);
+ "9084 Cannot setup S/G List for HBA"
+ "IO segs %d/%d SGL %d SCSI %d: %d %d\n",
+ lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
+ phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
+ prot_group_type, num_sge);
+
+ lpfc_cmd->seg_cnt = 0;
+ lpfc_cmd->prot_seg_cnt = 0;
return 1;
}
@@ -3690,7 +4090,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
cmd->device ? cmd->device->id : 0xffff,
cmd->device ? cmd->device->lun : 0xffff,
lpfc_cmd->status, lpfc_cmd->result,
- vport->fc_myDID, pnode->nlp_DID,
+ vport->fc_myDID,
+ (pnode) ? pnode->nlp_DID : 0,
phba->sli_rev == LPFC_SLI_REV4 ?
lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff,
pIocbOut->iocb.ulpContext,
@@ -3972,7 +4373,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
break;
}
} else
- fcp_cmnd->fcpCntl1 = 0;
+ fcp_cmnd->fcpCntl1 = SIMPLE_Q;
sli4 = (phba->sli_rev == LPFC_SLI_REV4);
@@ -4226,7 +4627,7 @@ static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
unsigned long poll_tmo_expires =
(jiffies + msecs_to_jiffies(phba->cfg_poll_tmo));
- if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt)
+ if (!list_empty(&phba->sli.ring[LPFC_FCP_RING].txcmplq))
mod_timer(&phba->fcp_poll_timer,
poll_tmo_expires);
}
@@ -4337,7 +4738,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
if (vport->phba->cfg_enable_bg) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_BG,
+ lpfc_printf_vlog(vport,
+ KERN_INFO, LOG_SCSI_CMD,
"9033 BLKGRD: rcvd %s cmd:x%x "
"sector x%llx cnt %u pt %x\n",
dif_op_str[scsi_get_prot_op(cmnd)],
@@ -4349,7 +4751,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd);
} else {
if (vport->phba->cfg_enable_bg) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_BG,
+ lpfc_printf_vlog(vport,
+ KERN_INFO, LOG_SCSI_CMD,
"9038 BLKGRD: rcvd PROT_NORMAL cmd: "
"x%x sector x%llx cnt %u pt %x\n",
cmnd->cmnd[0],
@@ -4522,7 +4925,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
/* Wait for abort to complete */
wait_event_timeout(waitq,
(lpfc_cmd->pCmd != cmnd),
- (2*vport->cfg_devloss_tmo*HZ));
+ msecs_to_jiffies(2*vport->cfg_devloss_tmo*1000));
lpfc_cmd->waitq = NULL;
if (lpfc_cmd->pCmd == cmnd) {
@@ -4992,16 +5395,24 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd)
struct lpfc_hba *phba = vport->phba;
int rc, ret = SUCCESS;
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ "3172 SCSI layer issued Host Reset Data:\n");
+
lpfc_offline_prep(phba, LPFC_MBX_WAIT);
lpfc_offline(phba);
rc = lpfc_sli_brdrestart(phba);
if (rc)
ret = FAILED;
- lpfc_online(phba);
+ rc = lpfc_online(phba);
+ if (rc)
+ ret = FAILED;
lpfc_unblock_mgmt_io(phba);
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
- "3172 SCSI layer issued Host Reset Data: x%x\n", ret);
+ if (ret == FAILED) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ "3323 Failed host reset, bring it offline\n");
+ lpfc_sli4_offline_eratt(phba);
+ }
return ret;
}
@@ -5068,11 +5479,11 @@ lpfc_slave_alloc(struct scsi_device *sdev)
}
num_allocated = lpfc_new_scsi_buf(vport, num_to_alloc);
if (num_to_alloc != num_allocated) {
- lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
- "0708 Allocation request of %d "
- "command buffers did not succeed. "
- "Allocated %d buffers.\n",
- num_to_alloc, num_allocated);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ "0708 Allocation request of %d "
+ "command buffers did not succeed. "
+ "Allocated %d buffers.\n",
+ num_to_alloc, num_allocated);
}
if (num_allocated > 0)
phba->total_scsi_bufs += num_allocated;
@@ -5150,6 +5561,7 @@ struct scsi_host_template lpfc_template = {
.max_sectors = 0xFFFF,
.vendor_id = LPFC_NL_VENDOR_ID,
.change_queue_depth = lpfc_change_queue_depth,
+ .change_queue_type = lpfc_change_queue_type,
};
struct scsi_host_template lpfc_vport_template = {
@@ -5172,4 +5584,5 @@ struct scsi_host_template lpfc_vport_template = {
.shost_attrs = lpfc_vport_attrs,
.max_sectors = 0xFFFF,
.change_queue_depth = lpfc_change_queue_depth,
+ .change_queue_type = lpfc_change_queue_type,
};
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 21a2ffe..b1d9f7fc 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 624eab3..43440ca 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -124,10 +124,17 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
/* Ring Doorbell */
doorbell.word0 = 0;
- bf_set(lpfc_wq_doorbell_num_posted, &doorbell, 1);
- bf_set(lpfc_wq_doorbell_index, &doorbell, host_index);
- bf_set(lpfc_wq_doorbell_id, &doorbell, q->queue_id);
- writel(doorbell.word0, q->phba->sli4_hba.WQDBregaddr);
+ if (q->db_format == LPFC_DB_LIST_FORMAT) {
+ bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1);
+ bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index);
+ bf_set(lpfc_wq_db_list_fm_id, &doorbell, q->queue_id);
+ } else if (q->db_format == LPFC_DB_RING_FORMAT) {
+ bf_set(lpfc_wq_db_ring_fm_num_posted, &doorbell, 1);
+ bf_set(lpfc_wq_db_ring_fm_id, &doorbell, q->queue_id);
+ } else {
+ return -EINVAL;
+ }
+ writel(doorbell.word0, q->db_regaddr);
return 0;
}
@@ -431,11 +438,12 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
struct lpfc_rqe *temp_hrqe;
struct lpfc_rqe *temp_drqe;
struct lpfc_register doorbell;
- int put_index = hq->host_index;
+ int put_index;
/* sanity check on queue memory */
if (unlikely(!hq) || unlikely(!dq))
return -ENOMEM;
+ put_index = hq->host_index;
temp_hrqe = hq->qe[hq->host_index].rqe;
temp_drqe = dq->qe[dq->host_index].rqe;
@@ -456,10 +464,20 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
/* Ring The Header Receive Queue Doorbell */
if (!(hq->host_index % hq->entry_repost)) {
doorbell.word0 = 0;
- bf_set(lpfc_rq_doorbell_num_posted, &doorbell,
- hq->entry_repost);
- bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id);
- writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr);
+ if (hq->db_format == LPFC_DB_RING_FORMAT) {
+ bf_set(lpfc_rq_db_ring_fm_num_posted, &doorbell,
+ hq->entry_repost);
+ bf_set(lpfc_rq_db_ring_fm_id, &doorbell, hq->queue_id);
+ } else if (hq->db_format == LPFC_DB_LIST_FORMAT) {
+ bf_set(lpfc_rq_db_list_fm_num_posted, &doorbell,
+ hq->entry_repost);
+ bf_set(lpfc_rq_db_list_fm_index, &doorbell,
+ hq->host_index);
+ bf_set(lpfc_rq_db_list_fm_id, &doorbell, hq->queue_id);
+ } else {
+ return -EINVAL;
+ }
+ writel(doorbell.word0, hq->db_regaddr);
}
return put_index;
}
@@ -649,7 +667,7 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba)
spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag &= ~HBA_RRQ_ACTIVE;
- next_time = jiffies + HZ * (phba->fc_ratov + 1);
+ next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov + 1));
list_for_each_entry_safe(rrq, nextrrq,
&phba->active_rrq_list, list) {
if (time_after(jiffies, rrq->rrq_stop_time))
@@ -764,7 +782,7 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
return;
spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag &= ~HBA_RRQ_ACTIVE;
- next_time = jiffies + HZ * (phba->fc_ratov * 2);
+ next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov * 2));
list_splice_init(&phba->active_rrq_list, &rrq_list);
spin_unlock_irqrestore(&phba->hbalock, iflags);
@@ -855,14 +873,17 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
xritag, rxid, ndlp->nlp_DID, send_rrq);
return -EINVAL;
}
- rrq->send_rrq = send_rrq;
+ if (phba->cfg_enable_rrq == 1)
+ rrq->send_rrq = send_rrq;
+ else
+ rrq->send_rrq = 0;
rrq->xritag = xritag;
- rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
+ rrq->rrq_stop_time = jiffies +
+ msecs_to_jiffies(1000 * (phba->fc_ratov + 1));
rrq->ndlp = ndlp;
rrq->nlp_DID = ndlp->nlp_DID;
rrq->vport = ndlp->vport;
rrq->rxid = rxid;
- rrq->send_rrq = send_rrq;
spin_lock_irqsave(&phba->hbalock, iflags);
empty = list_empty(&phba->active_rrq_list);
list_add_tail(&rrq->list, &phba->active_rrq_list);
@@ -906,8 +927,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
} else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
!(piocbq->iocb_flag & LPFC_IO_LIBDFC))
ndlp = piocbq->context_un.ndlp;
- else if ((piocbq->iocb.ulpCommand == CMD_ELS_REQUEST64_CR) &&
- (piocbq->iocb_flag & LPFC_IO_LIBDFC))
+ else if (piocbq->iocb_flag & LPFC_IO_LIBDFC)
ndlp = piocbq->context_un.ndlp;
else
ndlp = piocbq->context1;
@@ -991,6 +1011,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
else
sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_lxritag);
+
if (sglq) {
if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) &&
(sglq->state != SGL_XRI_ABORTED)) {
@@ -1007,7 +1028,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
&phba->sli4_hba.lpfc_sgl_list);
/* Check if TXQ queue needs to be serviced */
- if (pring->txq_cnt)
+ if (!list_empty(&pring->txq))
lpfc_worker_wake_up(phba);
}
}
@@ -1038,6 +1059,7 @@ __lpfc_sli_release_iocbq_s3(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
+
/*
* Clean all volatile data fields, preserve iotag and node struct.
*/
@@ -1104,7 +1126,6 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist,
while (!list_empty(iocblist)) {
list_remove_head(iocblist, piocb, struct lpfc_iocbq, list);
-
if (!piocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, piocb);
else {
@@ -1292,9 +1313,6 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
list_add_tail(&piocb->list, &pring->txcmplq);
piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ;
- pring->txcmplq_cnt++;
- if (pring->txcmplq_cnt > pring->txcmplq_max)
- pring->txcmplq_max = pring->txcmplq_cnt;
if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
(piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
@@ -1303,7 +1321,8 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
BUG();
else
mod_timer(&piocb->vport->els_tmofunc,
- jiffies + HZ * (phba->fc_ratov << 1));
+ jiffies +
+ msecs_to_jiffies(1000 * (phba->fc_ratov << 1)));
}
@@ -1326,8 +1345,6 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
struct lpfc_iocbq *cmd_iocb;
list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
- if (cmd_iocb != NULL)
- pring->txq_cnt--;
return cmd_iocb;
}
@@ -1596,8 +1613,9 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
* (c) link attention events can be processed (fcp ring only)
* (d) IOCB processing is not blocked by the outstanding mbox command.
*/
- if (pring->txq_cnt &&
- lpfc_is_link_up(phba) &&
+
+ if (lpfc_is_link_up(phba) &&
+ (!list_empty(&pring->txq)) &&
(pring->ringno != phba->sli.fcp_ring ||
phba->sli.sli_flag & LPFC_PROCESS_LA)) {
@@ -2305,7 +2323,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
/* Mailbox cmd <cmd> Cmpl <cmpl> */
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
"(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p "
- "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
+ "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x "
+ "x%x x%x x%x\n",
pmb->vport ? pmb->vport->vpi : 0,
pmbox->mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba, pmb),
@@ -2319,7 +2338,10 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
pmbox->un.varWords[4],
pmbox->un.varWords[5],
pmbox->un.varWords[6],
- pmbox->un.varWords[7]);
+ pmbox->un.varWords[7],
+ pmbox->un.varWords[8],
+ pmbox->un.varWords[9],
+ pmbox->un.varWords[10]);
if (pmb->mbox_cmpl)
pmb->mbox_cmpl(phba,pmb);
@@ -2594,7 +2616,6 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
cmd_iocb = phba->sli.iocbq_lookup[iotag];
list_del_init(&cmd_iocb->list);
if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
- pring->txcmplq_cnt--;
cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
}
return cmd_iocb;
@@ -2632,7 +2653,6 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
/* remove from txcmpl queue list */
list_del_init(&cmd_iocb->list);
cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
- pring->txcmplq_cnt--;
return cmd_iocb;
}
}
@@ -2875,8 +2895,9 @@ void lpfc_poll_eratt(unsigned long ptr)
lpfc_worker_wake_up(phba);
else
/* Restart the timer for next eratt poll */
- mod_timer(&phba->eratt_poll, jiffies +
- HZ * LPFC_ERATT_POLL_INTERVAL);
+ mod_timer(&phba->eratt_poll,
+ jiffies +
+ msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
return;
}
@@ -3240,7 +3261,7 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (free_saveq) {
list_for_each_entry_safe(rspiocbp, next_iocb,
&saveq->list, list) {
- list_del(&rspiocbp->list);
+ list_del_init(&rspiocbp->list);
__lpfc_sli_release_iocbq(phba, rspiocbp);
}
__lpfc_sli_release_iocbq(phba, saveq);
@@ -3481,7 +3502,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
*/
spin_lock_irq(&phba->hbalock);
list_splice_init(&pring->txq, &completions);
- pring->txq_cnt = 0;
/* Next issue ABTS for everything on the txcmplq */
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
@@ -3518,11 +3538,9 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock);
/* Retrieve everything on txq */
list_splice_init(&pring->txq, &txq);
- pring->txq_cnt = 0;
/* Retrieve everything on the txcmplq */
list_splice_init(&pring->txcmplq, &txcmplq);
- pring->txcmplq_cnt = 0;
/* Indicate the I/O queues are flushed */
phba->hba_flag |= HBA_FCP_IOQ_FLUSH;
@@ -4548,7 +4566,8 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2708 This device does not support "
- "Advanced Error Reporting (AER)\n");
+ "Advanced Error Reporting (AER): %d\n",
+ rc);
phba->cfg_aer_support = 0;
}
}
@@ -4939,7 +4958,7 @@ out_free_mboxq:
static void
lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
{
- uint8_t fcp_eqidx;
+ int fcp_eqidx;
lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM);
lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM);
@@ -5481,6 +5500,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
list_del_init(&rsrc_blk->list);
kfree(rsrc_blk);
}
+ phba->sli4_hba.max_cfg_param.vpi_used = 0;
break;
case LPFC_RSC_TYPE_FCOE_XRI:
kfree(phba->sli4_hba.xri_bmask);
@@ -5622,6 +5642,13 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
}
/* RPIs. */
count = phba->sli4_hba.max_cfg_param.max_rpi;
+ if (count <= 0) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3279 Invalid provisioning of "
+ "rpi:%d\n", count);
+ rc = -EINVAL;
+ goto err_exit;
+ }
base = phba->sli4_hba.max_cfg_param.rpi_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
phba->sli4_hba.rpi_bmask = kzalloc(longs *
@@ -5644,6 +5671,13 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
/* VPIs. */
count = phba->sli4_hba.max_cfg_param.max_vpi;
+ if (count <= 0) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3280 Invalid provisioning of "
+ "vpi:%d\n", count);
+ rc = -EINVAL;
+ goto free_rpi_ids;
+ }
base = phba->sli4_hba.max_cfg_param.vpi_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
phba->vpi_bmask = kzalloc(longs *
@@ -5666,6 +5700,13 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
/* XRIs. */
count = phba->sli4_hba.max_cfg_param.max_xri;
+ if (count <= 0) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3281 Invalid provisioning of "
+ "xri:%d\n", count);
+ rc = -EINVAL;
+ goto free_vpi_ids;
+ }
base = phba->sli4_hba.max_cfg_param.xri_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
phba->sli4_hba.xri_bmask = kzalloc(longs *
@@ -5689,6 +5730,13 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
/* VFIs. */
count = phba->sli4_hba.max_cfg_param.max_vfi;
+ if (count <= 0) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3282 Invalid provisioning of "
+ "vfi:%d\n", count);
+ rc = -EINVAL;
+ goto free_xri_ids;
+ }
base = phba->sli4_hba.max_cfg_param.vfi_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
phba->sli4_hba.vfi_bmask = kzalloc(longs *
@@ -5753,6 +5801,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI);
} else {
kfree(phba->vpi_bmask);
+ phba->sli4_hba.max_cfg_param.vpi_used = 0;
kfree(phba->vpi_ids);
bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
kfree(phba->sli4_hba.xri_bmask);
@@ -5934,7 +5983,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
struct lpfc_sglq *sglq_entry = NULL;
struct lpfc_sglq *sglq_entry_next = NULL;
struct lpfc_sglq *sglq_entry_first = NULL;
- int status, post_cnt = 0, num_posted = 0, block_cnt = 0;
+ int status, total_cnt, post_cnt = 0, num_posted = 0, block_cnt = 0;
int last_xritag = NO_XRI;
LIST_HEAD(prep_sgl_list);
LIST_HEAD(blck_sgl_list);
@@ -5942,10 +5991,11 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
LIST_HEAD(post_sgl_list);
LIST_HEAD(free_sgl_list);
- spin_lock(&phba->hbalock);
+ spin_lock_irq(&phba->hbalock);
list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &allc_sgl_list);
- spin_unlock(&phba->hbalock);
+ spin_unlock_irq(&phba->hbalock);
+ total_cnt = phba->sli4_hba.els_xri_cnt;
list_for_each_entry_safe(sglq_entry, sglq_entry_next,
&allc_sgl_list, list) {
list_del_init(&sglq_entry->list);
@@ -5997,9 +6047,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
sglq_entry->sli4_xritag);
list_add_tail(&sglq_entry->list,
&free_sgl_list);
- spin_lock_irq(&phba->hbalock);
- phba->sli4_hba.els_xri_cnt--;
- spin_unlock_irq(&phba->hbalock);
+ total_cnt--;
}
}
}
@@ -6027,9 +6075,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
(sglq_entry_first->sli4_xritag +
post_cnt - 1));
list_splice_init(&blck_sgl_list, &free_sgl_list);
- spin_lock_irq(&phba->hbalock);
- phba->sli4_hba.els_xri_cnt -= post_cnt;
- spin_unlock_irq(&phba->hbalock);
+ total_cnt -= post_cnt;
}
/* don't reset xirtag due to hole in xri block */
@@ -6039,16 +6085,18 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
/* reset els sgl post count for next round of posting */
post_cnt = 0;
}
+ /* update the number of XRIs posted for ELS */
+ phba->sli4_hba.els_xri_cnt = total_cnt;
/* free the els sgls failed to post */
lpfc_free_sgl_list(phba, &free_sgl_list);
/* push els sgls posted to the availble list */
if (!list_empty(&post_sgl_list)) {
- spin_lock(&phba->hbalock);
+ spin_lock_irq(&phba->hbalock);
list_splice_init(&post_sgl_list,
&phba->sli4_hba.lpfc_sgl_list);
- spin_unlock(&phba->hbalock);
+ spin_unlock_irq(&phba->hbalock);
} else {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3161 Failure to post els sgl to port.\n");
@@ -6388,16 +6436,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
/* Start the ELS watchdog timer */
mod_timer(&vport->els_tmofunc,
- jiffies + HZ * (phba->fc_ratov * 2));
+ jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov * 2)));
/* Start heart beat timer */
mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+ jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
phba->hb_outstanding = 0;
phba->last_completion_time = jiffies;
/* Start error attention (ERATT) polling timer */
- mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
+ mod_timer(&phba->eratt_poll,
+ jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
/* Enable PCIe device Advanced Error Reporting (AER) if configured */
if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) {
@@ -6599,7 +6648,7 @@ static int
lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
uint32_t flag)
{
- MAILBOX_t *mb;
+ MAILBOX_t *mbx;
struct lpfc_sli *psli = &phba->sli;
uint32_t status, evtctr;
uint32_t ha_copy, hc_copy;
@@ -6653,7 +6702,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
psli = &phba->sli;
- mb = &pmbox->u.mb;
+ mbx = &pmbox->u.mb;
status = MBX_SUCCESS;
if (phba->link_state == LPFC_HBA_ERROR) {
@@ -6668,7 +6717,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
goto out_not_finished;
}
- if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT) {
+ if (mbx->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT) {
if (lpfc_readl(phba->HCregaddr, &hc_copy) ||
!(hc_copy & HC_MBINT_ENA)) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
@@ -6722,7 +6771,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
"(%d):0308 Mbox cmd issue - BUSY Data: "
"x%x x%x x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0xffffff,
- mb->mbxCommand, phba->pport->port_state,
+ mbx->mbxCommand, phba->pport->port_state,
psli->sli_flag, flag);
psli->slistat.mbox_busy++;
@@ -6732,15 +6781,15 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
lpfc_debugfs_disc_trc(pmbox->vport,
LPFC_DISC_TRC_MBOX_VPORT,
"MBOX Bsy vport: cmd:x%x mb:x%x x%x",
- (uint32_t)mb->mbxCommand,
- mb->un.varWords[0], mb->un.varWords[1]);
+ (uint32_t)mbx->mbxCommand,
+ mbx->un.varWords[0], mbx->un.varWords[1]);
}
else {
lpfc_debugfs_disc_trc(phba->pport,
LPFC_DISC_TRC_MBOX,
"MBOX Bsy: cmd:x%x mb:x%x x%x",
- (uint32_t)mb->mbxCommand,
- mb->un.varWords[0], mb->un.varWords[1]);
+ (uint32_t)mbx->mbxCommand,
+ mbx->un.varWords[0], mbx->un.varWords[1]);
}
return MBX_BUSY;
@@ -6751,7 +6800,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
/* If we are not polling, we MUST be in SLI2 mode */
if (flag != MBX_POLL) {
if (!(psli->sli_flag & LPFC_SLI_ACTIVE) &&
- (mb->mbxCommand != MBX_KILL_BOARD)) {
+ (mbx->mbxCommand != MBX_KILL_BOARD)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
@@ -6764,8 +6813,9 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
goto out_not_finished;
}
/* timeout active mbox command */
- mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, pmbox))));
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) *
+ 1000);
+ mod_timer(&psli->mbox_tmo, jiffies + timeout);
}
/* Mailbox cmd <cmd> issue */
@@ -6773,23 +6823,23 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
"(%d):0309 Mailbox cmd x%x issue Data: x%x x%x "
"x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
- mb->mbxCommand, phba->pport->port_state,
+ mbx->mbxCommand, phba->pport->port_state,
psli->sli_flag, flag);
- if (mb->mbxCommand != MBX_HEARTBEAT) {
+ if (mbx->mbxCommand != MBX_HEARTBEAT) {
if (pmbox->vport) {
lpfc_debugfs_disc_trc(pmbox->vport,
LPFC_DISC_TRC_MBOX_VPORT,
"MBOX Send vport: cmd:x%x mb:x%x x%x",
- (uint32_t)mb->mbxCommand,
- mb->un.varWords[0], mb->un.varWords[1]);
+ (uint32_t)mbx->mbxCommand,
+ mbx->un.varWords[0], mbx->un.varWords[1]);
}
else {
lpfc_debugfs_disc_trc(phba->pport,
LPFC_DISC_TRC_MBOX,
"MBOX Send: cmd:x%x mb:x%x x%x",
- (uint32_t)mb->mbxCommand,
- mb->un.varWords[0], mb->un.varWords[1]);
+ (uint32_t)mbx->mbxCommand,
+ mbx->un.varWords[0], mbx->un.varWords[1]);
}
}
@@ -6797,12 +6847,12 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
evtctr = psli->slistat.mbox_event;
/* next set own bit for the adapter and copy over command word */
- mb->mbxOwner = OWN_CHIP;
+ mbx->mbxOwner = OWN_CHIP;
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
/* Populate mbox extension offset word. */
if (pmbox->in_ext_byte_len || pmbox->out_ext_byte_len) {
- *(((uint32_t *)mb) + pmbox->mbox_offset_word)
+ *(((uint32_t *)mbx) + pmbox->mbox_offset_word)
= (uint8_t *)phba->mbox_ext
- (uint8_t *)phba->mbox;
}
@@ -6814,11 +6864,11 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
pmbox->in_ext_byte_len);
}
/* Copy command data to host SLIM area */
- lpfc_sli_pcimem_bcopy(mb, phba->mbox, MAILBOX_CMD_SIZE);
+ lpfc_sli_pcimem_bcopy(mbx, phba->mbox, MAILBOX_CMD_SIZE);
} else {
/* Populate mbox extension offset word. */
if (pmbox->in_ext_byte_len || pmbox->out_ext_byte_len)
- *(((uint32_t *)mb) + pmbox->mbox_offset_word)
+ *(((uint32_t *)mbx) + pmbox->mbox_offset_word)
= MAILBOX_HBA_EXT_OFFSET;
/* Copy the mailbox extension data */
@@ -6828,24 +6878,24 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
pmbox->context2, pmbox->in_ext_byte_len);
}
- if (mb->mbxCommand == MBX_CONFIG_PORT) {
+ if (mbx->mbxCommand == MBX_CONFIG_PORT) {
/* copy command data into host mbox for cmpl */
- lpfc_sli_pcimem_bcopy(mb, phba->mbox, MAILBOX_CMD_SIZE);
+ lpfc_sli_pcimem_bcopy(mbx, phba->mbox, MAILBOX_CMD_SIZE);
}
/* First copy mbox command data to HBA SLIM, skip past first
word */
to_slim = phba->MBslimaddr + sizeof (uint32_t);
- lpfc_memcpy_to_slim(to_slim, &mb->un.varWords[0],
+ lpfc_memcpy_to_slim(to_slim, &mbx->un.varWords[0],
MAILBOX_CMD_SIZE - sizeof (uint32_t));
/* Next copy over first word, with mbxOwner set */
- ldata = *((uint32_t *)mb);
+ ldata = *((uint32_t *)mbx);
to_slim = phba->MBslimaddr;
writel(ldata, to_slim);
readl(to_slim); /* flush */
- if (mb->mbxCommand == MBX_CONFIG_PORT) {
+ if (mbx->mbxCommand == MBX_CONFIG_PORT) {
/* switch over to host mailbox */
psli->sli_flag |= LPFC_SLI_ACTIVE;
}
@@ -6920,7 +6970,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
/* First copy command data */
word0 = *((uint32_t *)phba->mbox);
word0 = le32_to_cpu(word0);
- if (mb->mbxCommand == MBX_CONFIG_PORT) {
+ if (mbx->mbxCommand == MBX_CONFIG_PORT) {
MAILBOX_t *slimmb;
uint32_t slimword0;
/* Check real SLIM for any errors */
@@ -6947,7 +6997,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
/* copy results back to user */
- lpfc_sli_pcimem_bcopy(phba->mbox, mb, MAILBOX_CMD_SIZE);
+ lpfc_sli_pcimem_bcopy(phba->mbox, mbx, MAILBOX_CMD_SIZE);
/* Copy the mailbox extension data */
if (pmbox->out_ext_byte_len && pmbox->context2) {
lpfc_sli_pcimem_bcopy(phba->mbox_ext,
@@ -6956,7 +7006,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
}
} else {
/* First copy command data */
- lpfc_memcpy_from_slim(mb, phba->MBslimaddr,
+ lpfc_memcpy_from_slim(mbx, phba->MBslimaddr,
MAILBOX_CMD_SIZE);
/* Copy the mailbox extension data */
if (pmbox->out_ext_byte_len && pmbox->context2) {
@@ -6971,7 +7021,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
readl(phba->HAregaddr); /* flush */
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
- status = mb->mbxStatus;
+ status = mbx->mbxStatus;
}
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
@@ -7438,7 +7488,7 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
/* Start timer for the mbox_tmo and log some mailbox post messages */
mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, mboxq))));
+ msecs_to_jiffies(1000 * lpfc_mbox_tmo_val(phba, mboxq))));
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
"(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: "
@@ -7569,7 +7619,6 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
/* Insert the caller's iocb in the txq tail for later processing. */
list_add_tail(&piocb->list, &pring->txq);
- pring->txq_cnt++;
}
/**
@@ -7857,15 +7906,21 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
static inline uint32_t
lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba)
{
- int i;
+ struct lpfc_vector_map_info *cpup;
+ int chann, cpu;
- if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU)
- i = smp_processor_id();
- else
- i = atomic_add_return(1, &phba->fcp_qidx);
-
- i = (i % phba->cfg_fcp_io_channel);
- return i;
+ if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU) {
+ cpu = smp_processor_id();
+ if (cpu < phba->sli4_hba.num_present_cpu) {
+ cpup = phba->sli4_hba.cpu_map;
+ cpup += cpu;
+ return cpup->channel_id;
+ }
+ chann = cpu;
+ }
+ chann = atomic_add_return(1, &phba->fcp_qidx);
+ chann = (chann % phba->cfg_fcp_io_channel);
+ return chann;
}
/**
@@ -8341,7 +8396,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
sglq = NULL;
else {
- if (pring->txq_cnt) {
+ if (!list_empty(&pring->txq)) {
if (!(flag & SLI_IOCB_RET_IOCB)) {
__lpfc_sli_ringtx_put(phba,
pring, piocb);
@@ -8370,7 +8425,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
* This is a continuation of a commandi,(CX) so this
* sglq is on the active list
*/
- sglq = __lpfc_get_active_sglq(phba, piocb->sli4_xritag);
+ sglq = __lpfc_get_active_sglq(phba, piocb->sli4_lxritag);
if (!sglq)
return IOCB_ERROR;
}
@@ -8387,10 +8442,14 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
if ((piocb->iocb_flag & LPFC_IO_FCP) ||
(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
+ if (unlikely(!phba->sli4_hba.fcp_wq))
+ return IOCB_ERROR;
if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx],
&wqe))
return IOCB_ERROR;
} else {
+ if (unlikely(!phba->sli4_hba.els_wq))
+ return IOCB_ERROR;
if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe))
return IOCB_ERROR;
}
@@ -8655,7 +8714,7 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba,
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"3116 Port generated FCP XRI ABORT event on "
"vpi %d rpi %d xri x%x status 0x%x parameter x%x\n",
- ndlp->vport->vpi, ndlp->nlp_rpi,
+ ndlp->vport->vpi, phba->sli4_hba.rpi_ids[ndlp->nlp_rpi],
bf_get(lpfc_wcqe_xa_xri, axri),
bf_get(lpfc_wcqe_xa_status, axri),
axri->parameter);
@@ -8855,12 +8914,6 @@ lpfc_sli_setup(struct lpfc_hba *phba)
pring->prt[3].type = FC_TYPE_CT;
pring->prt[3].lpfc_sli_rcv_unsol_event =
lpfc_ct_unsol_event;
- /* abort unsolicited sequence */
- pring->prt[4].profile = 0; /* Mask 4 */
- pring->prt[4].rctl = FC_RCTL_BA_ABTS;
- pring->prt[4].type = FC_TYPE_BLS;
- pring->prt[4].lpfc_sli_rcv_unsol_event =
- lpfc_sli4_ct_abort_unsol_event;
break;
}
totiocbsize += (pring->sli.sli3.numCiocb *
@@ -9015,7 +9068,6 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
if (iocb->vport != vport)
continue;
list_move_tail(&iocb->list, &completions);
- pring->txq_cnt--;
}
/* Next issue ABTS for everything on the txcmplq */
@@ -9084,8 +9136,6 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
* given to the FW yet.
*/
list_splice_init(&pring->txq, &completions);
- pring->txq_cnt = 0;
-
}
spin_unlock_irqrestore(&phba->hbalock, flags);
@@ -9720,7 +9770,7 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "3096 ABORT_XRI_CN completing on xri x%x "
+ "3096 ABORT_XRI_CN completing on rpi x%x "
"original iotag x%x, abort cmd iotag x%x "
"status 0x%x, reason 0x%x\n",
cmdiocb->iocb.un.acxri.abortContextTag,
@@ -9926,6 +9976,9 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
long timeleft, timeout_req = 0;
int retval = IOCB_SUCCESS;
uint32_t creg_val;
+ struct lpfc_iocbq *iocb;
+ int txq_cnt = 0;
+ int txcmplq_cnt = 0;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
/*
* If the caller has provided a response iocbq buffer, then context2
@@ -9952,7 +10005,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
retval = lpfc_sli_issue_iocb(phba, ring_number, piocb,
SLI_IOCB_RET_IOCB);
if (retval == IOCB_SUCCESS) {
- timeout_req = timeout * HZ;
+ timeout_req = msecs_to_jiffies(timeout * 1000);
timeleft = wait_event_timeout(done_q,
lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE),
timeout_req);
@@ -9973,9 +10026,17 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
retval = IOCB_TIMEDOUT;
}
} else if (retval == IOCB_BUSY) {
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n",
- phba->iocb_cnt, pring->txq_cnt, pring->txcmplq_cnt);
+ if (phba->cfg_log_verbose & LOG_SLI) {
+ list_for_each_entry(iocb, &pring->txq, list) {
+ txq_cnt++;
+ }
+ list_for_each_entry(iocb, &pring->txcmplq, list) {
+ txcmplq_cnt++;
+ }
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n",
+ phba->iocb_cnt, txq_cnt, txcmplq_cnt);
+ }
return retval;
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -10031,12 +10092,13 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
uint32_t timeout)
{
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
+ MAILBOX_t *mb = NULL;
int retval;
unsigned long flag;
- /* The caller must leave context1 empty. */
+ /* The caller might set context1 for extended buffer */
if (pmboxq->context1)
- return MBX_NOT_FINISHED;
+ mb = (MAILBOX_t *)pmboxq->context1;
pmboxq->mbox_flag &= ~LPFC_MBX_WAKE;
/* setup wake call as IOCB callback */
@@ -10049,10 +10111,11 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
wait_event_interruptible_timeout(done_q,
pmboxq->mbox_flag & LPFC_MBX_WAKE,
- timeout * HZ);
+ msecs_to_jiffies(timeout * 1000));
spin_lock_irqsave(&phba->hbalock, flag);
- pmboxq->context1 = NULL;
+ /* restore the possible extended buffer for free resource */
+ pmboxq->context1 = (uint8_t *)mb;
/*
* if LPFC_MBX_WAKE flag is set the mailbox is completed
* else do not free the resources.
@@ -10065,6 +10128,9 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
}
spin_unlock_irqrestore(&phba->hbalock, flag);
+ } else {
+ /* restore the possible extended buffer for free resource */
+ pmboxq->context1 = (uint8_t *)mb;
}
return retval;
@@ -11258,16 +11324,25 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
struct lpfc_iocbq *irspiocbq;
unsigned long iflags;
struct lpfc_sli_ring *pring = cq->pring;
+ int txq_cnt = 0;
+ int txcmplq_cnt = 0;
+ int fcp_txcmplq_cnt = 0;
/* Get an irspiocbq for later ELS response processing use */
irspiocbq = lpfc_sli_get_iocbq(phba);
if (!irspiocbq) {
+ if (!list_empty(&pring->txq))
+ txq_cnt++;
+ if (!list_empty(&pring->txcmplq))
+ txcmplq_cnt++;
+ if (!list_empty(&phba->sli.ring[LPFC_FCP_RING].txcmplq))
+ fcp_txcmplq_cnt++;
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d "
"fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n",
- pring->txq_cnt, phba->iocb_cnt,
- phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt,
- phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt);
+ txq_cnt, phba->iocb_cnt,
+ fcp_txcmplq_cnt,
+ txcmplq_cnt);
return false;
}
@@ -11873,7 +11948,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
struct lpfc_eqe *eqe;
unsigned long iflag;
int ecount = 0;
- uint32_t fcp_eqidx;
+ int fcp_eqidx;
/* Get the driver's phba structure from the dev_id */
fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)dev_id;
@@ -11975,7 +12050,7 @@ lpfc_sli4_intr_handler(int irq, void *dev_id)
struct lpfc_hba *phba;
irqreturn_t hba_irq_rc;
bool hba_handled = false;
- uint32_t fcp_eqidx;
+ int fcp_eqidx;
/* Get the driver's phba structure from the dev_id */
phba = (struct lpfc_hba *)dev_id;
@@ -12097,6 +12172,54 @@ out_fail:
}
/**
+ * lpfc_dual_chute_pci_bar_map - Map pci base address register to host memory
+ * @phba: HBA structure that indicates port to create a queue on.
+ * @pci_barset: PCI BAR set flag.
+ *
+ * This function shall perform iomap of the specified PCI BAR address to host
+ * memory address if not already done so and return it. The returned host
+ * memory address can be NULL.
+ */
+static void __iomem *
+lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
+{
+ struct pci_dev *pdev;
+ unsigned long bar_map, bar_map_len;
+
+ if (!phba->pcidev)
+ return NULL;
+ else
+ pdev = phba->pcidev;
+
+ switch (pci_barset) {
+ case WQ_PCI_BAR_0_AND_1:
+ if (!phba->pci_bar0_memmap_p) {
+ bar_map = pci_resource_start(pdev, PCI_64BIT_BAR0);
+ bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR0);
+ phba->pci_bar0_memmap_p = ioremap(bar_map, bar_map_len);
+ }
+ return phba->pci_bar0_memmap_p;
+ case WQ_PCI_BAR_2_AND_3:
+ if (!phba->pci_bar2_memmap_p) {
+ bar_map = pci_resource_start(pdev, PCI_64BIT_BAR2);
+ bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR2);
+ phba->pci_bar2_memmap_p = ioremap(bar_map, bar_map_len);
+ }
+ return phba->pci_bar2_memmap_p;
+ case WQ_PCI_BAR_4_AND_5:
+ if (!phba->pci_bar4_memmap_p) {
+ bar_map = pci_resource_start(pdev, PCI_64BIT_BAR4);
+ bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR4);
+ phba->pci_bar4_memmap_p = ioremap(bar_map, bar_map_len);
+ }
+ return phba->pci_bar4_memmap_p;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/**
* lpfc_modify_fcp_eq_delay - Modify Delay Multiplier on FCP EQs
* @phba: HBA structure that indicates port to create a queue on.
* @startq: The starting FCP EQ to modify
@@ -12673,6 +12796,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
union lpfc_sli4_cfg_shdr *shdr;
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
struct dma_address *page;
+ void __iomem *bar_memmap_p;
+ uint32_t db_offset;
+ uint16_t pci_barset;
/* sanity check on queue memory */
if (!wq || !cq)
@@ -12696,6 +12822,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
cq->queue_id);
bf_set(lpfc_mbox_hdr_version, &shdr->request,
phba->sli4_hba.pc_sli4_params.wqv);
+
if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) {
bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1,
wq->entry_count);
@@ -12723,6 +12850,10 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys);
page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys);
}
+
+ if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE)
+ bf_set(lpfc_mbx_wq_create_dua, &wq_create->u.request, 1);
+
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
@@ -12740,6 +12871,48 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
status = -ENXIO;
goto out;
}
+ if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) {
+ wq->db_format = bf_get(lpfc_mbx_wq_create_db_format,
+ &wq_create->u.response);
+ if ((wq->db_format != LPFC_DB_LIST_FORMAT) &&
+ (wq->db_format != LPFC_DB_RING_FORMAT)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3265 WQ[%d] doorbell format not "
+ "supported: x%x\n", wq->queue_id,
+ wq->db_format);
+ status = -EINVAL;
+ goto out;
+ }
+ pci_barset = bf_get(lpfc_mbx_wq_create_bar_set,
+ &wq_create->u.response);
+ bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset);
+ if (!bar_memmap_p) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3263 WQ[%d] failed to memmap pci "
+ "barset:x%x\n", wq->queue_id,
+ pci_barset);
+ status = -ENOMEM;
+ goto out;
+ }
+ db_offset = wq_create->u.response.doorbell_offset;
+ if ((db_offset != LPFC_ULP0_WQ_DOORBELL) &&
+ (db_offset != LPFC_ULP1_WQ_DOORBELL)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3252 WQ[%d] doorbell offset not "
+ "supported: x%x\n", wq->queue_id,
+ db_offset);
+ status = -EINVAL;
+ goto out;
+ }
+ wq->db_regaddr = bar_memmap_p + db_offset;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3264 WQ[%d]: barset:x%x, offset:x%x, "
+ "format:x%x\n", wq->queue_id, pci_barset,
+ db_offset, wq->db_format);
+ } else {
+ wq->db_format = LPFC_DB_LIST_FORMAT;
+ wq->db_regaddr = phba->sli4_hba.WQDBregaddr;
+ }
wq->type = LPFC_WQ;
wq->assoc_qid = cq->queue_id;
wq->subtype = subtype;
@@ -12816,6 +12989,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
uint32_t shdr_status, shdr_add_status;
union lpfc_sli4_cfg_shdr *shdr;
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
+ void __iomem *bar_memmap_p;
+ uint32_t db_offset;
+ uint16_t pci_barset;
/* sanity check on queue memory */
if (!hrq || !drq || !cq)
@@ -12894,6 +13070,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
rq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
putPaddrHigh(dmabuf->phys);
}
+ if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE)
+ bf_set(lpfc_mbx_rq_create_dua, &rq_create->u.request, 1);
+
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
@@ -12911,6 +13090,51 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
status = -ENXIO;
goto out;
}
+
+ if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) {
+ hrq->db_format = bf_get(lpfc_mbx_rq_create_db_format,
+ &rq_create->u.response);
+ if ((hrq->db_format != LPFC_DB_LIST_FORMAT) &&
+ (hrq->db_format != LPFC_DB_RING_FORMAT)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3262 RQ [%d] doorbell format not "
+ "supported: x%x\n", hrq->queue_id,
+ hrq->db_format);
+ status = -EINVAL;
+ goto out;
+ }
+
+ pci_barset = bf_get(lpfc_mbx_rq_create_bar_set,
+ &rq_create->u.response);
+ bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset);
+ if (!bar_memmap_p) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3269 RQ[%d] failed to memmap pci "
+ "barset:x%x\n", hrq->queue_id,
+ pci_barset);
+ status = -ENOMEM;
+ goto out;
+ }
+
+ db_offset = rq_create->u.response.doorbell_offset;
+ if ((db_offset != LPFC_ULP0_RQ_DOORBELL) &&
+ (db_offset != LPFC_ULP1_RQ_DOORBELL)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3270 RQ[%d] doorbell offset not "
+ "supported: x%x\n", hrq->queue_id,
+ db_offset);
+ status = -EINVAL;
+ goto out;
+ }
+ hrq->db_regaddr = bar_memmap_p + db_offset;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3266 RQ[qid:%d]: barset:x%x, offset:x%x, "
+ "format:x%x\n", hrq->queue_id, pci_barset,
+ db_offset, hrq->db_format);
+ } else {
+ hrq->db_format = LPFC_DB_RING_FORMAT;
+ hrq->db_regaddr = phba->sli4_hba.RQDBregaddr;
+ }
hrq->type = LPFC_HRQ;
hrq->assoc_qid = cq->queue_id;
hrq->subtype = subtype;
@@ -12976,6 +13200,8 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
rq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
putPaddrHigh(dmabuf->phys);
}
+ if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE)
+ bf_set(lpfc_mbx_rq_create_dua, &rq_create->u.request, 1);
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
/* The IOCTL status is embedded in the mailbox subheader. */
shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
@@ -13754,13 +13980,14 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
}
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "2538 Received frame rctl:%s type:%s "
- "Frame Data:%08x %08x %08x %08x %08x %08x\n",
- rctl_names[fc_hdr->fh_r_ctl],
- type_names[fc_hdr->fh_type],
+ "2538 Received frame rctl:%s (x%x), type:%s (x%x), "
+ "frame Data:%08x %08x %08x %08x %08x %08x %08x\n",
+ rctl_names[fc_hdr->fh_r_ctl], fc_hdr->fh_r_ctl,
+ type_names[fc_hdr->fh_type], fc_hdr->fh_type,
be32_to_cpu(header[0]), be32_to_cpu(header[1]),
be32_to_cpu(header[2]), be32_to_cpu(header[3]),
- be32_to_cpu(header[4]), be32_to_cpu(header[5]));
+ be32_to_cpu(header[4]), be32_to_cpu(header[5]),
+ be32_to_cpu(header[6]));
return 0;
drop:
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -14063,6 +14290,40 @@ lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport,
}
/**
+ * lpfc_sli4_abort_ulp_seq - Abort assembled unsol sequence from ulp
+ * @vport: pointer to a vitural port
+ * @dmabuf: pointer to a dmabuf that describes the FC sequence
+ *
+ * This function tries to abort from the assembed sequence from upper level
+ * protocol, described by the information from basic abbort @dmabuf. It
+ * checks to see whether such pending context exists at upper level protocol.
+ * If so, it shall clean up the pending context.
+ *
+ * Return
+ * true -- if there is matching pending context of the sequence cleaned
+ * at ulp;
+ * false -- if there is no matching pending context of the sequence present
+ * at ulp.
+ **/
+static bool
+lpfc_sli4_abort_ulp_seq(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
+{
+ struct lpfc_hba *phba = vport->phba;
+ int handled;
+
+ /* Accepting abort at ulp with SLI4 only */
+ if (phba->sli_rev < LPFC_SLI_REV4)
+ return false;
+
+ /* Register all caring upper level protocols to attend abort */
+ handled = lpfc_ct_handle_unsol_abort(phba, dmabuf);
+ if (handled)
+ return true;
+
+ return false;
+}
+
+/**
* lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler
* @phba: Pointer to HBA context object.
* @cmd_iocbq: pointer to the command iocbq structure.
@@ -14077,8 +14338,14 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
struct lpfc_iocbq *cmd_iocbq,
struct lpfc_iocbq *rsp_iocbq)
{
- if (cmd_iocbq)
+ struct lpfc_nodelist *ndlp;
+
+ if (cmd_iocbq) {
+ ndlp = (struct lpfc_nodelist *)cmd_iocbq->context1;
+ lpfc_nlp_put(ndlp);
+ lpfc_nlp_not_used(ndlp);
lpfc_sli_release_iocbq(phba, cmd_iocbq);
+ }
/* Failure means BLS ABORT RSP did not get delivered to remote node*/
if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus)
@@ -14118,9 +14385,10 @@ lpfc_sli4_xri_inrange(struct lpfc_hba *phba,
* event after aborting the sequence handling.
**/
static void
-lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
- struct fc_frame_header *fc_hdr)
+lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport,
+ struct fc_frame_header *fc_hdr, bool aborted)
{
+ struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *ctiocb = NULL;
struct lpfc_nodelist *ndlp;
uint16_t oxid, rxid, xri, lxri;
@@ -14135,12 +14403,27 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
oxid = be16_to_cpu(fc_hdr->fh_ox_id);
rxid = be16_to_cpu(fc_hdr->fh_rx_id);
- ndlp = lpfc_findnode_did(phba->pport, sid);
+ ndlp = lpfc_findnode_did(vport, sid);
if (!ndlp) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
- "1268 Find ndlp returned NULL for oxid:x%x "
- "SID:x%x\n", oxid, sid);
- return;
+ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+ if (!ndlp) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+ "1268 Failed to allocate ndlp for "
+ "oxid:x%x SID:x%x\n", oxid, sid);
+ return;
+ }
+ lpfc_nlp_init(vport, ndlp, sid);
+ /* Put ndlp onto pport node list */
+ lpfc_enqueue_node(vport, ndlp);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ /* re-setup ndlp without removing from node list */
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+ "3275 Failed to active ndlp found "
+ "for oxid:x%x SID:x%x\n", oxid, sid);
+ return;
+ }
}
/* Allocate buffer for rsp iocb */
@@ -14164,7 +14447,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
icmd->ulpLe = 1;
icmd->ulpClass = CLASS3;
icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
- ctiocb->context1 = ndlp;
+ ctiocb->context1 = lpfc_nlp_get(ndlp);
ctiocb->iocb_cmpl = NULL;
ctiocb->vport = phba->pport;
@@ -14183,14 +14466,24 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
if (lxri != NO_XRI)
lpfc_set_rrq_active(phba, ndlp, lxri,
(xri == oxid) ? rxid : oxid, 0);
- /* If the oxid maps to the FCP XRI range or if it is out of range,
- * send a BLS_RJT. The driver no longer has that exchange.
- * Override the IOCB for a BA_RJT.
+ /* For BA_ABTS from exchange responder, if the logical xri with
+ * the oxid maps to the FCP XRI range, the port no longer has
+ * that exchange context, send a BLS_RJT. Override the IOCB for
+ * a BA_RJT.
+ */
+ if ((fctl & FC_FC_EX_CTX) &&
+ (lxri > lpfc_sli4_get_els_iocb_cnt(phba))) {
+ icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
+ bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
+ bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
+ bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE);
+ }
+
+ /* If BA_ABTS failed to abort a partially assembled receive sequence,
+ * the driver no longer has that exchange, send a BLS_RJT. Override
+ * the IOCB for a BA_RJT.
*/
- if (xri > (phba->sli4_hba.max_cfg_param.max_xri +
- phba->sli4_hba.max_cfg_param.xri_base) ||
- xri > (lpfc_sli4_get_els_iocb_cnt(phba) +
- phba->sli4_hba.max_cfg_param.xri_base)) {
+ if (aborted == false) {
icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
@@ -14214,17 +14507,19 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid);
/* Xmit CT abts response on exchange <xid> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n",
- icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n",
+ icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state);
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
if (rc == IOCB_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "2925 Failed to issue CT ABTS RSP x%x on "
- "xri x%x, Data x%x\n",
- icmd->un.xseq64.w5.hcsw.Rctl, oxid,
- phba->link_state);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "2925 Failed to issue CT ABTS RSP x%x on "
+ "xri x%x, Data x%x\n",
+ icmd->un.xseq64.w5.hcsw.Rctl, oxid,
+ phba->link_state);
+ lpfc_nlp_put(ndlp);
+ ctiocb->context1 = NULL;
lpfc_sli_release_iocbq(phba, ctiocb);
}
}
@@ -14249,32 +14544,25 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport,
struct lpfc_hba *phba = vport->phba;
struct fc_frame_header fc_hdr;
uint32_t fctl;
- bool abts_par;
+ bool aborted;
/* Make a copy of fc_hdr before the dmabuf being released */
memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
fctl = sli4_fctl_from_fc_hdr(&fc_hdr);
if (fctl & FC_FC_EX_CTX) {
- /*
- * ABTS sent by responder to exchange, just free the buffer
- */
- lpfc_in_buf_free(phba, &dmabuf->dbuf);
+ /* ABTS by responder to exchange, no cleanup needed */
+ aborted = true;
} else {
- /*
- * ABTS sent by initiator to exchange, need to do cleanup
- */
- /* Try to abort partially assembled seq */
- abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf);
-
- /* Send abort to ULP if partially seq abort failed */
- if (abts_par == false)
- lpfc_sli4_send_seq_to_ulp(vport, dmabuf);
- else
- lpfc_in_buf_free(phba, &dmabuf->dbuf);
+ /* ABTS by initiator to exchange, need to do cleanup */
+ aborted = lpfc_sli4_abort_partial_seq(vport, dmabuf);
+ if (aborted == false)
+ aborted = lpfc_sli4_abort_ulp_seq(vport, dmabuf);
}
- /* Send basic accept (BA_ACC) to the abort requester */
- lpfc_sli4_seq_abort_rsp(phba, &fc_hdr);
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
+
+ /* Respond with BA_ACC or BA_RJT accordingly */
+ lpfc_sli4_seq_abort_rsp(vport, &fc_hdr, aborted);
}
/**
@@ -15232,11 +15520,18 @@ lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba)
LPFC_SLI4_FCF_TBL_INDX_MAX);
lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
"3060 Last IDX %d\n", last_index);
- if (list_empty(&phba->fcf.fcf_pri_list)) {
+
+ /* Verify the priority list has 2 or more entries */
+ spin_lock_irq(&phba->hbalock);
+ if (list_empty(&phba->fcf.fcf_pri_list) ||
+ list_is_singular(&phba->fcf.fcf_pri_list)) {
+ spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
"3061 Last IDX %d\n", last_index);
return 0; /* Empty rr list */
}
+ spin_unlock_irq(&phba->hbalock);
+
next_fcf_pri = 0;
/*
* Clear the rr_bmask and set all of the bits that are at this
@@ -15307,10 +15602,13 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
{
uint16_t next_fcf_index;
+initial_priority:
/* Search start from next bit of currently registered FCF index */
+ next_fcf_index = phba->fcf.current_rec.fcf_indx;
+
next_priority:
- next_fcf_index = (phba->fcf.current_rec.fcf_indx + 1) %
- LPFC_SLI4_FCF_TBL_INDX_MAX;
+ /* Determine the next fcf index to check */
+ next_fcf_index = (next_fcf_index + 1) % LPFC_SLI4_FCF_TBL_INDX_MAX;
next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
LPFC_SLI4_FCF_TBL_INDX_MAX,
next_fcf_index);
@@ -15337,7 +15635,7 @@ next_priority:
* at that level and continue the selection process.
*/
if (lpfc_check_next_fcf_pri_level(phba))
- goto next_priority;
+ goto initial_priority;
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
"2844 No roundrobin failover FCF available\n");
if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
@@ -15992,30 +16290,36 @@ lpfc_drain_txq(struct lpfc_hba *phba)
char *fail_msg = NULL;
struct lpfc_sglq *sglq;
union lpfc_wqe wqe;
+ int txq_cnt = 0;
- spin_lock_irqsave(&phba->hbalock, iflags);
- if (pring->txq_cnt > pring->txq_max)
- pring->txq_max = pring->txq_cnt;
+ spin_lock_irqsave(&pring->ring_lock, iflags);
+ list_for_each_entry(piocbq, &pring->txq, list) {
+ txq_cnt++;
+ }
- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (txq_cnt > pring->txq_max)
+ pring->txq_max = txq_cnt;
- while (pring->txq_cnt) {
- spin_lock_irqsave(&phba->hbalock, iflags);
+ spin_unlock_irqrestore(&pring->ring_lock, iflags);
+
+ while (!list_empty(&pring->txq)) {
+ spin_lock_irqsave(&pring->ring_lock, iflags);
piocbq = lpfc_sli_ringtx_get(phba, pring);
if (!piocbq) {
- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ spin_unlock_irqrestore(&pring->ring_lock, iflags);
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2823 txq empty and txq_cnt is %d\n ",
- pring->txq_cnt);
+ txq_cnt);
break;
}
sglq = __lpfc_sli_get_sglq(phba, piocbq);
if (!sglq) {
__lpfc_sli_ringtx_put(phba, pring, piocbq);
- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ spin_unlock_irqrestore(&pring->ring_lock, iflags);
break;
}
+ txq_cnt--;
/* The xri and iocb resources secured,
* attempt to issue request
@@ -16040,12 +16344,12 @@ lpfc_drain_txq(struct lpfc_hba *phba)
piocbq->iotag, piocbq->sli4_xritag);
list_add_tail(&piocbq->list, &completions);
}
- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ spin_unlock_irqrestore(&pring->ring_lock, iflags);
}
/* Cancel all the IOCBs that cannot be issued */
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
IOERR_SLI_ABORTED);
- return pring->txq_cnt;
+ return txq_cnt;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 44c427a..d710b87 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2009-2011 Emulex. All rights reserved. *
+ * Copyright (C) 2009-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -139,6 +139,10 @@ struct lpfc_queue {
struct lpfc_sli_ring *pring; /* ptr to io ring associated with q */
+ uint16_t db_format;
+#define LPFC_DB_RING_FORMAT 0x01
+#define LPFC_DB_LIST_FORMAT 0x02
+ void __iomem *db_regaddr;
/* For q stats */
uint32_t q_cnt_1;
uint32_t q_cnt_2;
@@ -342,11 +346,6 @@ struct lpfc_bmbx {
#define SLI4_CT_VFI 2
#define SLI4_CT_FCFI 3
-#define LPFC_SLI4_FL1_MAX_SEGMENT_SIZE 0x10000
-#define LPFC_SLI4_FL1_MAX_BUF_SIZE 0X2000
-#define LPFC_SLI4_MIN_BUF_SIZE 0x400
-#define LPFC_SLI4_MAX_BUF_SIZE 0x20000
-
/*
* SLI4 specific data structures
*/
@@ -436,6 +435,16 @@ struct lpfc_sli4_lnk_info {
#define LPFC_SLI4_HANDLER_NAME_SZ 16
+/* Used for IRQ vector to CPU mapping */
+struct lpfc_vector_map_info {
+ uint16_t phys_id;
+ uint16_t core_id;
+ uint16_t irq;
+ uint16_t channel_id;
+ struct cpumask maskbits;
+};
+#define LPFC_VECTOR_MAP_EMPTY 0xffff
+
/* SLI4 HBA data structure entries */
struct lpfc_sli4_hba {
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
@@ -508,6 +517,10 @@ struct lpfc_sli4_hba {
struct lpfc_queue *hdr_rq; /* Slow-path Header Receive queue */
struct lpfc_queue *dat_rq; /* Slow-path Data Receive queue */
+ uint8_t fw_func_mode; /* FW function protocol mode */
+ uint32_t ulp0_mode; /* ULP0 protocol mode */
+ uint32_t ulp1_mode; /* ULP1 protocol mode */
+
/* Setup information for various queue parameters */
int eq_esize;
int eq_ecount;
@@ -565,6 +578,11 @@ struct lpfc_sli4_hba {
struct lpfc_iov iov;
spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
+
+ /* CPU to vector mapping information */
+ struct lpfc_vector_map_info *cpu_map;
+ uint16_t num_online_cpu;
+ uint16_t num_present_cpu;
};
enum lpfc_sge_type {
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index ba596e8..c6c32ee 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2012 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.36"
+#define LPFC_DRIVER_VERSION "8.3.40"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
@@ -30,4 +30,4 @@
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION
-#define LPFC_COPYRIGHT "Copyright(c) 2004-2009 Emulex. All rights reserved."
+#define LPFC_COPYRIGHT "Copyright(c) 2004-2013 Emulex. All rights reserved."
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 0fe188e6..e28e431 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -80,7 +80,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport,
}
}
-static int
+int
lpfc_alloc_vpi(struct lpfc_hba *phba)
{
unsigned long vpi;
@@ -568,6 +568,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
struct lpfc_hba *phba = vport->phba;
long timeout;
+ bool ns_ndlp_referenced = false;
if (vport->port_type == LPFC_PHYSICAL_PORT) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
@@ -628,6 +629,18 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
lpfc_debugfs_terminate(vport);
+ /*
+ * The call to fc_remove_host might release the NameServer ndlp. Since
+ * we might need to use the ndlp to send the DA_ID CT command,
+ * increment the reference for the NameServer ndlp to prevent it from
+ * being released.
+ */
+ ndlp = lpfc_findnode_did(vport, NameServer_DID);
+ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ lpfc_nlp_get(ndlp);
+ ns_ndlp_referenced = true;
+ }
+
/* Remove FC host and then SCSI host with the vport */
fc_remove_host(lpfc_shost_from_vport(vport));
scsi_remove_host(lpfc_shost_from_vport(vport));
@@ -734,6 +747,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
lpfc_discovery_wait(vport);
skip_logo:
+
+ /*
+ * If the NameServer ndlp has been incremented to allow the DA_ID CT
+ * command to be sent, decrement the ndlp now.
+ */
+ if (ns_ndlp_referenced) {
+ ndlp = lpfc_findnode_did(vport, NameServer_DID);
+ lpfc_nlp_put(ndlp);
+ }
+
lpfc_cleanup(vport);
lpfc_sli_host_down(vport);
diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h
index 9082834..6b2c94e 100644
--- a/drivers/scsi/lpfc/lpfc_vport.h
+++ b/drivers/scsi/lpfc/lpfc_vport.h
@@ -90,6 +90,7 @@ int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *);
void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **);
+int lpfc_alloc_vpi(struct lpfc_hba *phba);
/*
* queuecommand VPORT-specific return codes. Specified in the host byte code.
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 70eb1f7..994fc5c 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -481,7 +481,7 @@ static struct esp_driver_ops mac_esp_ops = {
.dma_error = mac_esp_dma_error,
};
-static int __devinit esp_mac_probe(struct platform_device *dev)
+static int esp_mac_probe(struct platform_device *dev)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
struct Scsi_Host *host;
@@ -591,7 +591,7 @@ fail:
return err;
}
-static int __devexit esp_mac_remove(struct platform_device *dev)
+static int esp_mac_remove(struct platform_device *dev)
{
struct mac_esp_priv *mep = platform_get_drvdata(dev);
struct esp *esp = mep->esp;
@@ -614,7 +614,7 @@ static int __devexit esp_mac_remove(struct platform_device *dev)
static struct platform_driver esp_mac_driver = {
.probe = esp_mac_probe,
- .remove = __devexit_p(esp_mac_remove),
+ .remove = esp_mac_remove,
.driver = {
.name = DRV_MODULE_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 24828b5..8580757 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -561,7 +561,8 @@ static int macscsi_pwrite (struct Scsi_Host *instance,
static struct scsi_host_template driver_template = {
.proc_name = "Mac5380",
- .proc_info = macscsi_proc_info,
+ .show_info = macscsi_show_info,
+ .write_info = macscsi_write_info,
.name = "Macintosh NCR5380 SCSI",
.detect = macscsi_detect,
.release = macscsi_release,
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
index d26e331..7dc62fc 100644
--- a/drivers/scsi/mac_scsi.h
+++ b/drivers/scsi/mac_scsi.h
@@ -72,7 +72,8 @@
#define NCR5380_queue_command macscsi_queue_command
#define NCR5380_abort macscsi_abort
#define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_proc_info macscsi_proc_info
+#define NCR5380_show_info macscsi_show_info
+#define NCR5380_write_info macscsi_write_info
#define BOARD_NORMAL 0
#define BOARD_NCR53C400 1
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 76ad72d..90c95a3 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -39,6 +39,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/reboot.h>
#include <linux/module.h>
#include <linux/list.h>
@@ -2025,7 +2026,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
static inline int
make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
{
- *pdev = alloc_pci_dev();
+ *pdev = pci_alloc_dev(NULL);
if( *pdev == NULL ) return -1;
@@ -2069,385 +2070,201 @@ mega_free_inquiry(void *inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
#ifdef CONFIG_PROC_FS
/* Following code handles /proc fs */
-#define CREATE_READ_PROC(string, func) create_proc_read_entry(string, \
- S_IRUSR | S_IFREG, \
- controller_proc_dir_entry, \
- func, adapter)
-
/**
- * mega_create_proc_entry()
- * @index - index in soft state array
- * @parent - parent node for this /proc entry
- *
- * Creates /proc entries for our controllers.
- */
-static void
-mega_create_proc_entry(int index, struct proc_dir_entry *parent)
-{
- struct proc_dir_entry *controller_proc_dir_entry = NULL;
- u8 string[64] = { 0 };
- adapter_t *adapter = hba_soft_state[index];
-
- sprintf(string, "hba%d", adapter->host->host_no);
-
- controller_proc_dir_entry =
- adapter->controller_proc_dir_entry = proc_mkdir(string, parent);
-
- if(!controller_proc_dir_entry) {
- printk(KERN_WARNING "\nmegaraid: proc_mkdir failed\n");
- return;
- }
- adapter->proc_read = CREATE_READ_PROC("config", proc_read_config);
- adapter->proc_stat = CREATE_READ_PROC("stat", proc_read_stat);
- adapter->proc_mbox = CREATE_READ_PROC("mailbox", proc_read_mbox);
-#if MEGA_HAVE_ENH_PROC
- adapter->proc_rr = CREATE_READ_PROC("rebuild-rate", proc_rebuild_rate);
- adapter->proc_battery = CREATE_READ_PROC("battery-status",
- proc_battery);
-
- /*
- * Display each physical drive on its channel
- */
- adapter->proc_pdrvstat[0] = CREATE_READ_PROC("diskdrives-ch0",
- proc_pdrv_ch0);
- adapter->proc_pdrvstat[1] = CREATE_READ_PROC("diskdrives-ch1",
- proc_pdrv_ch1);
- adapter->proc_pdrvstat[2] = CREATE_READ_PROC("diskdrives-ch2",
- proc_pdrv_ch2);
- adapter->proc_pdrvstat[3] = CREATE_READ_PROC("diskdrives-ch3",
- proc_pdrv_ch3);
-
- /*
- * Display a set of up to 10 logical drive through each of following
- * /proc entries
- */
- adapter->proc_rdrvstat[0] = CREATE_READ_PROC("raiddrives-0-9",
- proc_rdrv_10);
- adapter->proc_rdrvstat[1] = CREATE_READ_PROC("raiddrives-10-19",
- proc_rdrv_20);
- adapter->proc_rdrvstat[2] = CREATE_READ_PROC("raiddrives-20-29",
- proc_rdrv_30);
- adapter->proc_rdrvstat[3] = CREATE_READ_PROC("raiddrives-30-39",
- proc_rdrv_40);
-#endif
-}
-
-
-/**
- * proc_read_config()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_config()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
* Display configuration information about the controller.
*/
static int
-proc_read_config(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_config(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
- int len = 0;
-
- len += sprintf(page+len, "%s", MEGARAID_VERSION);
+ adapter_t *adapter = m->private;
+ seq_puts(m, MEGARAID_VERSION);
if(adapter->product_info.product_name[0])
- len += sprintf(page+len, "%s\n",
- adapter->product_info.product_name);
+ seq_printf(m, "%s\n", adapter->product_info.product_name);
- len += sprintf(page+len, "Controller Type: ");
-
- if( adapter->flag & BOARD_MEMMAP ) {
- len += sprintf(page+len,
- "438/466/467/471/493/518/520/531/532\n");
- }
- else {
- len += sprintf(page+len,
- "418/428/434\n");
- }
+ seq_puts(m, "Controller Type: ");
- if(adapter->flag & BOARD_40LD) {
- len += sprintf(page+len,
- "Controller Supports 40 Logical Drives\n");
- }
+ if( adapter->flag & BOARD_MEMMAP )
+ seq_puts(m, "438/466/467/471/493/518/520/531/532\n");
+ else
+ seq_puts(m, "418/428/434\n");
- if(adapter->flag & BOARD_64BIT) {
- len += sprintf(page+len,
- "Controller capable of 64-bit memory addressing\n");
- }
- if( adapter->has_64bit_addr ) {
- len += sprintf(page+len,
- "Controller using 64-bit memory addressing\n");
- }
- else {
- len += sprintf(page+len,
- "Controller is not using 64-bit memory addressing\n");
- }
+ if(adapter->flag & BOARD_40LD)
+ seq_puts(m, "Controller Supports 40 Logical Drives\n");
- len += sprintf(page+len, "Base = %08lx, Irq = %d, ", adapter->base,
- adapter->host->irq);
-
- len += sprintf(page+len, "Logical Drives = %d, Channels = %d\n",
- adapter->numldrv, adapter->product_info.nchannels);
-
- len += sprintf(page+len, "Version =%s:%s, DRAM = %dMb\n",
- adapter->fw_version, adapter->bios_version,
- adapter->product_info.dram_size);
-
- len += sprintf(page+len,
- "Controller Queue Depth = %d, Driver Queue Depth = %d\n",
- adapter->product_info.max_commands, adapter->max_cmds);
-
- len += sprintf(page+len, "support_ext_cdb = %d\n",
- adapter->support_ext_cdb);
- len += sprintf(page+len, "support_random_del = %d\n",
- adapter->support_random_del);
- len += sprintf(page+len, "boot_ldrv_enabled = %d\n",
- adapter->boot_ldrv_enabled);
- len += sprintf(page+len, "boot_ldrv = %d\n",
- adapter->boot_ldrv);
- len += sprintf(page+len, "boot_pdrv_enabled = %d\n",
- adapter->boot_pdrv_enabled);
- len += sprintf(page+len, "boot_pdrv_ch = %d\n",
- adapter->boot_pdrv_ch);
- len += sprintf(page+len, "boot_pdrv_tgt = %d\n",
- adapter->boot_pdrv_tgt);
- len += sprintf(page+len, "quiescent = %d\n",
- atomic_read(&adapter->quiescent));
- len += sprintf(page+len, "has_cluster = %d\n",
- adapter->has_cluster);
-
- len += sprintf(page+len, "\nModule Parameters:\n");
- len += sprintf(page+len, "max_cmd_per_lun = %d\n",
- max_cmd_per_lun);
- len += sprintf(page+len, "max_sectors_per_io = %d\n",
- max_sectors_per_io);
-
- *eof = 1;
-
- return len;
+ if(adapter->flag & BOARD_64BIT)
+ seq_puts(m, "Controller capable of 64-bit memory addressing\n");
+ if( adapter->has_64bit_addr )
+ seq_puts(m, "Controller using 64-bit memory addressing\n");
+ else
+ seq_puts(m, "Controller is not using 64-bit memory addressing\n");
+
+ seq_printf(m, "Base = %08lx, Irq = %d, ",
+ adapter->base, adapter->host->irq);
+
+ seq_printf(m, "Logical Drives = %d, Channels = %d\n",
+ adapter->numldrv, adapter->product_info.nchannels);
+
+ seq_printf(m, "Version =%s:%s, DRAM = %dMb\n",
+ adapter->fw_version, adapter->bios_version,
+ adapter->product_info.dram_size);
+
+ seq_printf(m, "Controller Queue Depth = %d, Driver Queue Depth = %d\n",
+ adapter->product_info.max_commands, adapter->max_cmds);
+
+ seq_printf(m, "support_ext_cdb = %d\n", adapter->support_ext_cdb);
+ seq_printf(m, "support_random_del = %d\n", adapter->support_random_del);
+ seq_printf(m, "boot_ldrv_enabled = %d\n", adapter->boot_ldrv_enabled);
+ seq_printf(m, "boot_ldrv = %d\n", adapter->boot_ldrv);
+ seq_printf(m, "boot_pdrv_enabled = %d\n", adapter->boot_pdrv_enabled);
+ seq_printf(m, "boot_pdrv_ch = %d\n", adapter->boot_pdrv_ch);
+ seq_printf(m, "boot_pdrv_tgt = %d\n", adapter->boot_pdrv_tgt);
+ seq_printf(m, "quiescent = %d\n",
+ atomic_read(&adapter->quiescent));
+ seq_printf(m, "has_cluster = %d\n", adapter->has_cluster);
+
+ seq_puts(m, "\nModule Parameters:\n");
+ seq_printf(m, "max_cmd_per_lun = %d\n", max_cmd_per_lun);
+ seq_printf(m, "max_sectors_per_io = %d\n", max_sectors_per_io);
+ return 0;
}
-
-
/**
- * proc_read_stat()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_stat()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
- * Diaplay statistical information about the I/O activity.
+ * Display statistical information about the I/O activity.
*/
static int
-proc_read_stat(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_stat(struct seq_file *m, void *v)
{
- adapter_t *adapter;
- int len;
+ adapter_t *adapter = m->private;
+#if MEGA_HAVE_STATS
int i;
+#endif
- i = 0; /* avoid compilation warnings */
- len = 0;
- adapter = (adapter_t *)data;
-
- len = sprintf(page, "Statistical Information for this controller\n");
- len += sprintf(page+len, "pend_cmds = %d\n",
- atomic_read(&adapter->pend_cmds));
+ seq_puts(m, "Statistical Information for this controller\n");
+ seq_printf(m, "pend_cmds = %d\n", atomic_read(&adapter->pend_cmds));
#if MEGA_HAVE_STATS
for(i = 0; i < adapter->numldrv; i++) {
- len += sprintf(page+len, "Logical Drive %d:\n", i);
-
- len += sprintf(page+len,
- "\tReads Issued = %lu, Writes Issued = %lu\n",
- adapter->nreads[i], adapter->nwrites[i]);
-
- len += sprintf(page+len,
- "\tSectors Read = %lu, Sectors Written = %lu\n",
- adapter->nreadblocks[i], adapter->nwriteblocks[i]);
-
- len += sprintf(page+len,
- "\tRead errors = %lu, Write errors = %lu\n\n",
- adapter->rd_errors[i], adapter->wr_errors[i]);
+ seq_printf(m, "Logical Drive %d:\n", i);
+ seq_printf(m, "\tReads Issued = %lu, Writes Issued = %lu\n",
+ adapter->nreads[i], adapter->nwrites[i]);
+ seq_printf(m, "\tSectors Read = %lu, Sectors Written = %lu\n",
+ adapter->nreadblocks[i], adapter->nwriteblocks[i]);
+ seq_printf(m, "\tRead errors = %lu, Write errors = %lu\n\n",
+ adapter->rd_errors[i], adapter->wr_errors[i]);
}
#else
- len += sprintf(page+len,
- "IO and error counters not compiled in driver.\n");
+ seq_puts(m, "IO and error counters not compiled in driver.\n");
#endif
-
- *eof = 1;
-
- return len;
+ return 0;
}
/**
- * proc_read_mbox()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_mbox()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
* Display mailbox information for the last command issued. This information
* is good for debugging.
*/
static int
-proc_read_mbox(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_mbox(struct seq_file *m, void *v)
{
-
- adapter_t *adapter = (adapter_t *)data;
+ adapter_t *adapter = m->private;
volatile mbox_t *mbox = adapter->mbox;
- int len = 0;
-
- len = sprintf(page, "Contents of Mail Box Structure\n");
- len += sprintf(page+len, " Fw Command = 0x%02x\n",
- mbox->m_out.cmd);
- len += sprintf(page+len, " Cmd Sequence = 0x%02x\n",
- mbox->m_out.cmdid);
- len += sprintf(page+len, " No of Sectors= %04d\n",
- mbox->m_out.numsectors);
- len += sprintf(page+len, " LBA = 0x%02x\n",
- mbox->m_out.lba);
- len += sprintf(page+len, " DTA = 0x%08x\n",
- mbox->m_out.xferaddr);
- len += sprintf(page+len, " Logical Drive= 0x%02x\n",
- mbox->m_out.logdrv);
- len += sprintf(page+len, " No of SG Elmt= 0x%02x\n",
- mbox->m_out.numsgelements);
- len += sprintf(page+len, " Busy = %01x\n",
- mbox->m_in.busy);
- len += sprintf(page+len, " Status = 0x%02x\n",
- mbox->m_in.status);
-
- *eof = 1;
-
- return len;
+
+ seq_puts(m, "Contents of Mail Box Structure\n");
+ seq_printf(m, " Fw Command = 0x%02x\n", mbox->m_out.cmd);
+ seq_printf(m, " Cmd Sequence = 0x%02x\n", mbox->m_out.cmdid);
+ seq_printf(m, " No of Sectors= %04d\n", mbox->m_out.numsectors);
+ seq_printf(m, " LBA = 0x%02x\n", mbox->m_out.lba);
+ seq_printf(m, " DTA = 0x%08x\n", mbox->m_out.xferaddr);
+ seq_printf(m, " Logical Drive= 0x%02x\n", mbox->m_out.logdrv);
+ seq_printf(m, " No of SG Elmt= 0x%02x\n", mbox->m_out.numsgelements);
+ seq_printf(m, " Busy = %01x\n", mbox->m_in.busy);
+ seq_printf(m, " Status = 0x%02x\n", mbox->m_in.status);
+ return 0;
}
/**
- * proc_rebuild_rate()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_rebuild_rate()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
* Display current rebuild rate
*/
static int
-proc_rebuild_rate(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_rebuild_rate(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
+ adapter_t *adapter = m->private;
dma_addr_t dma_handle;
caddr_t inquiry;
struct pci_dev *pdev;
- int len = 0;
- if( make_local_pdev(adapter, &pdev) != 0 ) {
- *eof = 1;
- return len;
- }
+ if( make_local_pdev(adapter, &pdev) != 0 )
+ return 0;
- if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
- free_local_pdev(pdev);
- *eof = 1;
- return len;
- }
+ if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
+ goto free_pdev;
if( mega_adapinq(adapter, dma_handle) != 0 ) {
-
- len = sprintf(page, "Adapter inquiry failed.\n");
-
+ seq_puts(m, "Adapter inquiry failed.\n");
printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
- free_local_pdev(pdev);
-
- *eof = 1;
-
- return len;
+ goto free_inquiry;
}
- if( adapter->flag & BOARD_40LD ) {
- len = sprintf(page, "Rebuild Rate: [%d%%]\n",
- ((mega_inquiry3 *)inquiry)->rebuild_rate);
- }
- else {
- len = sprintf(page, "Rebuild Rate: [%d%%]\n",
+ if( adapter->flag & BOARD_40LD )
+ seq_printf(m, "Rebuild Rate: [%d%%]\n",
+ ((mega_inquiry3 *)inquiry)->rebuild_rate);
+ else
+ seq_printf(m, "Rebuild Rate: [%d%%]\n",
((mraid_ext_inquiry *)
- inquiry)->raid_inq.adapter_info.rebuild_rate);
- }
-
+ inquiry)->raid_inq.adapter_info.rebuild_rate);
+free_inquiry:
mega_free_inquiry(inquiry, dma_handle, pdev);
-
+free_pdev:
free_local_pdev(pdev);
-
- *eof = 1;
-
- return len;
+ return 0;
}
/**
- * proc_battery()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_battery()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
* Display information about the battery module on the controller.
*/
static int
-proc_battery(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_battery(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
+ adapter_t *adapter = m->private;
dma_addr_t dma_handle;
caddr_t inquiry;
struct pci_dev *pdev;
- u8 battery_status = 0;
- char str[256];
- int len = 0;
+ u8 battery_status;
- if( make_local_pdev(adapter, &pdev) != 0 ) {
- *eof = 1;
- return len;
- }
+ if( make_local_pdev(adapter, &pdev) != 0 )
+ return 0;
- if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
- free_local_pdev(pdev);
- *eof = 1;
- return len;
- }
+ if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
+ goto free_pdev;
if( mega_adapinq(adapter, dma_handle) != 0 ) {
-
- len = sprintf(page, "Adapter inquiry failed.\n");
-
+ seq_printf(m, "Adapter inquiry failed.\n");
printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
- free_local_pdev(pdev);
-
- *eof = 1;
-
- return len;
+ goto free_inquiry;
}
if( adapter->flag & BOARD_40LD ) {
@@ -2461,146 +2278,80 @@ proc_battery(char *page, char **start, off_t offset, int count, int *eof,
/*
* Decode the battery status
*/
- sprintf(str, "Battery Status:[%d]", battery_status);
+ seq_printf(m, "Battery Status:[%d]", battery_status);
if(battery_status == MEGA_BATT_CHARGE_DONE)
- strcat(str, " Charge Done");
+ seq_puts(m, " Charge Done");
if(battery_status & MEGA_BATT_MODULE_MISSING)
- strcat(str, " Module Missing");
+ seq_puts(m, " Module Missing");
if(battery_status & MEGA_BATT_LOW_VOLTAGE)
- strcat(str, " Low Voltage");
+ seq_puts(m, " Low Voltage");
if(battery_status & MEGA_BATT_TEMP_HIGH)
- strcat(str, " Temperature High");
+ seq_puts(m, " Temperature High");
if(battery_status & MEGA_BATT_PACK_MISSING)
- strcat(str, " Pack Missing");
+ seq_puts(m, " Pack Missing");
if(battery_status & MEGA_BATT_CHARGE_INPROG)
- strcat(str, " Charge In-progress");
+ seq_puts(m, " Charge In-progress");
if(battery_status & MEGA_BATT_CHARGE_FAIL)
- strcat(str, " Charge Fail");
+ seq_puts(m, " Charge Fail");
if(battery_status & MEGA_BATT_CYCLES_EXCEEDED)
- strcat(str, " Cycles Exceeded");
-
- len = sprintf(page, "%s\n", str);
+ seq_puts(m, " Cycles Exceeded");
+ seq_putc(m, '\n');
+free_inquiry:
mega_free_inquiry(inquiry, dma_handle, pdev);
-
+free_pdev:
free_local_pdev(pdev);
-
- *eof = 1;
-
- return len;
-}
-
-
-/**
- * proc_pdrv_ch0()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 0.
- */
-static int
-proc_pdrv_ch0(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
-{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_pdrv(adapter, page, 0));
-}
-
-
-/**
- * proc_pdrv_ch1()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 1.
- */
-static int
-proc_pdrv_ch1(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
-{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_pdrv(adapter, page, 1));
+ return 0;
}
-/**
- * proc_pdrv_ch2()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 2.
+/*
+ * Display scsi inquiry
*/
-static int
-proc_pdrv_ch2(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+static void
+mega_print_inquiry(struct seq_file *m, char *scsi_inq)
{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_pdrv(adapter, page, 2));
-}
+ int i;
+ seq_puts(m, " Vendor: ");
+ seq_write(m, scsi_inq + 8, 8);
+ seq_puts(m, " Model: ");
+ seq_write(m, scsi_inq + 16, 16);
+ seq_puts(m, " Rev: ");
+ seq_write(m, scsi_inq + 32, 4);
+ seq_putc(m, '\n');
-/**
- * proc_pdrv_ch3()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
- *
- * Display information about the physical drives on physical channel 3.
- */
-static int
-proc_pdrv_ch3(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
-{
- adapter_t *adapter = (adapter_t *)data;
+ i = scsi_inq[0] & 0x1f;
+ seq_printf(m, " Type: %s ", scsi_device_type(i));
- *eof = 1;
+ seq_printf(m, " ANSI SCSI revision: %02x",
+ scsi_inq[2] & 0x07);
- return (proc_pdrv(adapter, page, 3));
+ if( (scsi_inq[2] & 0x07) == 1 && (scsi_inq[3] & 0x0f) == 1 )
+ seq_puts(m, " CCS\n");
+ else
+ seq_putc(m, '\n');
}
-
/**
- * proc_pdrv()
+ * proc_show_pdrv()
+ * @m - Synthetic file construction data
* @page - buffer to write the data in
* @adapter - pointer to our soft state
*
* Display information about the physical drives.
*/
static int
-proc_pdrv(adapter_t *adapter, char *page, int channel)
+proc_show_pdrv(struct seq_file *m, adapter_t *adapter, int channel)
{
dma_addr_t dma_handle;
char *scsi_inq;
@@ -2611,32 +2362,24 @@ proc_pdrv(adapter_t *adapter, char *page, int channel)
u8 state;
int tgt;
int max_channels;
- int len = 0;
- char str[80];
int i;
- if( make_local_pdev(adapter, &pdev) != 0 ) {
- return len;
- }
+ if( make_local_pdev(adapter, &pdev) != 0 )
+ return 0;
- if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
+ if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
goto free_pdev;
- }
if( mega_adapinq(adapter, dma_handle) != 0 ) {
- len = sprintf(page, "Adapter inquiry failed.\n");
-
+ seq_puts(m, "Adapter inquiry failed.\n");
printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
goto free_inquiry;
}
scsi_inq = pci_alloc_consistent(pdev, 256, &scsi_inq_dma_handle);
-
if( scsi_inq == NULL ) {
- len = sprintf(page, "memory not available for scsi inq.\n");
-
+ seq_puts(m, "memory not available for scsi inq.\n");
goto free_inquiry;
}
@@ -2659,39 +2402,31 @@ proc_pdrv(adapter_t *adapter, char *page, int channel)
i = channel*16 + tgt;
state = *(pdrv_state + i);
-
switch( state & 0x0F ) {
-
case PDRV_ONLINE:
- sprintf(str,
- "Channel:%2d Id:%2d State: Online",
- channel, tgt);
+ seq_printf(m, "Channel:%2d Id:%2d State: Online",
+ channel, tgt);
break;
case PDRV_FAILED:
- sprintf(str,
- "Channel:%2d Id:%2d State: Failed",
- channel, tgt);
+ seq_printf(m, "Channel:%2d Id:%2d State: Failed",
+ channel, tgt);
break;
case PDRV_RBLD:
- sprintf(str,
- "Channel:%2d Id:%2d State: Rebuild",
- channel, tgt);
+ seq_printf(m, "Channel:%2d Id:%2d State: Rebuild",
+ channel, tgt);
break;
case PDRV_HOTSPARE:
- sprintf(str,
- "Channel:%2d Id:%2d State: Hot spare",
- channel, tgt);
+ seq_printf(m, "Channel:%2d Id:%2d State: Hot spare",
+ channel, tgt);
break;
default:
- sprintf(str,
- "Channel:%2d Id:%2d State: Un-configured",
- channel, tgt);
+ seq_printf(m, "Channel:%2d Id:%2d State: Un-configured",
+ channel, tgt);
break;
-
}
/*
@@ -2710,11 +2445,8 @@ proc_pdrv(adapter_t *adapter, char *page, int channel)
* Check for overflow. We print less than 240
* characters for inquiry
*/
- if( (len + 240) >= PAGE_SIZE ) break;
-
- len += sprintf(page+len, "%s.\n", str);
-
- len += mega_print_inquiry(page+len, scsi_inq);
+ seq_puts(m, ".\n");
+ mega_print_inquiry(m, scsi_inq);
}
free_pci:
@@ -2723,150 +2455,68 @@ free_inquiry:
mega_free_inquiry(inquiry, dma_handle, pdev);
free_pdev:
free_local_pdev(pdev);
-
- return len;
-}
-
-
-/*
- * Display scsi inquiry
- */
-static int
-mega_print_inquiry(char *page, char *scsi_inq)
-{
- int len = 0;
- int i;
-
- len = sprintf(page, " Vendor: ");
- for( i = 8; i < 16; i++ ) {
- len += sprintf(page+len, "%c", scsi_inq[i]);
- }
-
- len += sprintf(page+len, " Model: ");
-
- for( i = 16; i < 32; i++ ) {
- len += sprintf(page+len, "%c", scsi_inq[i]);
- }
-
- len += sprintf(page+len, " Rev: ");
-
- for( i = 32; i < 36; i++ ) {
- len += sprintf(page+len, "%c", scsi_inq[i]);
- }
-
- len += sprintf(page+len, "\n");
-
- i = scsi_inq[0] & 0x1f;
-
- len += sprintf(page+len, " Type: %s ", scsi_device_type(i));
-
- len += sprintf(page+len,
- " ANSI SCSI revision: %02x", scsi_inq[2] & 0x07);
-
- if( (scsi_inq[2] & 0x07) == 1 && (scsi_inq[3] & 0x0f) == 1 )
- len += sprintf(page+len, " CCS\n");
- else
- len += sprintf(page+len, "\n");
-
- return len;
+ return 0;
}
-
/**
- * proc_rdrv_10()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch0()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 0.
*/
static int
-proc_rdrv_10(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_pdrv_ch0(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_rdrv(adapter, page, 0, 9));
+ return proc_show_pdrv(m, m->private, 0);
}
/**
- * proc_rdrv_20()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch1()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 1.
*/
static int
-proc_rdrv_20(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_pdrv_ch1(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_rdrv(adapter, page, 10, 19));
+ return proc_show_pdrv(m, m->private, 1);
}
/**
- * proc_rdrv_30()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch2()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 2.
*/
static int
-proc_rdrv_30(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_pdrv_ch2(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_rdrv(adapter, page, 20, 29));
+ return proc_show_pdrv(m, m->private, 2);
}
/**
- * proc_rdrv_40()
- * @page - buffer to write the data in
- * @start - where the actual data has been written in page
- * @offset - same meaning as the read system call
- * @count - same meaning as the read system call
- * @eof - set if no more data needs to be returned
- * @data - pointer to our soft state
+ * proc_show_pdrv_ch3()
+ * @m - Synthetic file construction data
+ * @v - File iterator
*
- * Display real time information about the logical drives 0 through 9.
+ * Display information about the physical drives on physical channel 3.
*/
static int
-proc_rdrv_40(char *page, char **start, off_t offset, int count, int *eof,
- void *data)
+proc_show_pdrv_ch3(struct seq_file *m, void *v)
{
- adapter_t *adapter = (adapter_t *)data;
-
- *eof = 1;
-
- return (proc_rdrv(adapter, page, 30, 39));
+ return proc_show_pdrv(m, m->private, 3);
}
/**
- * proc_rdrv()
- * @page - buffer to write the data in
+ * proc_show_rdrv()
+ * @m - Synthetic file construction data
* @adapter - pointer to our soft state
* @start - starting logical drive to display
* @end - ending logical drive to display
@@ -2875,7 +2525,7 @@ proc_rdrv_40(char *page, char **start, off_t offset, int count, int *eof,
* /proc/scsi/scsi interface
*/
static int
-proc_rdrv(adapter_t *adapter, char *page, int start, int end )
+proc_show_rdrv(struct seq_file *m, adapter_t *adapter, int start, int end )
{
dma_addr_t dma_handle;
logdrv_param *lparam;
@@ -2887,29 +2537,18 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
u8 *rdrv_state;
int num_ldrv;
u32 array_sz;
- int len = 0;
int i;
- if( make_local_pdev(adapter, &pdev) != 0 ) {
- return len;
- }
+ if( make_local_pdev(adapter, &pdev) != 0 )
+ return 0;
- if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL ) {
- free_local_pdev(pdev);
- return len;
- }
+ if( (inquiry = mega_allocate_inquiry(&dma_handle, pdev)) == NULL )
+ goto free_pdev;
if( mega_adapinq(adapter, dma_handle) != 0 ) {
-
- len = sprintf(page, "Adapter inquiry failed.\n");
-
+ seq_puts(m, "Adapter inquiry failed.\n");
printk(KERN_WARNING "megaraid: inquiry failed.\n");
-
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
- free_local_pdev(pdev);
-
- return len;
+ goto free_inquiry;
}
memset(&mc, 0, sizeof(megacmd_t));
@@ -2935,13 +2574,8 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
&disk_array_dma_handle);
if( disk_array == NULL ) {
- len = sprintf(page, "memory not available.\n");
-
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
- free_local_pdev(pdev);
-
- return len;
+ seq_puts(m, "memory not available.\n");
+ goto free_inquiry;
}
mc.xferaddr = (u32)disk_array_dma_handle;
@@ -2951,17 +2585,8 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
mc.opcode = OP_DCMD_READ_CONFIG;
if( mega_internal_command(adapter, &mc, NULL) ) {
-
- len = sprintf(page, "40LD read config failed.\n");
-
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
- pci_free_consistent(pdev, array_sz, disk_array,
- disk_array_dma_handle);
-
- free_local_pdev(pdev);
-
- return len;
+ seq_puts(m, "40LD read config failed.\n");
+ goto free_pci;
}
}
@@ -2969,24 +2594,10 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
mc.cmd = NEW_READ_CONFIG_8LD;
if( mega_internal_command(adapter, &mc, NULL) ) {
-
mc.cmd = READ_CONFIG_8LD;
-
- if( mega_internal_command(adapter, &mc,
- NULL) ){
-
- len = sprintf(page,
- "8LD read config failed.\n");
-
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
- pci_free_consistent(pdev, array_sz,
- disk_array,
- disk_array_dma_handle);
-
- free_local_pdev(pdev);
-
- return len;
+ if( mega_internal_command(adapter, &mc, NULL) ) {
+ seq_puts(m, "8LD read config failed.\n");
+ goto free_pci;
}
}
}
@@ -3006,29 +2617,23 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
* Check for overflow. We print less than 240 characters for
* information about each logical drive.
*/
- if( (len + 240) >= PAGE_SIZE ) break;
-
- len += sprintf(page+len, "Logical drive:%2d:, ", i);
+ seq_printf(m, "Logical drive:%2d:, ", i);
switch( rdrv_state[i] & 0x0F ) {
case RDRV_OFFLINE:
- len += sprintf(page+len, "state: offline");
+ seq_puts(m, "state: offline");
break;
-
case RDRV_DEGRADED:
- len += sprintf(page+len, "state: degraded");
+ seq_puts(m, "state: degraded");
break;
-
case RDRV_OPTIMAL:
- len += sprintf(page+len, "state: optimal");
+ seq_puts(m, "state: optimal");
break;
-
case RDRV_DELETED:
- len += sprintf(page+len, "state: deleted");
+ seq_puts(m, "state: deleted");
break;
-
default:
- len += sprintf(page+len, "state: unknown");
+ seq_puts(m, "state: unknown");
break;
}
@@ -3036,84 +2641,203 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
* Check if check consistency or initialization is going on
* for this logical drive.
*/
- if( (rdrv_state[i] & 0xF0) == 0x20 ) {
- len += sprintf(page+len,
- ", check-consistency in progress");
- }
- else if( (rdrv_state[i] & 0xF0) == 0x10 ) {
- len += sprintf(page+len,
- ", initialization in progress");
- }
+ if( (rdrv_state[i] & 0xF0) == 0x20 )
+ seq_puts(m, ", check-consistency in progress");
+ else if( (rdrv_state[i] & 0xF0) == 0x10 )
+ seq_puts(m, ", initialization in progress");
- len += sprintf(page+len, "\n");
+ seq_putc(m, '\n');
- len += sprintf(page+len, "Span depth:%3d, ",
- lparam->span_depth);
-
- len += sprintf(page+len, "RAID level:%3d, ",
- lparam->level);
-
- len += sprintf(page+len, "Stripe size:%3d, ",
- lparam->stripe_sz ? lparam->stripe_sz/2: 128);
-
- len += sprintf(page+len, "Row size:%3d\n",
- lparam->row_size);
-
-
- len += sprintf(page+len, "Read Policy: ");
+ seq_printf(m, "Span depth:%3d, ", lparam->span_depth);
+ seq_printf(m, "RAID level:%3d, ", lparam->level);
+ seq_printf(m, "Stripe size:%3d, ",
+ lparam->stripe_sz ? lparam->stripe_sz/2: 128);
+ seq_printf(m, "Row size:%3d\n", lparam->row_size);
+ seq_puts(m, "Read Policy: ");
switch(lparam->read_ahead) {
-
case NO_READ_AHEAD:
- len += sprintf(page+len, "No read ahead, ");
+ seq_puts(m, "No read ahead, ");
break;
-
case READ_AHEAD:
- len += sprintf(page+len, "Read ahead, ");
+ seq_puts(m, "Read ahead, ");
break;
-
case ADAP_READ_AHEAD:
- len += sprintf(page+len, "Adaptive, ");
+ seq_puts(m, "Adaptive, ");
break;
}
- len += sprintf(page+len, "Write Policy: ");
-
+ seq_puts(m, "Write Policy: ");
switch(lparam->write_mode) {
-
case WRMODE_WRITE_THRU:
- len += sprintf(page+len, "Write thru, ");
+ seq_puts(m, "Write thru, ");
break;
-
case WRMODE_WRITE_BACK:
- len += sprintf(page+len, "Write back, ");
+ seq_puts(m, "Write back, ");
break;
}
- len += sprintf(page+len, "Cache Policy: ");
-
+ seq_puts(m, "Cache Policy: ");
switch(lparam->direct_io) {
-
case CACHED_IO:
- len += sprintf(page+len, "Cached IO\n\n");
+ seq_puts(m, "Cached IO\n\n");
break;
-
case DIRECT_IO:
- len += sprintf(page+len, "Direct IO\n\n");
+ seq_puts(m, "Direct IO\n\n");
break;
}
}
- mega_free_inquiry(inquiry, dma_handle, pdev);
-
+free_pci:
pci_free_consistent(pdev, array_sz, disk_array,
disk_array_dma_handle);
-
+free_inquiry:
+ mega_free_inquiry(inquiry, dma_handle, pdev);
+free_pdev:
free_local_pdev(pdev);
+ return 0;
+}
+
+/**
+ * proc_show_rdrv_10()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_10(struct seq_file *m, void *v)
+{
+ return proc_show_rdrv(m, m->private, 0, 9);
+}
+
+
+/**
+ * proc_show_rdrv_20()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_20(struct seq_file *m, void *v)
+{
+ return proc_show_rdrv(m, m->private, 10, 19);
+}
+
+
+/**
+ * proc_show_rdrv_30()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_30(struct seq_file *m, void *v)
+{
+ return proc_show_rdrv(m, m->private, 20, 29);
+}
+
+
+/**
+ * proc_show_rdrv_40()
+ * @m - Synthetic file construction data
+ * @v - File iterator
+ *
+ * Display real time information about the logical drives 0 through 9.
+ */
+static int
+proc_show_rdrv_40(struct seq_file *m, void *v)
+{
+ return proc_show_rdrv(m, m->private, 30, 39);
+}
+
+
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int mega_proc_open(struct inode *inode, struct file *file)
+{
+ adapter_t *adapter = proc_get_parent_data(inode);
+ int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
+
+ return single_open(file, show, adapter);
+}
+
+static const struct file_operations mega_proc_fops = {
+ .open = mega_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Table of proc files we need to create.
+ */
+struct mega_proc_file {
+ const char *name;
+ unsigned short ptr_offset;
+ int (*show) (struct seq_file *m, void *v);
+};
+
+static const struct mega_proc_file mega_proc_files[] = {
+ { "config", offsetof(adapter_t, proc_read), proc_show_config },
+ { "stat", offsetof(adapter_t, proc_stat), proc_show_stat },
+ { "mailbox", offsetof(adapter_t, proc_mbox), proc_show_mbox },
+#if MEGA_HAVE_ENH_PROC
+ { "rebuild-rate", offsetof(adapter_t, proc_rr), proc_show_rebuild_rate },
+ { "battery-status", offsetof(adapter_t, proc_battery), proc_show_battery },
+ { "diskdrives-ch0", offsetof(adapter_t, proc_pdrvstat[0]), proc_show_pdrv_ch0 },
+ { "diskdrives-ch1", offsetof(adapter_t, proc_pdrvstat[1]), proc_show_pdrv_ch1 },
+ { "diskdrives-ch2", offsetof(adapter_t, proc_pdrvstat[2]), proc_show_pdrv_ch2 },
+ { "diskdrives-ch3", offsetof(adapter_t, proc_pdrvstat[3]), proc_show_pdrv_ch3 },
+ { "raiddrives-0-9", offsetof(adapter_t, proc_rdrvstat[0]), proc_show_rdrv_10 },
+ { "raiddrives-10-19", offsetof(adapter_t, proc_rdrvstat[1]), proc_show_rdrv_20 },
+ { "raiddrives-20-29", offsetof(adapter_t, proc_rdrvstat[2]), proc_show_rdrv_30 },
+ { "raiddrives-30-39", offsetof(adapter_t, proc_rdrvstat[3]), proc_show_rdrv_40 },
+#endif
+ { NULL }
+};
+
+/**
+ * mega_create_proc_entry()
+ * @index - index in soft state array
+ * @parent - parent node for this /proc entry
+ *
+ * Creates /proc entries for our controllers.
+ */
+static void
+mega_create_proc_entry(int index, struct proc_dir_entry *parent)
+{
+ const struct mega_proc_file *f;
+ adapter_t *adapter = hba_soft_state[index];
+ struct proc_dir_entry *dir, *de, **ppde;
+ u8 string[16];
+
+ sprintf(string, "hba%d", adapter->host->host_no);
+
+ dir = adapter->controller_proc_dir_entry =
+ proc_mkdir_data(string, 0, parent, adapter);
+ if(!dir) {
+ printk(KERN_WARNING "\nmegaraid: proc_mkdir failed\n");
+ return;
+ }
- return len;
+ for (f = mega_proc_files; f->name; f++) {
+ de = proc_create_data(f->name, S_IRUSR, dir, &mega_proc_fops,
+ f->show);
+ if (!de) {
+ printk(KERN_WARNING "\nmegaraid: proc_create failed\n");
+ return;
+ }
+
+ ppde = (void *)adapter + f->ptr_offset;
+ *ppde = de;
+ }
}
+
#else
static inline void mega_create_proc_entry(int index, struct proc_dir_entry *parent)
{
@@ -4522,7 +4246,7 @@ static struct scsi_host_template megaraid_template = {
.eh_host_reset_handler = megaraid_reset,
};
-static int __devinit
+static int
megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct Scsi_Host *host;
@@ -4914,7 +4638,7 @@ __megaraid_shutdown(adapter_t *adapter)
mdelay(1000);
}
-static void __devexit
+static void
megaraid_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *host = pci_get_drvdata(pdev);
@@ -5008,7 +4732,7 @@ static struct pci_driver megaraid_pci_driver = {
.name = "megaraid_legacy",
.id_table = megaraid_pci_tbl,
.probe = megaraid_probe_one,
- .remove = __devexit_p(megaraid_remove_one),
+ .remove = megaraid_remove_one,
.shutdown = megaraid_shutdown,
};
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 4fb2adf..4d0ce4e 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -987,24 +987,7 @@ static int mega_init_scb (adapter_t *);
static int mega_is_bios_enabled (adapter_t *);
#ifdef CONFIG_PROC_FS
-static int mega_print_inquiry(char *, char *);
static void mega_create_proc_entry(int, struct proc_dir_entry *);
-static int proc_read_config(char *, char **, off_t, int, int *, void *);
-static int proc_read_stat(char *, char **, off_t, int, int *, void *);
-static int proc_read_mbox(char *, char **, off_t, int, int *, void *);
-static int proc_rebuild_rate(char *, char **, off_t, int, int *, void *);
-static int proc_battery(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch0(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch1(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch2(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv_ch3(char *, char **, off_t, int, int *, void *);
-static int proc_pdrv(adapter_t *, char *, int);
-static int proc_rdrv_10(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv_20(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv_30(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv_40(char *, char **, off_t, int, int *, void *);
-static int proc_rdrv(adapter_t *, char *, int, int);
-
static int mega_adapinq(adapter_t *, dma_addr_t);
static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t);
#endif
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 54b1c5b..e6a1e0b 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -305,7 +305,7 @@ static struct pci_driver megaraid_pci_driver = {
.name = "megaraid",
.id_table = pci_id_table_g,
.probe = megaraid_probe_one,
- .remove = __devexit_p(megaraid_detach_one),
+ .remove = megaraid_detach_one,
.shutdown = megaraid_mbox_shutdown,
};
@@ -434,7 +434,7 @@ megaraid_exit(void)
* This routine should be called whenever a new adapter is detected by the
* PCI hotplug susbsystem.
*/
-static int __devinit
+static int
megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
adapter_t *adapter;
@@ -735,7 +735,7 @@ megaraid_io_detach(adapter_t *adapter)
* - Allocate memory required for all the commands
* - Use internal library of FW routines, build up complete soft state
*/
-static int __devinit
+static int
megaraid_init_mbox(adapter_t *adapter)
{
struct pci_dev *pdev;
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 3b2365c..04a42a5 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -33,9 +33,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "06.504.01.00-rc1"
-#define MEGASAS_RELDATE "Oct. 1, 2012"
-#define MEGASAS_EXT_VERSION "Mon. Oct. 1 17:00:00 PDT 2012"
+#define MEGASAS_VERSION "06.600.18.00-rc1"
+#define MEGASAS_RELDATE "May. 15, 2013"
+#define MEGASAS_EXT_VERSION "Wed. May. 15 17:00:00 PDT 2013"
/*
* Device IDs
@@ -49,6 +49,33 @@
#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071
#define PCI_DEVICE_ID_LSI_FUSION 0x005b
#define PCI_DEVICE_ID_LSI_INVADER 0x005d
+#define PCI_DEVICE_ID_LSI_FURY 0x005f
+
+/*
+ * Intel HBA SSDIDs
+ */
+#define MEGARAID_INTEL_RS3DC080_SSDID 0x9360
+#define MEGARAID_INTEL_RS3DC040_SSDID 0x9362
+#define MEGARAID_INTEL_RS3SC008_SSDID 0x9380
+#define MEGARAID_INTEL_RS3MC044_SSDID 0x9381
+#define MEGARAID_INTEL_RS3WC080_SSDID 0x9341
+#define MEGARAID_INTEL_RS3WC040_SSDID 0x9343
+
+/*
+ * Intel HBA branding
+ */
+#define MEGARAID_INTEL_RS3DC080_BRANDING \
+ "Intel(R) RAID Controller RS3DC080"
+#define MEGARAID_INTEL_RS3DC040_BRANDING \
+ "Intel(R) RAID Controller RS3DC040"
+#define MEGARAID_INTEL_RS3SC008_BRANDING \
+ "Intel(R) RAID Controller RS3SC008"
+#define MEGARAID_INTEL_RS3MC044_BRANDING \
+ "Intel(R) RAID Controller RS3MC044"
+#define MEGARAID_INTEL_RS3WC080_BRANDING \
+ "Intel(R) RAID Controller RS3WC080"
+#define MEGARAID_INTEL_RS3WC040_BRANDING \
+ "Intel(R) RAID Controller RS3WC040"
/*
* =====================================
@@ -163,6 +190,12 @@
#define MR_DCMD_PD_LIST_QUERY 0x02010100
/*
+ * Global functions
+ */
+extern u8 MR_ValidateMapInfo(struct megasas_instance *instance);
+
+
+/*
* MFI command completion codes
*/
enum MFI_STAT {
@@ -702,8 +735,126 @@ struct megasas_ctrl_info {
*/
char package_version[0x60];
- u8 pad[0x800 - 0x6a0];
+ /*
+ * If adapterOperations.supportMoreThan8Phys is set,
+ * and deviceInterface.portCount is greater than 8,
+ * SAS Addrs for first 8 ports shall be populated in
+ * deviceInterface.portAddr, and the rest shall be
+ * populated in deviceInterfacePortAddr2.
+ */
+ u64 deviceInterfacePortAddr2[8]; /*6a0h */
+ u8 reserved3[128]; /*6e0h */
+
+ struct { /*760h */
+ u16 minPdRaidLevel_0:4;
+ u16 maxPdRaidLevel_0:12;
+
+ u16 minPdRaidLevel_1:4;
+ u16 maxPdRaidLevel_1:12;
+
+ u16 minPdRaidLevel_5:4;
+ u16 maxPdRaidLevel_5:12;
+
+ u16 minPdRaidLevel_1E:4;
+ u16 maxPdRaidLevel_1E:12;
+
+ u16 minPdRaidLevel_6:4;
+ u16 maxPdRaidLevel_6:12;
+
+ u16 minPdRaidLevel_10:4;
+ u16 maxPdRaidLevel_10:12;
+
+ u16 minPdRaidLevel_50:4;
+ u16 maxPdRaidLevel_50:12;
+
+ u16 minPdRaidLevel_60:4;
+ u16 maxPdRaidLevel_60:12;
+
+ u16 minPdRaidLevel_1E_RLQ0:4;
+ u16 maxPdRaidLevel_1E_RLQ0:12;
+
+ u16 minPdRaidLevel_1E0_RLQ0:4;
+ u16 maxPdRaidLevel_1E0_RLQ0:12;
+
+ u16 reserved[6];
+ } pdsForRaidLevels;
+
+ u16 maxPds; /*780h */
+ u16 maxDedHSPs; /*782h */
+ u16 maxGlobalHSPs; /*784h */
+ u16 ddfSize; /*786h */
+ u8 maxLdsPerArray; /*788h */
+ u8 partitionsInDDF; /*789h */
+ u8 lockKeyBinding; /*78ah */
+ u8 maxPITsPerLd; /*78bh */
+ u8 maxViewsPerLd; /*78ch */
+ u8 maxTargetId; /*78dh */
+ u16 maxBvlVdSize; /*78eh */
+
+ u16 maxConfigurableSSCSize; /*790h */
+ u16 currentSSCsize; /*792h */
+
+ char expanderFwVersion[12]; /*794h */
+
+ u16 PFKTrialTimeRemaining; /*7A0h */
+
+ u16 cacheMemorySize; /*7A2h */
+
+ struct { /*7A4h */
+ u32 supportPIcontroller:1;
+ u32 supportLdPIType1:1;
+ u32 supportLdPIType2:1;
+ u32 supportLdPIType3:1;
+ u32 supportLdBBMInfo:1;
+ u32 supportShieldState:1;
+ u32 blockSSDWriteCacheChange:1;
+ u32 supportSuspendResumeBGops:1;
+ u32 supportEmergencySpares:1;
+ u32 supportSetLinkSpeed:1;
+ u32 supportBootTimePFKChange:1;
+ u32 supportJBOD:1;
+ u32 disableOnlinePFKChange:1;
+ u32 supportPerfTuning:1;
+ u32 supportSSDPatrolRead:1;
+ u32 realTimeScheduler:1;
+
+ u32 supportResetNow:1;
+ u32 supportEmulatedDrives:1;
+ u32 headlessMode:1;
+ u32 dedicatedHotSparesLimited:1;
+
+
+ u32 supportUnevenSpans:1;
+ u32 reserved:11;
+ } adapterOperations2;
+
+ u8 driverVersion[32]; /*7A8h */
+ u8 maxDAPdCountSpinup60; /*7C8h */
+ u8 temperatureROC; /*7C9h */
+ u8 temperatureCtrl; /*7CAh */
+ u8 reserved4; /*7CBh */
+ u16 maxConfigurablePds; /*7CCh */
+
+
+ u8 reserved5[2]; /*0x7CDh */
+
+ /*
+ * HA cluster information
+ */
+ struct {
+ u32 peerIsPresent:1;
+ u32 peerIsIncompatible:1;
+ u32 hwIncompatible:1;
+ u32 fwVersionMismatch:1;
+ u32 ctrlPropIncompatible:1;
+ u32 premiumFeatureMismatch:1;
+ u32 reserved:26;
+ } cluster;
+
+ char clusterId[16]; /*7D4h */
+
+ u8 pad[0x800-0x7E4]; /*7E4 */
} __packed;
/*
@@ -759,7 +910,7 @@ struct megasas_ctrl_info {
#define MEGASAS_INT_CMDS 32
#define MEGASAS_SKINNY_INT_CMDS 5
-#define MEGASAS_MAX_MSIX_QUEUES 16
+#define MEGASAS_MAX_MSIX_QUEUES 128
/*
* FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
* SGLs based on the size of dma_addr_t
@@ -784,6 +935,11 @@ struct megasas_ctrl_info {
#define MFI_1068_PCSR_OFFSET 0x84
#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
#define MFI_1068_FW_READY 0xDDDD0000
+
+#define MR_MAX_REPLY_QUEUES_OFFSET 0X0000001F
+#define MR_MAX_REPLY_QUEUES_EXT_OFFSET 0X003FC000
+#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14
+#define MR_MAX_MSIX_REG_ARRAY 16
/*
* register set for both 1068 and 1078 controllers
* structure extended for 1078 registers
@@ -893,6 +1049,15 @@ union megasas_sgl_frame {
} __attribute__ ((packed));
+typedef union _MFI_CAPABILITIES {
+ struct {
+ u32 support_fp_remote_lun:1;
+ u32 support_additional_msix:1;
+ u32 reserved:30;
+ } mfi_capabilities;
+ u32 reg;
+} MFI_CAPABILITIES;
+
struct megasas_init_frame {
u8 cmd; /*00h */
@@ -900,7 +1065,7 @@ struct megasas_init_frame {
u8 cmd_status; /*02h */
u8 reserved_1; /*03h */
- u32 reserved_2; /*04h */
+ MFI_CAPABILITIES driver_operations; /*04h*/
u32 context; /*08h */
u32 pad_0; /*0Ch */
@@ -1297,7 +1462,7 @@ struct megasas_instance {
unsigned long base_addr;
struct megasas_register_set __iomem *reg_set;
-
+ u32 *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY];
struct megasas_pd_list pd_list[MEGASAS_MAX_PD];
u8 ld_ids[MEGASAS_MAX_LD_IDS];
s8 init_id;
@@ -1348,6 +1513,7 @@ struct megasas_instance {
u8 flag_ieee;
u8 issuepend_done;
u8 disableOnlineCtrlReset;
+ u8 UnevenSpanSupport;
u8 adprecovery;
unsigned long last_time;
u32 mfiStatus;
@@ -1366,6 +1532,8 @@ struct megasas_instance {
long reset_flags;
struct mutex reset_mutex;
int throttlequeuedepth;
+ u8 mask_interrupts;
+ u8 is_imr;
};
enum {
@@ -1381,8 +1549,8 @@ struct megasas_instance_template {
void (*fire_cmd)(struct megasas_instance *, dma_addr_t, \
u32, struct megasas_register_set __iomem *);
- void (*enable_intr)(struct megasas_register_set __iomem *) ;
- void (*disable_intr)(struct megasas_register_set __iomem *);
+ void (*enable_intr)(struct megasas_instance *);
+ void (*disable_intr)(struct megasas_instance *);
int (*clear_intr)(struct megasas_register_set __iomem *);
@@ -1488,7 +1656,4 @@ struct megasas_mgmt_info {
int max_index;
};
-#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
-#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
-
#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index e4f2baa..0177295 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FILE: megaraid_sas_base.c
- * Version : v06.504.01.00-rc1
+ * Version : 06.600.18.00-rc1
*
* Authors: LSI Corporation
* Sreenivas Bagalkote
@@ -122,6 +122,8 @@ static struct pci_device_id megasas_pci_table[] = {
/* Fusion */
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INVADER)},
/* Invader */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)},
+ /* Fury */
{}
};
@@ -169,8 +171,6 @@ megasas_sync_map_info(struct megasas_instance *instance);
int
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
void megasas_reset_reply_desc(struct megasas_instance *instance);
-u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
- struct LD_LOAD_BALANCE_INFO *lbInfo);
int megasas_reset_fusion(struct Scsi_Host *shost);
void megasas_fusion_ocr_wq(struct work_struct *work);
@@ -223,6 +223,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
cmd->frame_count = 0;
if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
(instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
(reset_devices))
cmd->frame->hdr.cmd = MFI_CMD_INVALID;
list_add_tail(&cmd->list, &instance->cmd_pool);
@@ -241,8 +242,10 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
* @regs: MFI register set
*/
static inline void
-megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
+megasas_enable_intr_xscale(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
+ regs = instance->reg_set;
writel(0, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */
@@ -254,9 +257,11 @@ megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
* @regs: MFI register set
*/
static inline void
-megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
+megasas_disable_intr_xscale(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
u32 mask = 0x1f;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -410,8 +415,10 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
* @regs: MFI register set
*/
static inline void
-megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+megasas_enable_intr_ppc(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
+ regs = instance->reg_set;
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
writel(~0x80000000, &(regs)->outbound_intr_mask);
@@ -425,9 +432,11 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
* @regs: MFI register set
*/
static inline void
-megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
+megasas_disable_intr_ppc(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
u32 mask = 0xFFFFFFFF;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -528,8 +537,10 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
* @regs: MFI register set
*/
static inline void
-megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_skinny(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
+ regs = instance->reg_set;
writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
@@ -543,9 +554,11 @@ megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
* @regs: MFI register set
*/
static inline void
-megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
+megasas_disable_intr_skinny(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
u32 mask = 0xFFFFFFFF;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -583,7 +596,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
/*
* Check if it is our interrupt
*/
- if ((megasas_read_fw_status_reg_gen2(regs) & MFI_STATE_MASK) ==
+ if ((megasas_read_fw_status_reg_skinny(regs) & MFI_STATE_MASK) ==
MFI_STATE_FAULT) {
mfiStatus = MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
} else
@@ -663,8 +676,10 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
* @regs: MFI register set
*/
static inline void
-megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_gen2(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
+ regs = instance->reg_set;
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
/* write ~0x00000005 (4 & 1) to the intr mask*/
@@ -679,9 +694,11 @@ megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
* @regs: MFI register set
*/
static inline void
-megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
+megasas_disable_intr_gen2(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
u32 mask = 0xFFFFFFFF;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -711,7 +728,7 @@ megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
*/
status = readl(&regs->outbound_intr_status);
- if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) {
+ if (status & MFI_INTR_FLAG_REPLY_MESSAGE) {
mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
}
if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) {
@@ -1471,6 +1488,14 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd
return SCSI_MLQUEUE_HOST_BUSY;
spin_lock_irqsave(&instance->hba_lock, flags);
+
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ scmd->result = DID_ERROR << 16;
+ done(scmd);
+ return 0;
+ }
+
if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
spin_unlock_irqrestore(&instance->hba_lock, flags);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1591,7 +1616,8 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
} else {
writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
@@ -1615,10 +1641,7 @@ megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
spin_lock_irqsave(instance->host->host_lock, flags);
instance->flag &= ~MEGASAS_FW_BUSY;
- if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ if (instance->is_imr) {
instance->host->can_queue =
instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
} else
@@ -1695,7 +1718,7 @@ void megasas_do_ocr(struct megasas_instance *instance)
(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
*instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN;
}
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
instance->issuepend_done = 0;
@@ -1966,7 +1989,8 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
* First wait for all commands to complete
*/
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
ret = megasas_reset_fusion(scmd->device->host);
else
ret = megasas_generic_reset(scmd);
@@ -2266,6 +2290,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
/* Check for LD map update */
if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
(cmd->frame->dcmd.mbox.b[1] == 1)) {
+ fusion->fast_path_io = 0;
spin_lock_irqsave(instance->host->host_lock, flags);
if (cmd->frame->hdr.cmd_status != 0) {
if (cmd->frame->hdr.cmd_status !=
@@ -2283,9 +2308,13 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
} else
instance->map_id++;
megasas_return_cmd(instance, cmd);
- if (MR_ValidateMapInfo(
- fusion->ld_map[(instance->map_id & 1)],
- fusion->load_balance_info))
+
+ /*
+ * Set fast path IO to ZERO.
+ * Validate Map will set proper value.
+ * Meanwhile all IOs will go as LD IO.
+ */
+ if (MR_ValidateMapInfo(instance))
fusion->fast_path_io = 1;
else
fusion->fast_path_io = 0;
@@ -2477,7 +2506,7 @@ process_fw_state_change_wq(struct work_struct *work)
printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
"state, restarting it...\n");
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
atomic_set(&instance->fw_outstanding, 0);
atomic_set(&instance->fw_reset_no_pci_access, 1);
@@ -2518,7 +2547,7 @@ process_fw_state_change_wq(struct work_struct *work)
spin_lock_irqsave(&instance->hba_lock, flags);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
spin_unlock_irqrestore(&instance->hba_lock, flags);
- instance->instancet->enable_intr(instance->reg_set);
+ instance->instancet->enable_intr(instance);
megasas_issue_pending_cmds_again(instance);
instance->issuepend_done = 1;
@@ -2581,7 +2610,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
}
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
instance->issuepend_done = 0;
@@ -2672,9 +2701,11 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) ||
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER)) {
+ PCI_DEVICE_ID_LSI_FURY)) {
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
@@ -2696,7 +2727,9 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_FUSION) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER)) {
+ PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FURY)) {
writel(MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
} else
@@ -2711,7 +2744,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
/*
* Bring it to READY state; assuming max wait 10 secs
*/
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if ((instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
@@ -2719,13 +2752,17 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
(instance->pdev->device
== PCI_DEVICE_ID_LSI_FUSION) ||
(instance->pdev->device
- == PCI_DEVICE_ID_LSI_INVADER)) {
+ == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device
+ == PCI_DEVICE_ID_LSI_FURY)) {
writel(MFI_RESET_FLAGS,
&instance->reg_set->doorbell);
if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER)) {
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FURY)) {
for (i = 0; i < (10 * 1000); i += 20) {
if (readl(
&instance->
@@ -2950,6 +2987,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
cmd->frame->io.pad_0 = 0;
if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
(instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
(reset_devices))
cmd->frame->hdr.cmd = MFI_CMD_INVALID;
}
@@ -3352,7 +3390,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
/*
* disable the intr before firing the init frame to FW
*/
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
/*
* Issue the init frame in polled mode
@@ -3459,11 +3497,11 @@ static int megasas_init_fw(struct megasas_instance *instance)
{
u32 max_sectors_1;
u32 max_sectors_2;
- u32 tmp_sectors, msix_enable;
+ u32 tmp_sectors, msix_enable, scratch_pad_2;
struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info;
unsigned long bar_list;
- int i;
+ int i, loop, fw_msix_count = 0;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
@@ -3487,6 +3525,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
case PCI_DEVICE_ID_LSI_INVADER:
+ case PCI_DEVICE_ID_LSI_FURY:
instance->instancet = &megasas_instance_template_fusion;
break;
case PCI_DEVICE_ID_LSI_SAS1078R:
@@ -3514,20 +3553,49 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (megasas_transition_to_ready(instance, 0))
goto fail_ready_state;
+ /*
+ * MSI-X host index 0 is common for all adapter.
+ * It is used for all MPT based Adapters.
+ */
+ instance->reply_post_host_index_addr[0] =
+ (u32 *)((u8 *)instance->reg_set +
+ MPI2_REPLY_POST_HOST_INDEX_OFFSET);
+
/* Check if MSI-X is supported while in ready state */
msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
0x4000000) >> 0x1a;
if (msix_enable && !msix_disable) {
+ scratch_pad_2 = readl
+ (&instance->reg_set->outbound_scratch_pad_2);
/* Check max MSI-X vectors */
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
- instance->msix_vectors = (readl(&instance->reg_set->
- outbound_scratch_pad_2
- ) & 0x1F) + 1;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+ instance->msix_vectors = (scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+ fw_msix_count = instance->msix_vectors;
if (msix_vectors)
instance->msix_vectors =
min(msix_vectors,
instance->msix_vectors);
+ } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
+ || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+ /* Invader/Fury supports more than 8 MSI-X */
+ instance->msix_vectors = ((scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
+ >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
+ fw_msix_count = instance->msix_vectors;
+ /* Save 1-15 reply post index address to local memory
+ * Index 0 is already saved from reg offset
+ * MPI2_REPLY_POST_HOST_INDEX_OFFSET
+ */
+ for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
+ instance->reply_post_host_index_addr[loop] =
+ (u32 *)((u8 *)instance->reg_set +
+ MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
+ + (loop * 0x10));
+ }
+ if (msix_vectors)
+ instance->msix_vectors = min(msix_vectors,
+ instance->msix_vectors);
} else
instance->msix_vectors = 1;
/* Don't bother allocating more MSI-X vectors than cpus */
@@ -3547,6 +3615,12 @@ static int megasas_init_fw(struct megasas_instance *instance)
}
} else
instance->msix_vectors = 0;
+
+ dev_info(&instance->pdev->dev, "[scsi%d]: FW supports"
+ "<%d> MSIX vector,Online CPUs: <%d>,"
+ "Current MSIX <%d>\n", instance->host->host_no,
+ fw_msix_count, (unsigned int)num_online_cpus(),
+ instance->msix_vectors);
}
/* Get operational params, sge flags, send init cmd to controller */
@@ -3585,8 +3659,32 @@ static int megasas_init_fw(struct megasas_instance *instance)
max_sectors_2 = ctrl_info->max_request_size;
tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
+
+ /*Check whether controller is iMR or MR */
+ if (ctrl_info->memory_size) {
+ instance->is_imr = 0;
+ dev_info(&instance->pdev->dev, "Controller type: MR,"
+ "Memory size is: %dMB\n",
+ ctrl_info->memory_size);
+ } else {
+ instance->is_imr = 1;
+ dev_info(&instance->pdev->dev,
+ "Controller type: iMR\n");
+ }
instance->disableOnlineCtrlReset =
ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
+ instance->UnevenSpanSupport =
+ ctrl_info->adapterOperations2.supportUnevenSpans;
+ if (instance->UnevenSpanSupport) {
+ struct fusion_context *fusion = instance->ctrl_context;
+ dev_info(&instance->pdev->dev, "FW supports: "
+ "UnevenSpanSupport=%x\n", instance->UnevenSpanSupport);
+ if (MR_ValidateMapInfo(instance))
+ fusion->fast_path_io = 1;
+ else
+ fusion->fast_path_io = 0;
+
+ }
}
instance->max_sectors_per_req = instance->max_num_sge *
@@ -3597,8 +3695,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
kfree(ctrl_info);
/* Check for valid throttlequeuedepth module parameter */
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY ||
- instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) {
+ if (instance->is_imr) {
if (throttlequeuedepth > (instance->max_fw_cmds -
MEGASAS_SKINNY_INT_CMDS))
instance->throttlequeuedepth =
@@ -3882,8 +3979,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
*/
host->irq = instance->pdev->irq;
host->unique_id = instance->unique_id;
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ if (instance->is_imr) {
host->can_queue =
instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
} else
@@ -3925,7 +4021,8 @@ static int megasas_io_attach(struct megasas_instance *instance)
/* Fusion only supports host reset */
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
host->hostt->eh_device_reset_handler = NULL;
host->hostt->eh_bus_reset_handler = NULL;
}
@@ -3972,8 +4069,8 @@ fail_set_dma_mask:
* @pdev: PCI device structure
* @id: PCI ids of supported hotplugged adapter
*/
-static int __devinit
-megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int megasas_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
int rval, pos, i, j;
struct Scsi_Host *host;
@@ -3984,12 +4081,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (reset_devices) {
pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
if (pos) {
- pci_read_config_word(pdev, msi_control_reg(pos),
+ pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS,
&control);
if (control & PCI_MSIX_FLAGS_ENABLE) {
dev_info(&pdev->dev, "resetting MSI-X\n");
pci_write_config_word(pdev,
- msi_control_reg(pos),
+ pos + PCI_MSIX_FLAGS,
control &
~PCI_MSIX_FLAGS_ENABLE);
}
@@ -4036,6 +4133,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
case PCI_DEVICE_ID_LSI_INVADER:
+ case PCI_DEVICE_ID_LSI_FURY:
{
struct fusion_context *fusion;
@@ -4076,6 +4174,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->ev = NULL;
instance->issuepend_done = 1;
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+ instance->is_imr = 0;
megasas_poll_wait_aen = 0;
instance->evt_detail = pci_alloc_consistent(pdev,
@@ -4126,9 +4225,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->unload = 1;
instance->last_time = 0;
instance->disableOnlineCtrlReset = 1;
+ instance->UnevenSpanSupport = 0;
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
else
INIT_WORK(&instance->work_init, process_fw_state_change_wq);
@@ -4139,6 +4240,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (megasas_init_fw(instance))
goto fail_init_mfi;
+retry_irq_register:
/*
* Register IRQ
*/
@@ -4156,7 +4258,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
free_irq(
instance->msixentry[j].vector,
&instance->irq_context[j]);
- goto fail_irq;
+ /* Retry irq register for IO_APIC */
+ instance->msix_vectors = 0;
+ goto retry_irq_register;
}
}
} else {
@@ -4170,7 +4274,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
}
- instance->instancet->enable_intr(instance->reg_set);
+ instance->instancet->enable_intr(instance);
/*
* Store instance in PCI softstate
@@ -4210,7 +4314,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
megasas_mgmt_info.max_index--;
pci_set_drvdata(pdev, NULL);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector,
@@ -4219,7 +4323,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
free_irq(instance->pdev->irq, &instance->irq_context[0]);
fail_irq:
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
megasas_release_fusion(instance);
else
megasas_release_mfi(instance);
@@ -4359,7 +4464,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
tasklet_kill(&instance->isr_tasklet);
pci_set_drvdata(instance->pdev, instance);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
@@ -4430,6 +4535,7 @@ megasas_resume(struct pci_dev *pdev)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
case PCI_DEVICE_ID_LSI_INVADER:
+ case PCI_DEVICE_ID_LSI_FURY:
{
megasas_reset_reply_desc(instance);
if (megasas_ioc_init_fusion(instance)) {
@@ -4483,7 +4589,7 @@ megasas_resume(struct pci_dev *pdev)
}
}
- instance->instancet->enable_intr(instance->reg_set);
+ instance->instancet->enable_intr(instance);
instance->unload = 0;
/*
@@ -4525,7 +4631,7 @@ fail_ready_state:
* megasas_detach_one - PCI hot"un"plug entry point
* @pdev: PCI device structure
*/
-static void __devexit megasas_detach_one(struct pci_dev *pdev)
+static void megasas_detach_one(struct pci_dev *pdev)
{
int i;
struct Scsi_Host *host;
@@ -4565,7 +4671,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
pci_set_drvdata(instance->pdev, NULL);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
@@ -4579,6 +4685,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
case PCI_DEVICE_ID_LSI_INVADER:
+ case PCI_DEVICE_ID_LSI_FURY:
megasas_release_fusion(instance);
for (i = 0; i < 2 ; i++)
if (fusion->ld_map[i])
@@ -4591,10 +4698,6 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
break;
default:
megasas_release_mfi(instance);
- pci_free_consistent(pdev,
- sizeof(struct megasas_evt_detail),
- instance->evt_detail,
- instance->evt_detail_h);
pci_free_consistent(pdev, sizeof(u32),
instance->producer,
instance->producer_h);
@@ -4604,6 +4707,9 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
break;
}
+ if (instance->evt_detail)
+ pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+ instance->evt_detail, instance->evt_detail_h);
scsi_host_put(host);
pci_set_drvdata(pdev, NULL);
@@ -4625,7 +4731,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
instance->unload = 1;
megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector,
@@ -4852,10 +4958,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
sense, sense_handle);
}
- for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
- dma_free_coherent(&instance->pdev->dev,
- kern_sge32[i].length,
- kbuff_arr[i], kern_sge32[i].phys_addr);
+ for (i = 0; i < ioc->sge_count; i++) {
+ if (kbuff_arr[i])
+ dma_free_coherent(&instance->pdev->dev,
+ kern_sge32[i].length,
+ kbuff_arr[i],
+ kern_sge32[i].phys_addr);
}
megasas_return_cmd(instance, cmd);
@@ -4931,11 +5039,12 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
printk(KERN_ERR "megaraid_sas: timed out while"
"waiting for HBA to recover\n");
error = -ENODEV;
- goto out_kfree_ioc;
+ goto out_up;
}
spin_unlock_irqrestore(&instance->hba_lock, flags);
error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
+ out_up:
up(&instance->ioctl_sem);
out_kfree_ioc:
@@ -5119,7 +5228,7 @@ static struct pci_driver megasas_pci_driver = {
.name = "megaraid_sas",
.id_table = megasas_pci_table,
.probe = megasas_probe_one,
- .remove = __devexit_p(megasas_detach_one),
+ .remove = megasas_detach_one,
.suspend = megasas_suspend,
.resume = megasas_resume,
.shutdown = megasas_shutdown,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index a11df82..4f401f7 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -60,10 +60,22 @@
#define FALSE 0
#define TRUE 1
+#define SPAN_DEBUG 0
+#define SPAN_ROW_SIZE(map, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowSize)
+#define SPAN_ROW_DATA_SIZE(map_, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize)
+#define SPAN_INVALID 0xff
+
/* Prototypes */
-void
-mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
- struct LD_LOAD_BALANCE_INFO *lbInfo);
+void mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
+ struct LD_LOAD_BALANCE_INFO *lbInfo);
+
+static void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
+ PLD_SPAN_INFO ldSpanInfo);
+static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
+ u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info,
+ struct RAID_CONTEXT *pRAID_Context, struct MR_FW_RAID_MAP_ALL *map);
+static u64 get_row_from_strip(struct megasas_instance *instance, u32 ld,
+ u64 strip, struct MR_FW_RAID_MAP_ALL *map);
u32 mega_mod64(u64 dividend, u32 divisor)
{
@@ -148,9 +160,12 @@ static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
/*
* This function will validate Map info data provided by FW
*/
-u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
- struct LD_LOAD_BALANCE_INFO *lbInfo)
+u8 MR_ValidateMapInfo(struct megasas_instance *instance)
{
+ struct fusion_context *fusion = instance->ctrl_context;
+ struct MR_FW_RAID_MAP_ALL *map = fusion->ld_map[(instance->map_id & 1)];
+ struct LD_LOAD_BALANCE_INFO *lbInfo = fusion->load_balance_info;
+ PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
if (pFwRaidMap->totalSize !=
@@ -167,13 +182,16 @@ u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
return 0;
}
+ if (instance->UnevenSpanSupport)
+ mr_update_span_set(map, ldSpanInfo);
+
mr_update_load_balance_params(map, lbInfo);
return 1;
}
u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
- struct MR_FW_RAID_MAP_ALL *map, int *div_error)
+ struct MR_FW_RAID_MAP_ALL *map)
{
struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
struct MR_QUAD_ELEMENT *quad;
@@ -185,10 +203,8 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) {
quad = &pSpanBlock->block_span_info.quad[j];
- if (quad->diff == 0) {
- *div_error = 1;
- return span;
- }
+ if (quad->diff == 0)
+ return SPAN_INVALID;
if (quad->logStart <= row && row <= quad->logEnd &&
(mega_mod64(row-quad->logStart, quad->diff)) == 0) {
if (span_blk != NULL) {
@@ -207,7 +223,456 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
}
}
}
- return span;
+ return SPAN_INVALID;
+}
+
+/*
+******************************************************************************
+*
+* Function to print info about span set created in driver from FW raid map
+*
+* Inputs :
+* map - LD map
+* ldSpanInfo - ldSpanInfo per HBA instance
+*/
+#if SPAN_DEBUG
+static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
+{
+
+ u8 span;
+ u32 element;
+ struct MR_LD_RAID *raid;
+ LD_SPAN_SET *span_set;
+ struct MR_QUAD_ELEMENT *quad;
+ int ldCount;
+ u16 ld;
+
+ for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+ ld = MR_TargetIdToLdGet(ldCount, map);
+ if (ld >= MAX_LOGICAL_DRIVES)
+ continue;
+ raid = MR_LdRaidGet(ld, map);
+ dev_dbg(&instance->pdev->dev, "LD %x: span_depth=%x\n",
+ ld, raid->spanDepth);
+ for (span = 0; span < raid->spanDepth; span++)
+ dev_dbg(&instance->pdev->dev, "Span=%x,"
+ " number of quads=%x\n", span,
+ map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements);
+ for (element = 0; element < MAX_QUAD_DEPTH; element++) {
+ span_set = &(ldSpanInfo[ld].span_set[element]);
+ if (span_set->span_row_data_width == 0)
+ break;
+
+ dev_dbg(&instance->pdev->dev, "Span Set %x:"
+ "width=%x, diff=%x\n", element,
+ (unsigned int)span_set->span_row_data_width,
+ (unsigned int)span_set->diff);
+ dev_dbg(&instance->pdev->dev, "logical LBA"
+ "start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)span_set->log_start_lba,
+ (long unsigned int)span_set->log_end_lba);
+ dev_dbg(&instance->pdev->dev, "span row start=0x%08lx,"
+ " end=0x%08lx\n",
+ (long unsigned int)span_set->span_row_start,
+ (long unsigned int)span_set->span_row_end);
+ dev_dbg(&instance->pdev->dev, "data row start=0x%08lx,"
+ " end=0x%08lx\n",
+ (long unsigned int)span_set->data_row_start,
+ (long unsigned int)span_set->data_row_end);
+ dev_dbg(&instance->pdev->dev, "data strip start=0x%08lx,"
+ " end=0x%08lx\n",
+ (long unsigned int)span_set->data_strip_start,
+ (long unsigned int)span_set->data_strip_end);
+
+ for (span = 0; span < raid->spanDepth; span++) {
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >=
+ element + 1) {
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].block_span_info.
+ quad[element];
+ dev_dbg(&instance->pdev->dev, "Span=%x,"
+ "Quad=%x, diff=%x\n", span,
+ element, quad->diff);
+ dev_dbg(&instance->pdev->dev,
+ "offset_in_span=0x%08lx\n",
+ (long unsigned int)quad->offsetInSpan);
+ dev_dbg(&instance->pdev->dev,
+ "logical start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)quad->logStart,
+ (long unsigned int)quad->logEnd);
+ }
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+/*
+******************************************************************************
+*
+* This routine calculates the Span block for given row using spanset.
+*
+* Inputs :
+* instance - HBA instance
+* ld - Logical drive number
+* row - Row number
+* map - LD map
+*
+* Outputs :
+*
+* span - Span number
+* block - Absolute Block number in the physical disk
+* div_error - Devide error code.
+*/
+
+u32 mr_spanset_get_span_block(struct megasas_instance *instance,
+ u32 ld, u64 row, u64 *span_blk, struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct fusion_context *fusion = instance->ctrl_context;
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ struct MR_QUAD_ELEMENT *quad;
+ u32 span, info;
+ PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+
+ if (row > span_set->data_row_end)
+ continue;
+
+ for (span = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info+1) {
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].
+ block_span_info.quad[info];
+ if (quad->diff == 0)
+ return SPAN_INVALID;
+ if (quad->logStart <= row &&
+ row <= quad->logEnd &&
+ (mega_mod64(row - quad->logStart,
+ quad->diff)) == 0) {
+ if (span_blk != NULL) {
+ u64 blk;
+ blk = mega_div64_32
+ ((row - quad->logStart),
+ quad->diff);
+ blk = (blk + quad->offsetInSpan)
+ << raid->stripeShift;
+ *span_blk = blk;
+ }
+ return span;
+ }
+ }
+ }
+ return SPAN_INVALID;
+}
+
+/*
+******************************************************************************
+*
+* This routine calculates the row for given strip using spanset.
+*
+* Inputs :
+* instance - HBA instance
+* ld - Logical drive number
+* Strip - Strip
+* map - LD map
+*
+* Outputs :
+*
+* row - row associated with strip
+*/
+
+static u64 get_row_from_strip(struct megasas_instance *instance,
+ u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct fusion_context *fusion = instance->ctrl_context;
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
+ u32 info, strip_offset, span, span_offset;
+ u64 span_set_Strip, span_set_Row, retval;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (strip > span_set->data_strip_end)
+ continue;
+
+ span_set_Strip = strip - span_set->data_strip_start;
+ strip_offset = mega_mod64(span_set_Strip,
+ span_set->span_row_data_width);
+ span_set_Row = mega_div64_32(span_set_Strip,
+ span_set->span_row_data_width) * span_set->diff;
+ for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info+1) {
+ if (strip_offset >=
+ span_set->strip_offset[span])
+ span_offset++;
+ else
+ break;
+ }
+#if SPAN_DEBUG
+ dev_info(&instance->pdev->dev, "Strip 0x%llx,"
+ "span_set_Strip 0x%llx, span_set_Row 0x%llx"
+ "data width 0x%llx span offset 0x%x\n", strip,
+ (unsigned long long)span_set_Strip,
+ (unsigned long long)span_set_Row,
+ (unsigned long long)span_set->span_row_data_width,
+ span_offset);
+ dev_info(&instance->pdev->dev, "For strip 0x%llx"
+ "row is 0x%llx\n", strip,
+ (unsigned long long) span_set->data_row_start +
+ (unsigned long long) span_set_Row + (span_offset - 1));
+#endif
+ retval = (span_set->data_row_start + span_set_Row +
+ (span_offset - 1));
+ return retval;
+ }
+ return -1LLU;
+}
+
+
+/*
+******************************************************************************
+*
+* This routine calculates the Start Strip for given row using spanset.
+*
+* Inputs :
+* instance - HBA instance
+* ld - Logical drive number
+* row - Row number
+* map - LD map
+*
+* Outputs :
+*
+* Strip - Start strip associated with row
+*/
+
+static u64 get_strip_from_row(struct megasas_instance *instance,
+ u32 ld, u64 row, struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct fusion_context *fusion = instance->ctrl_context;
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ struct MR_QUAD_ELEMENT *quad;
+ PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
+ u32 span, info;
+ u64 strip;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (row > span_set->data_row_end)
+ continue;
+
+ for (span = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info+1) {
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].block_span_info.quad[info];
+ if (quad->logStart <= row &&
+ row <= quad->logEnd &&
+ mega_mod64((row - quad->logStart),
+ quad->diff) == 0) {
+ strip = mega_div64_32
+ (((row - span_set->data_row_start)
+ - quad->logStart),
+ quad->diff);
+ strip *= span_set->span_row_data_width;
+ strip += span_set->data_strip_start;
+ strip += span_set->strip_offset[span];
+ return strip;
+ }
+ }
+ }
+ dev_err(&instance->pdev->dev, "get_strip_from_row"
+ "returns invalid strip for ld=%x, row=%lx\n",
+ ld, (long unsigned int)row);
+ return -1;
+}
+
+/*
+******************************************************************************
+*
+* This routine calculates the Physical Arm for given strip using spanset.
+*
+* Inputs :
+* instance - HBA instance
+* ld - Logical drive number
+* strip - Strip
+* map - LD map
+*
+* Outputs :
+*
+* Phys Arm - Phys Arm associated with strip
+*/
+
+static u32 get_arm_from_strip(struct megasas_instance *instance,
+ u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct fusion_context *fusion = instance->ctrl_context;
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
+ u32 info, strip_offset, span, span_offset, retval;
+
+ for (info = 0 ; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (strip > span_set->data_strip_end)
+ continue;
+
+ strip_offset = (uint)mega_mod64
+ ((strip - span_set->data_strip_start),
+ span_set->span_row_data_width);
+
+ for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info+1) {
+ if (strip_offset >=
+ span_set->strip_offset[span])
+ span_offset =
+ span_set->strip_offset[span];
+ else
+ break;
+ }
+#if SPAN_DEBUG
+ dev_info(&instance->pdev->dev, "get_arm_from_strip:"
+ "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld,
+ (long unsigned int)strip, (strip_offset - span_offset));
+#endif
+ retval = (strip_offset - span_offset);
+ return retval;
+ }
+
+ dev_err(&instance->pdev->dev, "get_arm_from_strip"
+ "returns invalid arm for ld=%x strip=%lx\n",
+ ld, (long unsigned int)strip);
+
+ return -1;
+}
+
+/* This Function will return Phys arm */
+u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe,
+ struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ /* Need to check correct default value */
+ u32 arm = 0;
+
+ switch (raid->level) {
+ case 0:
+ case 5:
+ case 6:
+ arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span));
+ break;
+ case 1:
+ /* start with logical arm */
+ arm = get_arm_from_strip(instance, ld, stripe, map);
+ if (arm != -1U)
+ arm *= 2;
+ break;
+ }
+
+ return arm;
+}
+
+
+/*
+******************************************************************************
+*
+* This routine calculates the arm, span and block for the specified stripe and
+* reference in stripe using spanset
+*
+* Inputs :
+*
+* ld - Logical drive number
+* stripRow - Stripe number
+* stripRef - Reference in stripe
+*
+* Outputs :
+*
+* span - Span number
+* block - Absolute Block number in the physical disk
+*/
+static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
+ u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info,
+ struct RAID_CONTEXT *pRAID_Context,
+ struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ u32 pd, arRef;
+ u8 physArm, span;
+ u64 row;
+ u8 retval = TRUE;
+ u8 do_invader = 0;
+ u64 *pdBlock = &io_info->pdBlock;
+ u16 *pDevHandle = &io_info->devHandle;
+ u32 logArm, rowMod, armQ, arm;
+
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
+ instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ do_invader = 1;
+
+ /*Get row and span from io_info for Uneven Span IO.*/
+ row = io_info->start_row;
+ span = io_info->start_span;
+
+
+ if (raid->level == 6) {
+ logArm = get_arm_from_strip(instance, ld, stripRow, map);
+ if (logArm == -1U)
+ return FALSE;
+ rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span));
+ armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod;
+ arm = armQ + 1 + logArm;
+ if (arm >= SPAN_ROW_SIZE(map, ld, span))
+ arm -= SPAN_ROW_SIZE(map, ld, span);
+ physArm = (u8)arm;
+ } else
+ /* Calculate the arm */
+ physArm = get_arm(instance, ld, span, stripRow, map);
+ if (physArm == 0xFF)
+ return FALSE;
+
+ arRef = MR_LdSpanArrayGet(ld, span, map);
+ pd = MR_ArPdGet(arRef, physArm, map);
+
+ if (pd != MR_PD_INVALID)
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ else {
+ *pDevHandle = MR_PD_INVALID;
+ if ((raid->level >= 5) &&
+ (!do_invader || (do_invader &&
+ (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
+ pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
+ else if (raid->level == 1) {
+ pd = MR_ArPdGet(arRef, physArm + 1, map);
+ if (pd != MR_PD_INVALID)
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ }
+ }
+
+ *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
+ pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
+ physArm;
+ return retval;
}
/*
@@ -228,16 +693,22 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
* block - Absolute Block number in the physical disk
*/
u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
- u16 stripRef, u64 *pdBlock, u16 *pDevHandle,
- struct RAID_CONTEXT *pRAID_Context,
- struct MR_FW_RAID_MAP_ALL *map)
+ u16 stripRef, struct IO_REQUEST_INFO *io_info,
+ struct RAID_CONTEXT *pRAID_Context,
+ struct MR_FW_RAID_MAP_ALL *map)
{
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
u32 pd, arRef;
u8 physArm, span;
u64 row;
u8 retval = TRUE;
- int error_code = 0;
+ u8 do_invader = 0;
+ u64 *pdBlock = &io_info->pdBlock;
+ u16 *pDevHandle = &io_info->devHandle;
+
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
+ instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ do_invader = 1;
row = mega_div64_32(stripRow, raid->rowDataSize);
@@ -267,8 +738,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
span = 0;
*pdBlock = row << raid->stripeShift;
} else {
- span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);
- if (error_code == 1)
+ span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map);
+ if (span == SPAN_INVALID)
return FALSE;
}
@@ -282,9 +753,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
else {
*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
if ((raid->level >= 5) &&
- ((instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER &&
- raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
+ (!do_invader || (do_invader &&
+ (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
/* Get alternate Pd. */
@@ -327,17 +797,42 @@ MR_BuildRaidContext(struct megasas_instance *instance,
u32 numBlocks, ldTgtId;
u8 isRead;
u8 retval = 0;
+ u8 startlba_span = SPAN_INVALID;
+ u64 *pdBlock = &io_info->pdBlock;
ldStartBlock = io_info->ldStartBlock;
numBlocks = io_info->numBlocks;
ldTgtId = io_info->ldTgtId;
isRead = io_info->isRead;
+ io_info->IoforUnevenSpan = 0;
+ io_info->start_span = SPAN_INVALID;
ld = MR_TargetIdToLdGet(ldTgtId, map);
raid = MR_LdRaidGet(ld, map);
+ /*
+ * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero
+ * return FALSE
+ */
+ if (raid->rowDataSize == 0) {
+ if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0)
+ return FALSE;
+ else if (instance->UnevenSpanSupport) {
+ io_info->IoforUnevenSpan = 1;
+ } else {
+ dev_info(&instance->pdev->dev,
+ "raid->rowDataSize is 0, but has SPAN[0]"
+ "rowDataSize = 0x%0x,"
+ "but there is _NO_ UnevenSpanSupport\n",
+ MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize);
+ return FALSE;
+ }
+ }
+
stripSize = 1 << raid->stripeShift;
stripe_mask = stripSize-1;
+
+
/*
* calculate starting row and stripe, and number of strips and rows
*/
@@ -347,11 +842,50 @@ MR_BuildRaidContext(struct megasas_instance *instance,
ref_in_end_stripe = (u16)(endLba & stripe_mask);
endStrip = endLba >> raid->stripeShift;
num_strips = (u8)(endStrip - start_strip + 1); /* End strip */
- if (raid->rowDataSize == 0)
- return FALSE;
- start_row = mega_div64_32(start_strip, raid->rowDataSize);
- endRow = mega_div64_32(endStrip, raid->rowDataSize);
- numRows = (u8)(endRow - start_row + 1);
+
+ if (io_info->IoforUnevenSpan) {
+ start_row = get_row_from_strip(instance, ld, start_strip, map);
+ endRow = get_row_from_strip(instance, ld, endStrip, map);
+ if (start_row == -1ULL || endRow == -1ULL) {
+ dev_info(&instance->pdev->dev, "return from %s %d."
+ "Send IO w/o region lock.\n",
+ __func__, __LINE__);
+ return FALSE;
+ }
+
+ if (raid->spanDepth == 1) {
+ startlba_span = 0;
+ *pdBlock = start_row << raid->stripeShift;
+ } else
+ startlba_span = (u8)mr_spanset_get_span_block(instance,
+ ld, start_row, pdBlock, map);
+ if (startlba_span == SPAN_INVALID) {
+ dev_info(&instance->pdev->dev, "return from %s %d"
+ "for row 0x%llx,start strip %llx"
+ "endSrip %llx\n", __func__, __LINE__,
+ (unsigned long long)start_row,
+ (unsigned long long)start_strip,
+ (unsigned long long)endStrip);
+ return FALSE;
+ }
+ io_info->start_span = startlba_span;
+ io_info->start_row = start_row;
+#if SPAN_DEBUG
+ dev_dbg(&instance->pdev->dev, "Check Span number from %s %d"
+ "for row 0x%llx, start strip 0x%llx end strip 0x%llx"
+ " span 0x%x\n", __func__, __LINE__,
+ (unsigned long long)start_row,
+ (unsigned long long)start_strip,
+ (unsigned long long)endStrip, startlba_span);
+ dev_dbg(&instance->pdev->dev, "start_row 0x%llx endRow 0x%llx"
+ "Start span 0x%x\n", (unsigned long long)start_row,
+ (unsigned long long)endRow, startlba_span);
+#endif
+ } else {
+ start_row = mega_div64_32(start_strip, raid->rowDataSize);
+ endRow = mega_div64_32(endStrip, raid->rowDataSize);
+ }
+ numRows = (u8)(endRow - start_row + 1);
/*
* calculate region info.
@@ -384,28 +918,56 @@ MR_BuildRaidContext(struct megasas_instance *instance,
regSize = numBlocks;
}
/* multi-strip IOs always need to full stripe locked */
- } else {
+ } else if (io_info->IoforUnevenSpan == 0) {
+ /*
+ * For Even span region lock optimization.
+ * If the start strip is the last in the start row
+ */
if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
- /* If the start strip is the last in the start row */
regStart += ref_in_start_stripe;
- regSize = stripSize - ref_in_start_stripe;
/* initialize count to sectors from startref to end
of strip */
+ regSize = stripSize - ref_in_start_stripe;
}
+ /* add complete rows in the middle of the transfer */
if (numRows > 2)
- /* Add complete rows in the middle of the transfer */
regSize += (numRows-2) << raid->stripeShift;
- /* if IO ends within first strip of last row */
+ /* if IO ends within first strip of last row*/
if (endStrip == endRow*raid->rowDataSize)
regSize += ref_in_end_stripe+1;
else
regSize += stripSize;
+ } else {
+ /*
+ * For Uneven span region lock optimization.
+ * If the start strip is the last in the start row
+ */
+ if (start_strip == (get_strip_from_row(instance, ld, start_row, map) +
+ SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) {
+ regStart += ref_in_start_stripe;
+ /* initialize count to sectors from
+ * startRef to end of strip
+ */
+ regSize = stripSize - ref_in_start_stripe;
+ }
+ /* Add complete rows in the middle of the transfer*/
+
+ if (numRows > 2)
+ /* Add complete rows in the middle of the transfer*/
+ regSize += (numRows-2) << raid->stripeShift;
+
+ /* if IO ends within first strip of last row */
+ if (endStrip == get_strip_from_row(instance, ld, endRow, map))
+ regSize += ref_in_end_stripe + 1;
+ else
+ regSize += stripSize;
}
pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
pRAID_Context->regLockFlags = (isRead) ?
raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
else
@@ -419,30 +981,161 @@ MR_BuildRaidContext(struct megasas_instance *instance,
/*Get Phy Params only if FP capable, or else leave it to MR firmware
to do the calculation.*/
if (io_info->fpOkForIo) {
- retval = MR_GetPhyParams(instance, ld, start_strip,
- ref_in_start_stripe,
- &io_info->pdBlock,
- &io_info->devHandle, pRAID_Context,
- map);
- /* If IO on an invalid Pd, then FP i snot possible */
+ retval = io_info->IoforUnevenSpan ?
+ mr_spanset_get_phy_params(instance, ld,
+ start_strip, ref_in_start_stripe,
+ io_info, pRAID_Context, map) :
+ MR_GetPhyParams(instance, ld, start_strip,
+ ref_in_start_stripe, io_info,
+ pRAID_Context, map);
+ /* If IO on an invalid Pd, then FP is not possible.*/
if (io_info->devHandle == MR_PD_INVALID)
io_info->fpOkForIo = FALSE;
return retval;
} else if (isRead) {
uint stripIdx;
for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
- if (!MR_GetPhyParams(instance, ld,
- start_strip + stripIdx,
- ref_in_start_stripe,
- &io_info->pdBlock,
- &io_info->devHandle,
- pRAID_Context, map))
+ retval = io_info->IoforUnevenSpan ?
+ mr_spanset_get_phy_params(instance, ld,
+ start_strip + stripIdx,
+ ref_in_start_stripe, io_info,
+ pRAID_Context, map) :
+ MR_GetPhyParams(instance, ld,
+ start_strip + stripIdx, ref_in_start_stripe,
+ io_info, pRAID_Context, map);
+ if (!retval)
return TRUE;
}
}
+
+#if SPAN_DEBUG
+ /* Just for testing what arm we get for strip.*/
+ if (io_info->IoforUnevenSpan)
+ get_arm_from_strip(instance, ld, start_strip, map);
+#endif
return TRUE;
}
+/*
+******************************************************************************
+*
+* This routine pepare spanset info from Valid Raid map and store it into
+* local copy of ldSpanInfo per instance data structure.
+*
+* Inputs :
+* map - LD map
+* ldSpanInfo - ldSpanInfo per HBA instance
+*
+*/
+void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
+ PLD_SPAN_INFO ldSpanInfo)
+{
+ u8 span, count;
+ u32 element, span_row_width;
+ u64 span_row;
+ struct MR_LD_RAID *raid;
+ LD_SPAN_SET *span_set, *span_set_prev;
+ struct MR_QUAD_ELEMENT *quad;
+ int ldCount;
+ u16 ld;
+
+
+ for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+ ld = MR_TargetIdToLdGet(ldCount, map);
+ if (ld >= MAX_LOGICAL_DRIVES)
+ continue;
+ raid = MR_LdRaidGet(ld, map);
+ for (element = 0; element < MAX_QUAD_DEPTH; element++) {
+ for (span = 0; span < raid->spanDepth; span++) {
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements <
+ element + 1)
+ continue;
+ span_set = &(ldSpanInfo[ld].span_set[element]);
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].block_span_info.
+ quad[element];
+
+ span_set->diff = quad->diff;
+
+ for (count = 0, span_row_width = 0;
+ count < raid->spanDepth; count++) {
+ if (map->raidMap.ldSpanMap[ld].
+ spanBlock[count].
+ block_span_info.
+ noElements >= element + 1) {
+ span_set->strip_offset[count] =
+ span_row_width;
+ span_row_width +=
+ MR_LdSpanPtrGet
+ (ld, count, map)->spanRowDataSize;
+ printk(KERN_INFO "megasas:"
+ "span %x rowDataSize %x\n",
+ count, MR_LdSpanPtrGet
+ (ld, count, map)->spanRowDataSize);
+ }
+ }
+
+ span_set->span_row_data_width = span_row_width;
+ span_row = mega_div64_32(((quad->logEnd -
+ quad->logStart) + quad->diff),
+ quad->diff);
+
+ if (element == 0) {
+ span_set->log_start_lba = 0;
+ span_set->log_end_lba =
+ ((span_row << raid->stripeShift)
+ * span_row_width) - 1;
+
+ span_set->span_row_start = 0;
+ span_set->span_row_end = span_row - 1;
+
+ span_set->data_strip_start = 0;
+ span_set->data_strip_end =
+ (span_row * span_row_width) - 1;
+
+ span_set->data_row_start = 0;
+ span_set->data_row_end =
+ (span_row * quad->diff) - 1;
+ } else {
+ span_set_prev = &(ldSpanInfo[ld].
+ span_set[element - 1]);
+ span_set->log_start_lba =
+ span_set_prev->log_end_lba + 1;
+ span_set->log_end_lba =
+ span_set->log_start_lba +
+ ((span_row << raid->stripeShift)
+ * span_row_width) - 1;
+
+ span_set->span_row_start =
+ span_set_prev->span_row_end + 1;
+ span_set->span_row_end =
+ span_set->span_row_start + span_row - 1;
+
+ span_set->data_strip_start =
+ span_set_prev->data_strip_end + 1;
+ span_set->data_strip_end =
+ span_set->data_strip_start +
+ (span_row * span_row_width) - 1;
+
+ span_set->data_row_start =
+ span_set_prev->data_row_end + 1;
+ span_set->data_row_end =
+ span_set->data_row_start +
+ (span_row * quad->diff) - 1;
+ }
+ break;
+ }
+ if (span == raid->spanDepth)
+ break;
+ }
+ }
+#if SPAN_DEBUG
+ getSpanInfo(map, ldSpanInfo);
+#endif
+
+}
+
void
mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo)
@@ -503,8 +1196,9 @@ u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block,
diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]);
bestArm = (diff0 <= diff1 ? 0 : 1);
- if ((bestArm == arm && pend0 > pend1 + 16) ||
- (bestArm != arm && pend1 > pend0 + 16))
+ /*Make balance count from 16 to 4 to keep driver in sync with Firmware*/
+ if ((bestArm == arm && pend0 > pend1 + 4) ||
+ (bestArm != arm && pend1 > pend0 + 4))
bestArm ^= 1;
/* Update the last accessed block on the correct pd */
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 74030af..417d5f1 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -86,8 +86,6 @@ u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
void
megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
-u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
- struct LD_LOAD_BALANCE_INFO *lbInfo);
u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *in_info);
int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
@@ -101,8 +99,10 @@ extern int resetwaittime;
* @regs: MFI register set
*/
void
-megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_fusion(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *regs;
+ regs = instance->reg_set;
/* For Thunderbolt/Invader also clear intr on enable */
writel(~0, &regs->outbound_intr_status);
readl(&regs->outbound_intr_status);
@@ -111,6 +111,7 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
+ instance->mask_interrupts = 0;
}
/**
@@ -118,10 +119,13 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
* @regs: MFI register set
*/
void
-megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs)
+megasas_disable_intr_fusion(struct megasas_instance *instance)
{
u32 mask = 0xFFFFFFFF;
u32 status;
+ struct megasas_register_set __iomem *regs;
+ regs = instance->reg_set;
+ instance->mask_interrupts = 1;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
@@ -643,6 +647,12 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
init_frame->cmd = MFI_CMD_INIT;
init_frame->cmd_status = 0xFF;
+ /* driver support Extended MSIX */
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ init_frame->driver_operations.
+ mfi_capabilities.support_additional_msix = 1;
+
init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
@@ -657,7 +667,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
/*
* disable the intr before firing the init frame
*/
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
for (i = 0; i < (10 * 1000); i += 20) {
if (readl(&instance->reg_set->doorbell) & 1)
@@ -770,8 +780,7 @@ megasas_get_map_info(struct megasas_instance *instance)
fusion->fast_path_io = 0;
if (!megasas_get_ld_map_info(instance)) {
- if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)],
- fusion->load_balance_info)) {
+ if (MR_ValidateMapInfo(instance)) {
fusion->fast_path_io = 1;
return 0;
}
@@ -864,6 +873,66 @@ megasas_sync_map_info(struct megasas_instance *instance)
return ret;
}
+/*
+ * meagasas_display_intel_branding - Display branding string
+ * @instance: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+megasas_display_intel_branding(struct megasas_instance *instance)
+{
+ if (instance->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
+ return;
+
+ switch (instance->pdev->device) {
+ case PCI_DEVICE_ID_LSI_INVADER:
+ switch (instance->pdev->subsystem_device) {
+ case MEGARAID_INTEL_RS3DC080_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RS3DC080_BRANDING);
+ break;
+ case MEGARAID_INTEL_RS3DC040_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RS3DC040_BRANDING);
+ break;
+ case MEGARAID_INTEL_RS3SC008_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RS3SC008_BRANDING);
+ break;
+ case MEGARAID_INTEL_RS3MC044_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RS3MC044_BRANDING);
+ break;
+ default:
+ break;
+ }
+ break;
+ case PCI_DEVICE_ID_LSI_FURY:
+ switch (instance->pdev->subsystem_device) {
+ case MEGARAID_INTEL_RS3WC080_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RS3WC080_BRANDING);
+ break;
+ case MEGARAID_INTEL_RS3WC040_SSDID:
+ dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+ instance->host->host_no,
+ MEGARAID_INTEL_RS3WC040_BRANDING);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
/**
* megasas_init_adapter_fusion - Initializes the FW
* @instance: Adapter soft state
@@ -944,6 +1013,8 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
if (megasas_ioc_init_fusion(instance))
goto fail_ioc_init;
+ megasas_display_intel_branding(instance);
+
instance->flag_ieee = 1;
fusion->map_sz = sizeof(struct MR_FW_RAID_MAP) +
@@ -1071,7 +1142,8 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
fusion = instance->ctrl_context;
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
sgl_ptr_end->Flags = 0;
@@ -1088,7 +1160,8 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
sgl_ptr->Length = sg_dma_len(os_sgl);
sgl_ptr->Address = sg_dma_address(os_sgl);
sgl_ptr->Flags = 0;
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
if (i == sge_count - 1)
sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
}
@@ -1100,8 +1173,10 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
(sge_count > fusion->max_sge_in_main_msg)) {
struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
- if (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER) {
+ if ((instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FURY)) {
if ((cmd->io_request->IoFlags &
MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
@@ -1117,8 +1192,10 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
sg_chain = sgl_ptr;
/* Prepare chain element */
sg_chain->NextChainOffset = 0;
- if (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_INVADER)
+ if ((instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FURY))
sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
else
sg_chain->Flags =
@@ -1206,7 +1283,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
}
io_request->Control |= (0x4 << 26);
- io_request->EEDPBlockSize = MEGASAS_EEDPBLOCKSIZE;
+ io_request->EEDPBlockSize = scp->device->sector_size;
} else {
/* Some drives don't support 16/12 byte CDB's, convert to 10 */
if (((cdb_len == 12) || (cdb_len == 16)) &&
@@ -1434,7 +1511,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
cmd->request_desc->SCSIIO.RequestFlags =
(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
if (io_request->RaidContext.regLockFlags ==
REGION_TYPE_UNUSED)
cmd->request_desc->SCSIIO.RequestFlags =
@@ -1465,7 +1543,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
cmd->request_desc->SCSIIO.RequestFlags =
(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
if (io_request->RaidContext.regLockFlags ==
REGION_TYPE_UNUSED)
cmd->request_desc->SCSIIO.RequestFlags =
@@ -1511,7 +1590,8 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS &&
instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
io_request->Function = 0;
- io_request->DevHandle =
+ if (fusion->fast_path_io)
+ io_request->DevHandle =
local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
io_request->RaidContext.timeoutValue =
local_map_ptr->raidMap.fpPdIoTimeoutSec;
@@ -1521,11 +1601,27 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
io_request->RaidContext.RAIDFlags =
MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ io_request->IoFlags |=
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
cmd->request_desc->SCSIIO.RequestFlags =
(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
cmd->request_desc->SCSIIO.DevHandle =
local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+ /*
+ * If the command is for the tape device, set the
+ * FP timeout to the os layer timeout value.
+ */
+ if (scmd->device->type == TYPE_TAPE) {
+ if ((scmd->request->timeout / HZ) > 0xFFFF)
+ io_request->RaidContext.timeoutValue =
+ 0xFFFF;
+ else
+ io_request->RaidContext.timeoutValue =
+ scmd->request->timeout / HZ;
+ }
} else {
io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
io_request->DevHandle = device_id;
@@ -1824,8 +1920,15 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
return IRQ_NONE;
wmb();
- writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex],
- &instance->reg_set->reply_post_host_index);
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+ writel(((MSIxIndex & 0x7) << 24) |
+ fusion->last_reply_idx[MSIxIndex],
+ instance->reply_post_host_index_addr[MSIxIndex/8]);
+ else
+ writel((MSIxIndex << 24) |
+ fusion->last_reply_idx[MSIxIndex],
+ instance->reply_post_host_index_addr[0]);
megasas_check_and_restore_queue_depth(instance);
return IRQ_HANDLED;
}
@@ -1867,6 +1970,9 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp)
struct megasas_instance *instance = irq_context->instance;
u32 mfiStatus, fw_state;
+ if (instance->mask_interrupts)
+ return IRQ_NONE;
+
if (!instance->msix_vectors) {
mfiStatus = instance->instancet->clear_intr(instance->reg_set);
if (!mfiStatus)
@@ -1928,7 +2034,8 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
fusion = instance->ctrl_context;
io_req = cmd->io_request;
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
(struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
@@ -2131,7 +2238,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
mutex_lock(&instance->reset_mutex);
set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
msleep(1000);
/* First try waiting for commands to complete */
@@ -2255,7 +2362,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
clear_bit(MEGASAS_FUSION_IN_RESET,
&instance->reset_flags);
- instance->instancet->enable_intr(instance->reg_set);
+ instance->instancet->enable_intr(instance);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
/* Re-fire management commands */
@@ -2317,7 +2424,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
retval = FAILED;
} else {
clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
- instance->instancet->enable_intr(instance->reg_set);
+ instance->instancet->enable_intr(instance);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
}
out:
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index a7c64f0..12ff01c 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -43,7 +43,7 @@
#define HOST_DIAG_WRITE_ENABLE 0x80
#define HOST_DIAG_RESET_ADAPTER 0x4
#define MEGASAS_FUSION_MAX_RESET_TRIES 3
-#define MAX_MSIX_QUEUES_FUSION 16
+#define MAX_MSIX_QUEUES_FUSION 128
/* Invader defines */
#define MPI2_TYPE_CUDA 0x2
@@ -61,7 +61,9 @@
#define MEGASAS_SCSI_ADDL_CDB_LEN 0x18
#define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20
#define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60
-#define MEGASAS_EEDPBLOCKSIZE 512
+
+#define MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C)
+#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
/*
* Raid context flags
@@ -461,6 +463,7 @@ struct MPI2_IOC_INIT_REQUEST {
/* mrpriv defines */
#define MR_PD_INVALID 0xFFFF
#define MAX_SPAN_DEPTH 8
+#define MAX_QUAD_DEPTH MAX_SPAN_DEPTH
#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
#define MAX_ROW_SIZE 32
#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
@@ -502,7 +505,9 @@ struct MR_LD_SPAN {
u64 startBlk;
u64 numBlks;
u16 arrayRef;
- u8 reserved[6];
+ u8 spanRowSize;
+ u8 spanRowDataSize;
+ u8 reserved[4];
};
struct MR_SPAN_BLOCK_INFO {
@@ -588,6 +593,10 @@ struct IO_REQUEST_INFO {
u16 devHandle;
u64 pdBlock;
u8 fpOkForIo;
+ u8 IoforUnevenSpan;
+ u8 start_span;
+ u8 reserved;
+ u64 start_row;
};
struct MR_LD_TARGET_SYNC {
@@ -649,6 +658,26 @@ struct LD_LOAD_BALANCE_INFO {
u64 last_accessed_block[2];
};
+/* SPAN_SET is info caclulated from span info from Raid map per LD */
+typedef struct _LD_SPAN_SET {
+ u64 log_start_lba;
+ u64 log_end_lba;
+ u64 span_row_start;
+ u64 span_row_end;
+ u64 data_strip_start;
+ u64 data_strip_end;
+ u64 data_row_start;
+ u64 data_row_end;
+ u8 strip_offset[MAX_SPAN_DEPTH];
+ u32 span_row_data_width;
+ u32 diff;
+ u32 reserved[2];
+} LD_SPAN_SET, *PLD_SPAN_SET;
+
+typedef struct LOG_BLOCK_SPAN_INFO {
+ LD_SPAN_SET span_set[MAX_SPAN_DEPTH];
+} LD_SPAN_INFO, *PLD_SPAN_INFO;
+
struct MR_FW_RAID_MAP_ALL {
struct MR_FW_RAID_MAP raidMap;
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
@@ -693,6 +722,7 @@ struct fusion_context {
u32 map_sz;
u8 fast_path_io;
struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
+ LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES];
};
union desc_value {
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index e960f96..31b5b15 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.25
+ * mpi2.h Version: 02.00.27
*
* Version History
* ---------------
@@ -75,6 +75,8 @@
* 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.
* --------------------------------------------------------------------------
*/
@@ -100,7 +102,7 @@
#define MPI2_VERSION_02_00 (0x0200)
/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x19)
+#define MPI2_HEADER_VERSION_UNIT (0x1B)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index 38c5da3..963761f 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -6,7 +6,7 @@
* Title: MPI SCSI initiator mode messages and structures
* Creation Date: June 23, 2006
*
- * mpi2_init.h Version: 02.00.13
+ * mpi2_init.h Version: 02.00.14
*
* Version History
* ---------------
@@ -36,6 +36,7 @@
* 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
* 02-06-12 02.00.13 Added alternate defines for Task Priority / Command
* Priority to match SAM-4.
+ * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION.
* --------------------------------------------------------------------------
*/
@@ -189,6 +190,7 @@ typedef struct _MPI2_SCSI_IO_REQUEST
#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)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index b0d4760..e93f8f5 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -6,7 +6,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
- * mpi2_ioc.h Version: 02.00.21
+ * mpi2_ioc.h Version: 02.00.22
*
* Version History
* ---------------
@@ -118,6 +118,9 @@
* MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure.
* Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete.
* 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.
* --------------------------------------------------------------------------
*/
@@ -284,6 +287,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY
#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)
@@ -624,7 +628,7 @@ typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS
U8 RAIDOperation; /* 0x04 */
U8 PercentComplete; /* 0x05 */
U16 Reserved2; /* 0x06 */
- U32 Resereved3; /* 0x08 */
+ U32 ElapsedSeconds; /* 0x08 */
} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
Mpi2EventDataIrOperationStatus_t,
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
index 2b38af2..255b0ca 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
@@ -6,7 +6,7 @@
* Title: MPI Integrated RAID messages and structures
* Creation Date: April 26, 2007
*
- * mpi2_raid.h Version: 02.00.08
+ * mpi2_raid.h Version: 02.00.09
*
* Version History
* ---------------
@@ -27,6 +27,8 @@
* related structures and defines.
* Added product-specific range to RAID Action values.
* 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.
* --------------------------------------------------------------------------
*/
@@ -276,10 +278,13 @@ typedef struct _MPI2_RAID_VOL_INDICATOR
U64 TotalBlocks; /* 0x00 */
U64 BlocksRemaining; /* 0x08 */
U32 Flags; /* 0x10 */
+ U32 ElapsedSeconds; /* 0x14 */
} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
Mpi2RaidVolIndicator_t, MPI2_POINTER 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)
@@ -320,7 +325,7 @@ MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t;
/* RAID Action Reply ActionData union */
typedef union _MPI2_RAID_ACTION_REPLY_DATA
{
- U32 Word[5];
+ U32 Word[6];
MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
U16 VolDevHandle;
U8 VolumeState;
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
index 3cbe677..67c387f 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2010 LSI Corporation.
+ * 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.07
+ * mpi2_tool.h Version: 02.00.10
*
* Version History
* ---------------
@@ -27,6 +27,8 @@
* Post Request.
* 05-25-11 02.00.07 Added Flags field and related defines to
* MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST.
+ * 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.
* --------------------------------------------------------------------------
*/
@@ -270,7 +272,7 @@ typedef struct _MPI2_TOOLBOX_BEACON_REQUEST
#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C)
-/* Toolbox Diagnostic CLI Tool request message */
+/* MPI v2.0 Toolbox Diagnostic CLI Tool request message */
typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
U8 Tool; /* 0x00 */
U8 Reserved1; /* 0x01 */
@@ -288,7 +290,7 @@ typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
U32 DataLength; /* 0x10 */
U8 DiagnosticCliCommand
[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH]; /* 0x14 */
- MPI2_SGE_SIMPLE_UNION SGL; /* 0x70 */
+ MPI2_MPI_SGE_IO_UNION SGL; /* 0x70 */
} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
Mpi2ToolboxDiagnosticCliRequest_t,
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index ffd85c5..ccd6d5a 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -80,10 +80,6 @@ static int msix_disable = -1;
module_param(msix_disable, int, 0);
MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
-static int missing_delay[2] = {-1, -1};
-module_param_array(missing_delay, int, NULL, 0);
-MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
-
static int mpt2sas_fwfault_debug;
MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
"and halt firmware - (default=0)");
@@ -155,7 +151,7 @@ _base_fault_reset_work(struct work_struct *work)
struct task_struct *p;
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery)
+ if (ioc->shost_recovery || ioc->pci_error_recovery)
goto rearm_timer;
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
@@ -164,6 +160,20 @@ _base_fault_reset_work(struct work_struct *work)
printk(MPT2SAS_INFO_FMT "%s : SAS host is non-operational !!!!\n",
ioc->name, __func__);
+ /* 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, mpt2sas 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
@@ -193,6 +203,8 @@ _base_fault_reset_work(struct work_struct *work)
return; /* don't rearm timer */
}
+ ioc->non_operational_loop = 0;
+
if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
@@ -2007,6 +2019,14 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
MPT2SAS_INTEL_RMS25KB040_BRANDING);
break;
+ case MPT2SAS_INTEL_RMS25LB040_SSDID:
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25LB040_BRANDING);
+ break;
+ case MPT2SAS_INTEL_RMS25LB080_SSDID:
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RMS25LB080_BRANDING);
+ break;
default:
break;
}
@@ -2175,7 +2195,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
}
/**
- * _base_update_missing_delay - change the missing delay timers
+ * mpt2sas_base_update_missing_delay - change the missing delay timers
* @ioc: per adapter object
* @device_missing_delay: amount of time till device is reported missing
* @io_missing_delay: interval IO is returned when there is a missing device
@@ -2186,8 +2206,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
* delay, as well as the io missing delay. This should be called at driver
* load time.
*/
-static void
-_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+void
+mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay)
{
u16 dmd, dmd_new, dmd_orignal;
@@ -2483,23 +2503,25 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
/* 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_free_queue_depth % 16)
- ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + 16;
- else
- ioc->reply_post_queue_depth = ioc->reply_free_queue_depth +
- 32 - (ioc->reply_free_queue_depth % 16);
+ 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 = min_t(u16,
- (facts->MaxReplyDescriptorPostQueueDepth -
- (facts->MaxReplyDescriptorPostQueueDepth % 16)),
- (ioc->hba_queue_depth - (ioc->hba_queue_depth % 16)));
- ioc->reply_free_queue_depth = ioc->reply_post_queue_depth - 16;
- ioc->hba_queue_depth = ioc->reply_free_queue_depth - 64;
+ 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, printk(MPT2SAS_INFO_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,
@@ -3916,11 +3938,15 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
&ioc->chip->HostDiagnostic);
- /* don't access any registers for 50 milliseconds */
- msleep(50);
+ /* 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);
- /* 300 second max wait */
- for (count = 0; count < 3000000 ; count++) {
+ /* 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);
@@ -3929,11 +3955,13 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
break;
- /* wait 100 msec */
+ /* Wait to pass the second read delay window */
if (sleep_flag == CAN_SLEEP)
- msleep(1);
+ msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
+ /1000);
else
- mdelay(1);
+ mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
+ /1000);
}
if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
@@ -4383,9 +4411,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
if (r)
goto out_free_resources;
- if (missing_delay[0] != -1 && missing_delay[1] != -1)
- _base_update_missing_delay(ioc, missing_delay[0],
- missing_delay[1]);
+ ioc->non_operational_loop = 0;
return 0;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 543d8d6..6fbd084 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,8 +69,8 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "14.100.00.00"
-#define MPT2SAS_MAJOR_VERSION 14
+#define MPT2SAS_DRIVER_VERSION "15.100.00.00"
+#define MPT2SAS_MAJOR_VERSION 15
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
#define MPT2SAS_RELEASE_VERSION 00
@@ -165,6 +165,10 @@
"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 \
@@ -180,6 +184,8 @@
#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
@@ -835,6 +841,7 @@ struct MPT2SAS_ADAPTER {
u16 cpu_msix_table_sz;
u32 ioc_reset_count;
MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
+ u32 non_operational_loop;
/* internal commands, callback index */
u8 scsi_io_cb_idx;
@@ -1048,6 +1055,9 @@ void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_ty
void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+ u16 device_missing_delay, u8 io_missing_delay);
+
int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
/* scsih shared API */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 08685c4..eec052c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -505,19 +505,6 @@ _ctl_fasync(int fd, struct file *filep, int mode)
}
/**
- * _ctl_release -
- * @inode -
- * @filep -
- *
- * Called when application releases the fasyn callback handler.
- */
-static int
-_ctl_release(struct inode *inode, struct file *filep)
-{
- return fasync_helper(-1, filep, 0, &async_queue);
-}
-
-/**
* _ctl_poll -
* @file -
* @wait -
@@ -3027,7 +3014,6 @@ struct device_attribute *mpt2sas_dev_attrs[] = {
static const struct file_operations ctl_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = _ctl_ioctl,
- .release = _ctl_release,
.poll = _ctl_poll,
.fasync = _ctl_fasync,
#ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index af4e6c4..5100476 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -101,6 +101,10 @@ 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 MPT2SAS_MAX_LUN (16895)
static int max_lun = MPT2SAS_MAX_LUN;
@@ -3994,11 +3998,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
else
mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
} else
-/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */
-/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED;
- */
- mpi_control |= (0x500);
-
+ mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
} else
mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
/* Make sure Device is not raid volume.
@@ -5815,9 +5815,10 @@ _scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc,
u8 task_abort_retries;
mutex_lock(&ioc->tm_cmds.mutex);
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
- "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
- event_data->PortWidth));
+ pr_info(MPT2SAS_FMT
+ "%s: enter: phy number(%d), width(%d)\n",
+ ioc->name, __func__, event_data->PhyNum,
+ event_data->PortWidth);
_scsih_block_io_all_device(ioc);
@@ -7093,12 +7094,15 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
struct _sas_device *sas_device;
struct _sas_node *expander_device;
static struct _raid_device *raid_device;
+ u8 retry_count;
unsigned long flags;
printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
_scsih_sas_host_refresh(ioc);
+ printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n",
+ ioc->name);
/* expanders */
handle = 0xFFFF;
while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
@@ -7107,6 +7111,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
handle = le16_to_cpu(expander_pg0.DevHandle);
spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_device = mpt2sas_scsih_expander_find_by_sas_address(
@@ -7115,13 +7126,26 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (expander_device)
_scsih_refresh_expander_links(ioc, expander_device,
handle);
- else
+ else {
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(expander_pg0.SASAddress));
_scsih_expander_add(ioc, handle);
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(expander_pg0.SASAddress));
+ }
}
+ printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n",
+ ioc->name);
+
if (!ioc->ir_firmware)
goto skip_to_sas;
+ printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name);
/* phys disk */
phys_disk_num = 0xFF;
while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
@@ -7131,6 +7155,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:"
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
@@ -7142,17 +7173,46 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
&sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
handle) != 0)
continue;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
if (!_scsih_get_sas_address(ioc, parent_handle,
&sas_address)) {
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: "
+ " handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
mpt2sas_transport_update_links(ioc, sas_address,
handle, sas_device_pg0.PhyNum,
MPI2_SAS_NEG_LINK_RATE_1_5);
set_bit(handle, ioc->pd_handles);
- _scsih_add_device(ioc, handle, 0, 1);
+ retry_count = 0;
+ /* This will retry adding the end device.
+ * _scsih_add_device() will decide on retries and
+ * return "1" when it should be retried
+ */
+ while (_scsih_add_device(ioc, handle, retry_count++,
+ 1)) {
+ ssleep(1);
+ }
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: "
+ " handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
}
}
+ printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n",
+ ioc->name);
+
+ printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name);
/* volumes */
handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
@@ -7161,6 +7221,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
handle = le16_to_cpu(volume_pg1.DevHandle);
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_wwid(ioc,
@@ -7172,18 +7239,38 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
&volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t)))
continue;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
element.VolDevHandle = volume_pg1.DevHandle;
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: "
+ " handle (0x%04x)\n", ioc->name,
+ volume_pg1.DevHandle);
_scsih_sas_volume_add(ioc, &element);
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: "
+ " handle (0x%04x)\n", ioc->name,
+ volume_pg1.DevHandle);
}
}
+ printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n",
+ ioc->name);
+
skip_to_sas:
+ printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n",
+ ioc->name);
/* sas devices */
handle = 0xFFFF;
while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
@@ -7193,6 +7280,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:"
+ " ioc_status(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, ioc_status,
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+ break;
+ }
handle = le16_to_cpu(sas_device_pg0.DevHandle);
if (!(_scsih_is_end_device(
le32_to_cpu(sas_device_pg0.DeviceInfo))))
@@ -7205,12 +7299,31 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
continue;
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
mpt2sas_transport_update_links(ioc, sas_address, handle,
sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
- _scsih_add_device(ioc, handle, 0, 0);
+ retry_count = 0;
+ /* This will retry adding the end device.
+ * _scsih_add_device() will decide on retries and
+ * return "1" when it should be retried
+ */
+ while (_scsih_add_device(ioc, handle, retry_count++,
+ 0)) {
+ ssleep(1);
+ }
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: "
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
+ ioc->name, handle, (unsigned long long)
+ le64_to_cpu(sas_device_pg0.SASAddress));
}
}
+ printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n",
+ ioc->name);
+
printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
}
@@ -7303,7 +7416,9 @@ _firmware_event_work(struct work_struct *work)
case MPT2SAS_PORT_ENABLE_COMPLETE:
ioc->start_scan = 0;
-
+ if (missing_delay[0] != -1 && missing_delay[1] != -1)
+ mpt2sas_base_update_missing_delay(ioc, missing_delay[0],
+ missing_delay[1]);
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
"from worker thread\n", ioc->name));
@@ -7686,7 +7801,7 @@ _scsih_shutdown(struct pci_dev *pdev)
* Routine called when unloading the driver.
* Return nothing.
*/
-static void __devexit
+static void
_scsih_remove(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -8070,8 +8185,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (max_sectors != 0xFFFF) {
if (max_sectors < 64) {
shost->max_sectors = 64;
- printk(MPT2SAS_WARN_FMT "Invalid value %d passed "\
- "for max_sectors, range is 64 to 32767. Assigning "\
+ printk(MPT2SAS_WARN_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;
@@ -8338,7 +8453,7 @@ static struct pci_driver scsih_driver = {
.name = MPT2SAS_DRIVER_NAME,
.id_table = scsih_pci_table,
.probe = _scsih_probe,
- .remove = __devexit_p(_scsih_remove),
+ .remove = _scsih_remove,
.shutdown = _scsih_shutdown,
.err_handler = &_scsih_err_handler,
#ifdef CONFIG_PM
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index 8c2ffbe..193e7ae 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -1939,7 +1939,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
ioc->transport_cmds.status = MPT2_CMD_PENDING;
/* Check if the request is split across multiple segments */
- if (req->bio->bi_vcnt > 1) {
+ if (bio_segments(req->bio) > 1) {
u32 offset = 0;
/* Allocate memory and copy the request */
@@ -1971,7 +1971,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
/* Check if the response needs to be populated across
* multiple segments */
- if (rsp->bio->bi_vcnt > 1) {
+ if (bio_segments(rsp->bio) > 1) {
pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
&pci_dma_in);
if (!pci_addr_in) {
@@ -2038,7 +2038,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
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;
- if (req->bio->bi_vcnt > 1) {
+ if (bio_segments(req->bio) > 1) {
ioc->base_add_sg_single(psge, sgl_flags |
(blk_rq_bytes(req) - 4), pci_dma_out);
} else {
@@ -2054,7 +2054,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
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;
- if (rsp->bio->bi_vcnt > 1) {
+ if (bio_segments(rsp->bio) > 1) {
ioc->base_add_sg_single(psge, sgl_flags |
(blk_rq_bytes(rsp) + 4), pci_dma_in);
} else {
@@ -2099,7 +2099,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
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) {
+ if (bio_segments(rsp->bio) > 1) {
u32 offset = 0;
u32 bytes_to_copy =
le16_to_cpu(mpi_reply->ResponseDataLength);
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig
index 81471bf..d53e1b0 100644
--- a/drivers/scsi/mpt3sas/Kconfig
+++ b/drivers/scsi/mpt3sas/Kconfig
@@ -2,7 +2,7 @@
# Kernel configuration file for the MPT3SAS
#
# This code is based on drivers/scsi/mpt3sas/Kconfig
-# Copyright (C) 2012 LSI Corporation
+# Copyright (C) 2012-2013 LSI Corporation
# (mailto:DL-MPTFusionLinux@lsi.com)
# This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
index 03317ff..20da8f9 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
*
*
* Name: mpi2.h
@@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.26
+ * mpi2.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
@@ -82,6 +82,10 @@
* 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.
* --------------------------------------------------------------------------
*/
@@ -115,7 +119,7 @@
#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_UNIT (0x1D)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -274,6 +278,8 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
#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
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index d8b2c3e..889aa70 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
*
*
* Name: mpi2_cnfg.h
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.22
+ * mpi2_cnfg.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
@@ -155,6 +155,11 @@
* 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.
* --------------------------------------------------------------------------
*/
@@ -714,6 +719,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
#define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
/*defines for the Flags field */
+#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002)
#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
@@ -1310,6 +1316,9 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 {
#define MPI2_BIOSPAGE1_PAGEVERSION (0x05)
/*values for BIOS Page 1 BiosOptions field */
+#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)
@@ -1884,6 +1893,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
#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)
@@ -1897,6 +1907,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
#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)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_init.h b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
index a079e52..f7928bf 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
*
*
* Name: mpi2_init.h
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
index 0de425d..e2bb821 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 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
+ * mpi2_ioc.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
@@ -124,6 +124,9 @@
* 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.
* --------------------------------------------------------------------------
*/
@@ -283,6 +286,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
#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)
@@ -634,7 +638,7 @@ typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS {
U8 RAIDOperation; /*0x04 */
U8 PercentComplete; /*0x05 */
U16 Reserved2; /*0x06 */
- U32 Resereved3; /*0x08 */
+ U32 ElapsedSeconds; /*0x08 */
} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
*PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
Mpi2EventDataIrOperationStatus_t,
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_raid.h b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h
index d1d9866..7176523 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_raid.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 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
+ * mpi2_raid.h Version: 02.00.09
*
* Version History
* ---------------
@@ -28,6 +28,8 @@
* 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.
* --------------------------------------------------------------------------
*/
@@ -269,10 +271,12 @@ 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)
@@ -312,7 +316,7 @@ typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT {
/*RAID Action Reply ActionData union */
typedef union _MPI2_RAID_ACTION_REPLY_DATA {
- U32 Word[5];
+ U32 Word[6];
MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
U16 VolDevHandle;
U8 VolumeState;
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_sas.h b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h
index b4e7084a..cba046f 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_sas.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
*
*
* Name: mpi2_sas.h
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
index 71453d1..34e9a7b 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 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
+ * mpi2_tool.h Version: 02.00.10
*
* Version History
* ---------------
@@ -30,6 +30,8 @@
* 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.
* --------------------------------------------------------------------------
*/
@@ -279,7 +281,7 @@ typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
U16 Reserved6; /*0x0E */
U32 DataLength; /*0x10 */
U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */
- MPI2_SGE_SIMPLE_UNION SGL; /*0x70 */
+ MPI2_MPI_SGE_IO_UNION SGL; /*0x70 */
} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
*PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
Mpi2ToolboxDiagnosticCliRequest_t,
@@ -302,7 +304,7 @@ typedef struct _MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
U32 Reserved5; /*0x0C */
U32 DataLength; /*0x10 */
U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */
- MPI25_SGE_IO_UNION SGL; /*0x70 */
+ MPI25_SGE_IO_UNION SGL; /* 0x70 */
} MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
*PTR_MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
Mpi25ToolboxDiagnosticCliRequest_t,
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_type.h b/drivers/scsi/mpt3sas/mpi/mpi2_type.h
index 516f959..ba1fed5 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_type.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_type.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2007 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
*
*
* Name: mpi2_type.h
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 04f8010..5dc280c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -3,7 +3,7 @@
* for access to MPT (Message Passing Technology) firmware.
*
* This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
- * Copyright (C) 2012 LSI Corporation
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -1310,7 +1309,6 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
void *sg_local, *chain;
u32 chain_offset;
u32 chain_length;
- u32 chain_flags;
int sges_left;
u32 sges_in_segment;
u8 simple_sgl_flags;
@@ -1356,8 +1354,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
sges_in_segment--;
}
- /* initializing the chain flags and pointers */
- chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
+ /* initializing the pointers */
chain_req = _base_get_chain_buffer_tracker(ioc, smid);
if (!chain_req)
return -1;
@@ -4093,11 +4090,15 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
&ioc->chip->HostDiagnostic);
- /* don't access any registers for 50 milliseconds */
- msleep(50);
+ /*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);
- /* 300 second max wait */
- for (count = 0; count < 3000000 ; count++) {
+ /* 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);
@@ -4106,11 +4107,13 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
break;
- /* wait 1 msec */
+ /* Wait to pass the second read delay window */
if (sleep_flag == CAN_SLEEP)
- usleep_range(1000, 1500);
+ msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
+ / 1000);
else
- mdelay(1);
+ mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
+ / 1000);
}
if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 994656c..0ebf5d9 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -3,7 +3,7 @@
* for access to MPT (Message Passing Technology) firmware.
*
* This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
- * Copyright (C) 2012 LSI Corporation
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
@@ -70,10 +70,10 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#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_DRIVER_VERSION "02.100.00.00"
+#define MPT3SAS_MAJOR_VERSION 2
#define MPT3SAS_MINOR_VERSION 100
-#define MPT3SAS_BUILD_VERSION 1
+#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
/*
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
index ce7e59b..936ec03 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -2,7 +2,7 @@
* 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
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
@@ -41,7 +41,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -149,7 +148,7 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
desc = "raid_config";
break;
case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
- desc = "driver_mappping";
+ desc = "driver_mapping";
break;
}
break;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 8af944d..9b89de1 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -3,7 +3,7 @@
* controllers
*
* This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c
- * Copyright (C) 2012 LSI Corporation
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -504,19 +503,6 @@ _ctl_fasync(int fd, struct file *filep, int mode)
}
/**
- * _ctl_release -
- * @inode -
- * @filep -
- *
- * Called when application releases the fasyn callback handler.
- */
-static int
-_ctl_release(struct inode *inode, struct file *filep)
-{
- return fasync_helper(-1, filep, 0, &async_queue);
-}
-
-/**
* _ctl_poll -
* @file -
* @wait -
@@ -3136,7 +3122,7 @@ _ctl_diag_trigger_mpi_store(struct device *cdev,
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(struct SL_WH_EVENT_TRIGGERS_T));
+ 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;
@@ -3234,7 +3220,6 @@ struct device_attribute *mpt3sas_dev_attrs[] = {
static const struct file_operations ctl_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = _ctl_ioctl,
- .release = _ctl_release,
.poll = _ctl_poll,
.fasync = _ctl_fasync,
#ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
index bd89f4f..53b0c48 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
@@ -3,7 +3,7 @@
* controllers
*
* This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.h
- * Copyright (C) 2012 LSI Corporation
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/mpt3sas/mpt3sas_debug.h b/drivers/scsi/mpt3sas/mpt3sas_debug.h
index 35405e7..545b22d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_debug.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_debug.h
@@ -2,7 +2,7 @@
* 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
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 05f8045..8cbe8fd 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2,7 +2,7 @@
* 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
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
@@ -41,7 +41,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -676,11 +675,12 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
* 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)
+ 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_remove(ioc, sas_device);
+ }
}
}
@@ -1274,6 +1274,7 @@ _scsih_slave_alloc(struct scsi_device *sdev)
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);
@@ -1302,6 +1303,19 @@ _scsih_slave_alloc(struct scsi_device *sdev)
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;
}
@@ -2755,13 +2769,11 @@ _scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc,
int i;
u16 handle;
u16 reason_code;
- u8 phy_number;
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;
if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
@@ -6395,7 +6407,7 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
handle = le16_to_cpu(sas_device_pg0.DevHandle);
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
@@ -6497,7 +6509,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
&volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
handle = le16_to_cpu(volume_pg1.DevHandle);
@@ -6521,7 +6533,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
phys_disk_num))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
@@ -6600,7 +6612,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
handle = le16_to_cpu(expander_pg0.DevHandle);
@@ -6745,8 +6757,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
"ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -6790,8 +6800,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
phys_disk_num))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
"ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -6857,8 +6865,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
&volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
"ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -6917,8 +6923,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
- if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
- break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
" ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -7374,8 +7378,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
* Routine called when unloading the driver.
* Return nothing.
*/
-static void __devexit
-_scsih_remove(struct pci_dev *pdev)
+static void _scsih_remove(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7529,10 +7532,12 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
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,
+ if (!ioc->is_driver_loading) {
+ mpt3sas_transport_port_remove(ioc,
+ sas_address,
sas_address_parent);
- _scsih_sas_device_remove(ioc, sas_device);
+ _scsih_sas_device_remove(ioc, sas_device);
+ }
}
}
}
@@ -7588,13 +7593,14 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
* oops in scsi_sysfs_add_sdev()->add_device()->
* sysfs_addrm_start()
*/
- if (!ioc->is_driver_loading)
+ 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;
+ list_del(&sas_device->list);
+ kfree(sas_device);
+ continue;
+ }
}
spin_lock_irqsave(&ioc->sas_device_lock, flags);
@@ -8044,7 +8050,7 @@ static struct pci_driver scsih_driver = {
.name = MPT3SAS_DRIVER_NAME,
.id_table = scsih_pci_table,
.probe = _scsih_probe,
- .remove = __devexit_p(_scsih_remove),
+ .remove = _scsih_remove,
.shutdown = _scsih_shutdown,
.err_handler = &_scsih_err_handler,
#ifdef CONFIG_PM
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 87ca2b7..dcadd56 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -2,7 +2,7 @@
* 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
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
index da6c5f2..f6533ab 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
@@ -3,7 +3,7 @@
* (Message Passing Technology) based controllers
*
* This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
- * Copyright (C) 2012 LSI Corporation
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
index a10c309..bb69392 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
@@ -4,7 +4,7 @@
* controllers
*
* This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
- * Copyright (C) 2012 LSI Corporation
+ * Copyright (C) 2012-2013 LSI Corporation
* (mailto:DL-MPTFusionLinux@lsi.com)
*
* This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index c29d0db..e7f6661 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -76,7 +76,8 @@ int mvme147_detect(struct scsi_host_template *tpnt)
called++;
tpnt->proc_name = "MVME147";
- tpnt->proc_info = &wd33c93_proc_info;
+ tpnt->show_info = wd33c93_show_info,
+ tpnt->write_info = wd33c93_write_info,
instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
if (!instance)
diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c
index 39f554f..8fbb97a8 100644
--- a/drivers/scsi/mvme16x_scsi.c
+++ b/drivers/scsi/mvme16x_scsi.c
@@ -34,8 +34,7 @@ static struct scsi_host_template mvme16x_scsi_driver_template = {
static struct platform_device *mvme16x_scsi_device;
-static __devinit int
-mvme16x_probe(struct platform_device *dev)
+static int mvme16x_probe(struct platform_device *dev)
{
struct Scsi_Host * host = NULL;
struct NCR_700_Host_Parameters *hostdata;
@@ -103,8 +102,7 @@ mvme16x_probe(struct platform_device *dev)
return -ENODEV;
}
-static __devexit int
-mvme16x_device_remove(struct platform_device *dev)
+static int mvme16x_device_remove(struct platform_device *dev)
{
struct Scsi_Host *host = platform_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
@@ -131,7 +129,7 @@ static struct platform_driver mvme16x_scsi_driver = {
.owner = THIS_MODULE,
},
.probe = mvme16x_probe,
- .remove = __devexit_p(mvme16x_device_remove),
+ .remove = mvme16x_device_remove,
};
static int __init mvme16x_scsi_init(void)
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c
index 8ba4722..8bb0699 100644
--- a/drivers/scsi/mvsas/mv_64xx.c
+++ b/drivers/scsi/mvsas/mv_64xx.c
@@ -41,7 +41,7 @@ static void mvs_64xx_detect_porttype(struct mvs_info *mvi, int i)
phy->phy_type |= PORT_TYPE_SATA;
}
-static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
+static void mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
{
void __iomem *regs = mvi->regs;
u32 tmp;
@@ -54,7 +54,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
mw32(MVS_PCS, tmp);
}
-static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
+static void mvs_64xx_phy_hacks(struct mvs_info *mvi)
{
void __iomem *regs = mvi->regs;
int i;
@@ -156,7 +156,7 @@ void mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
}
}
-static int __devinit mvs_64xx_chip_reset(struct mvs_info *mvi)
+static int mvs_64xx_chip_reset(struct mvs_info *mvi)
{
void __iomem *regs = mvi->regs;
u32 tmp;
@@ -250,7 +250,7 @@ static void mvs_64xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
}
}
-static int __devinit mvs_64xx_init(struct mvs_info *mvi)
+static int mvs_64xx_init(struct mvs_info *mvi)
{
void __iomem *regs = mvi->regs;
int i;
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 7e423e5..1e4479f 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -216,8 +216,7 @@ void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
mvs_write_port_vsr_data(mvi, phy_id, phy_cfg.v);
}
-static void __devinit
-mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
+static void mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
{
u32 temp;
temp = (u32)(*(u32 *)&mvi->hba_info_param.phy_tuning[phy_id]);
@@ -258,7 +257,7 @@ mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
mvi->hba_info_param.phy_rate[phy_id]);
}
-static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
+static void mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
{
void __iomem *regs = mvi->regs;
u32 tmp;
@@ -331,7 +330,7 @@ static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff);
}
-static int __devinit mvs_94xx_init(struct mvs_info *mvi)
+static int mvs_94xx_init(struct mvs_info *mvi)
{
void __iomem *regs = mvi->regs;
int i;
diff --git a/drivers/scsi/mvsas/mv_chips.h b/drivers/scsi/mvsas/mv_chips.h
index bcc4080..8c4479a 100644
--- a/drivers/scsi/mvsas/mv_chips.h
+++ b/drivers/scsi/mvsas/mv_chips.h
@@ -160,7 +160,7 @@ static inline void mvs_write_port_irq_mask(struct mvs_info *mvi,
MVS_P4_INT_MASK, port, val);
}
-static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
+static inline void mvs_phy_hacks(struct mvs_info *mvi)
{
u32 tmp;
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index cc59dff..7b7381d 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -96,7 +96,7 @@ static struct sas_domain_function_template mvs_transport_ops = {
};
-static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
+static void mvs_phy_init(struct mvs_info *mvi, int phy_id)
{
struct mvs_phy *phy = &mvi->phy[phy_id];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -235,7 +235,7 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
return IRQ_HANDLED;
}
-static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
+static int mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
{
int i = 0, slot_nr;
char pool_name[32];
@@ -254,7 +254,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
}
for (i = 0; i < MVS_MAX_DEVICES; i++) {
mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED;
- mvi->devices[i].dev_type = NO_DEVICE;
+ mvi->devices[i].dev_type = SAS_PHY_UNUSED;
mvi->devices[i].device_id = i;
mvi->devices[i].dev_status = MVS_DEV_NORMAL;
init_timer(&mvi->devices[i].timer);
@@ -373,7 +373,7 @@ void mvs_iounmap(void __iomem *regs)
iounmap(regs);
}
-static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
+static struct mvs_info *mvs_pci_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent,
struct Scsi_Host *shost, unsigned int id)
{
@@ -444,7 +444,7 @@ static int pci_go_64(struct pci_dev *pdev)
return rc;
}
-static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
+static int mvs_prep_sas_ha_init(struct Scsi_Host *shost,
const struct mvs_chip_info *chip_info)
{
int phy_nr, port_nr; unsigned short core_nr;
@@ -486,7 +486,7 @@ exit_free:
}
-static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
+static void mvs_post_sas_ha_init(struct Scsi_Host *shost,
const struct mvs_chip_info *chip_info)
{
int can_queue, i = 0, j = 0;
@@ -537,8 +537,7 @@ static void mvs_init_sas_add(struct mvs_info *mvi)
memcpy(mvi->sas_addr, &mvi->phy[0].dev_sas_addr, SAS_ADDR_SIZE);
}
-static int __devinit mvs_pci_init(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int mvs_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned int rc, nhost = 0;
struct mvs_info *mvi;
@@ -645,7 +644,7 @@ err_out_enable:
return rc;
}
-static void __devexit mvs_pci_remove(struct pci_dev *pdev)
+static void mvs_pci_remove(struct pci_dev *pdev)
{
unsigned short core_nr, i = 0;
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
@@ -677,7 +676,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
return;
}
-static struct pci_device_id __devinitdata mvs_pci_table[] = {
+static struct pci_device_id mvs_pci_table[] = {
{ PCI_VDEVICE(MARVELL, 0x6320), chip_6320 },
{ PCI_VDEVICE(MARVELL, 0x6340), chip_6440 },
{
@@ -704,7 +703,7 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
{ PCI_VDEVICE(TTI, 0x2744), chip_9480 },
{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
{
- .vendor = 0x1b4b,
+ .vendor = PCI_VENDOR_ID_MARVELL_EXT,
.device = 0x9480,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
@@ -713,7 +712,7 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
.driver_data = chip_9480,
},
{
- .vendor = 0x1b4b,
+ .vendor = PCI_VENDOR_ID_MARVELL_EXT,
.device = 0x9445,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
@@ -722,7 +721,7 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
.driver_data = chip_9445,
},
{
- .vendor = 0x1b4b,
+ .vendor = PCI_VENDOR_ID_MARVELL_EXT,
.device = 0x9485,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
@@ -748,7 +747,7 @@ static struct pci_driver mvs_pci_driver = {
.name = DRV_NAME,
.id_table = mvs_pci_table,
.probe = mvs_pci_init,
- .remove = __devexit_p(mvs_pci_remove),
+ .remove = mvs_pci_remove,
};
static ssize_t
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index a3776d6..f14665a 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -220,8 +220,8 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
return rc;
}
-void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
- u32 off_lo, u32 off_hi, u64 sas_addr)
+void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
+ u32 off_hi, u64 sas_addr)
{
u32 lo = (u32)sas_addr;
u32 hi = (u32)(sas_addr>>32);
@@ -316,10 +316,13 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
struct mvs_task_exec_info *tei)
{
int elem, rc, i;
+ struct sas_ha_struct *sha = mvi->sas;
struct sas_task *task = tei->task;
struct mvs_cmd_hdr *hdr = tei->hdr;
struct domain_device *dev = task->dev;
struct asd_sas_port *sas_port = dev->port;
+ struct sas_phy *sphy = dev->phy;
+ struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number];
struct scatterlist *sg_req, *sg_resp;
u32 req_len, resp_len, tag = tei->tag;
void *buf_tmp;
@@ -392,7 +395,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
slot->tx = mvi->tx_prod;
mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) |
TXQ_MODE_I | tag |
- (sas_port->phy_mask << TXQ_PHY_SHIFT));
+ (MVS_PHY_ID << TXQ_PHY_SHIFT));
hdr->flags |= flags;
hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4));
@@ -438,11 +441,14 @@ static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
static int mvs_task_prep_ata(struct mvs_info *mvi,
struct mvs_task_exec_info *tei)
{
+ struct sas_ha_struct *sha = mvi->sas;
struct sas_task *task = tei->task;
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_cmd_hdr *hdr = tei->hdr;
struct asd_sas_port *sas_port = dev->port;
+ struct sas_phy *sphy = dev->phy;
+ struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number];
struct mvs_slot_info *slot;
void *buf_prd;
u32 tag = tei->tag, hdr_tag;
@@ -462,7 +468,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
slot->tx = mvi->tx_prod;
del_q = TXQ_MODE_I | tag |
(TXQ_CMD_STP << TXQ_CMD_SHIFT) |
- (sas_port->phy_mask << TXQ_PHY_SHIFT) |
+ (MVS_PHY_ID << TXQ_PHY_SHIFT) |
(mvi_dev->taskfileset << TXQ_SRS_SHIFT);
mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
@@ -680,7 +686,8 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
if (ssp_hdr->frame_type != SSP_TASK) {
buf_cmd[9] = fburst | task->ssp_task.task_attr |
(task->ssp_task.task_prio << 3);
- memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16);
+ memcpy(buf_cmd + 12, task->ssp_task.cmd->cmnd,
+ task->ssp_task.cmd->cmd_len);
} else{
buf_cmd[10] = tmf->tmf;
switch (tmf->tmf) {
@@ -700,7 +707,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
return 0;
}
-#define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE)))
+#define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == SAS_PHY_UNUSED)))
static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf,
struct mvs_tmf_task *tmf, int *pass)
{
@@ -720,7 +727,7 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf
* libsas will use dev->port, should
* not call task_done for sata
*/
- if (dev->dev_type != SATA_DEV)
+ if (dev->dev_type != SAS_SATA_DEV)
task->task_done(task);
return rc;
}
@@ -1153,10 +1160,10 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
phy->identify.device_type =
phy->att_dev_info & PORT_DEV_TYPE_MASK;
- if (phy->identify.device_type == SAS_END_DEV)
+ if (phy->identify.device_type == SAS_END_DEVICE)
phy->identify.target_port_protocols =
SAS_PROTOCOL_SSP;
- else if (phy->identify.device_type != NO_DEVICE)
+ else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols =
SAS_PROTOCOL_SMP;
if (oob_done)
@@ -1254,7 +1261,7 @@ struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi)
{
u32 dev;
for (dev = 0; dev < MVS_MAX_DEVICES; dev++) {
- if (mvi->devices[dev].dev_type == NO_DEVICE) {
+ if (mvi->devices[dev].dev_type == SAS_PHY_UNUSED) {
mvi->devices[dev].device_id = dev;
return &mvi->devices[dev];
}
@@ -1272,7 +1279,7 @@ void mvs_free_dev(struct mvs_device *mvi_dev)
u32 id = mvi_dev->device_id;
memset(mvi_dev, 0, sizeof(*mvi_dev));
mvi_dev->device_id = id;
- mvi_dev->dev_type = NO_DEVICE;
+ mvi_dev->dev_type = SAS_PHY_UNUSED;
mvi_dev->dev_status = MVS_DEV_NORMAL;
mvi_dev->taskfileset = MVS_ID_NOT_MAPPED;
}
@@ -1474,7 +1481,7 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
{
int rc;
struct sas_phy *phy = sas_get_local_phy(dev);
- int reset_type = (dev->dev_type == SATA_DEV ||
+ int reset_type = (dev->dev_type == SAS_SATA_DEV ||
(dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
rc = sas_phy_reset(phy, reset_type);
sas_put_local_phy(phy);
@@ -1623,7 +1630,7 @@ int mvs_abort_task(struct sas_task *task)
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
- if (SATA_DEV == dev->dev_type) {
+ if (SAS_SATA_DEV == dev->dev_type) {
struct mvs_slot_info *slot = task->lldd_task;
u32 slot_idx = (u32)(slot - mvi->slot_info);
mv_dprintk("mvs_abort_task() mvi=%p task=%p "
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index da24955..60e2fb7 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -67,7 +67,7 @@ extern const struct mvs_dispatch mvs_94xx_dispatch;
extern struct kmem_cache *mvs_task_list_cache;
#define DEV_IS_EXPANDER(type) \
- ((type == EDGE_DEV) || (type == FANOUT_DEV))
+ ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
#define bit(n) ((u64)1 << n)
@@ -76,6 +76,7 @@ extern struct kmem_cache *mvs_task_list_cache;
(__mc) != 0 ; \
(++__lseq), (__mc) >>= 1)
+#define MVS_PHY_ID (1U << sas_phy->id)
#define MV_INIT_DELAYED_WORK(w, f, d) INIT_DELAYED_WORK(w, f)
#define UNASSOC_D2H_FIS(id) \
((void *) mvi->rx_fis + 0x100 * id)
@@ -240,7 +241,7 @@ struct mvs_phy {
struct mvs_device {
struct list_head dev_entry;
- enum sas_dev_type dev_type;
+ enum sas_device_type dev_type;
struct mvs_info *mvi_info;
struct domain_device *sas_device;
struct timer_list timer;
@@ -456,8 +457,8 @@ int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex);
void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard);
int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
-void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
- u32 off_lo, u32 off_hi, u64 sas_addr);
+void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
+ u32 off_hi, u64 sas_addr);
void mvs_scan_start(struct Scsi_Host *shost);
int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
int mvs_queue_command(struct sas_task *task, const int num,
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index c585a92..c3601b5 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -49,8 +49,8 @@ MODULE_AUTHOR("jyli@marvell.com");
MODULE_DESCRIPTION("Marvell UMI Driver");
static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) },
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9580) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) },
{ 0 }
};
@@ -2506,8 +2506,7 @@ fail_add_device:
* @pdev: PCI device structure
* @id: PCI ids of supported hotplugged adapter
*/
-static int __devinit mvumi_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int mvumi_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct Scsi_Host *host;
struct mvumi_hba *mhba;
@@ -2728,7 +2727,7 @@ static struct pci_driver mvumi_pci_driver = {
.name = MV_DRIVER_NAME,
.id_table = mvumi_pci_table,
.probe = mvumi_probe_one,
- .remove = __devexit_p(mvumi_detach_one),
+ .remove = mvumi_detach_one,
.shutdown = mvumi_shutdown,
#ifdef CONFIG_PM
.suspend = mvumi_suspend,
diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h
index e360135..41f1687 100644
--- a/drivers/scsi/mvumi.h
+++ b/drivers/scsi/mvumi.h
@@ -32,7 +32,6 @@
#define VER_BUILD 1500
#define MV_DRIVER_NAME "mvumi"
-#define PCI_VENDOR_ID_MARVELL_2 0x1b4b
#define PCI_DEVICE_ID_MARVELL_MV9143 0x9143
#define PCI_DEVICE_ID_MARVELL_MV9580 0x9580
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 62b6168..0665f9c 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -76,7 +76,7 @@ static const char *nsp32_release_version = "1.2";
/****************************************************************************
* Supported hardware
*/
-static struct pci_device_id nsp32_pci_table[] __devinitdata = {
+static struct pci_device_id nsp32_pci_table[] = {
{
.vendor = PCI_VENDOR_ID_IODATA,
.device = PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II,
@@ -186,13 +186,13 @@ static nsp32_sync_table nsp32_sync_table_pci[] = {
* function declaration
*/
/* module entry point */
-static int __devinit nsp32_probe (struct pci_dev *, const struct pci_device_id *);
-static void __devexit nsp32_remove(struct pci_dev *);
-static int __init init_nsp32 (void);
-static void __exit exit_nsp32 (void);
+static int nsp32_probe (struct pci_dev *, const struct pci_device_id *);
+static void nsp32_remove(struct pci_dev *);
+static int __init init_nsp32 (void);
+static void __exit exit_nsp32 (void);
/* struct struct scsi_host_template */
-static int nsp32_proc_info (struct Scsi_Host *, char *, char **, off_t, int, int);
+static int nsp32_show_info (struct seq_file *, struct Scsi_Host *);
static int nsp32_detect (struct pci_dev *pdev);
static int nsp32_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
@@ -268,7 +268,7 @@ static void nsp32_dmessage(const char *, int, int, char *, ...);
static struct scsi_host_template nsp32_template = {
.proc_name = "nsp32",
.name = "Workbit NinjaSCSI-32Bi/UDE",
- .proc_info = nsp32_proc_info,
+ .show_info = nsp32_show_info,
.info = nsp32_info,
.queuecommand = nsp32_queuecommand,
.can_queue = 1,
@@ -1442,19 +1442,10 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id)
}
#undef SPRINTF
-#define SPRINTF(args...) \
- do { \
- if(length > (pos - buffer)) { \
- pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
- nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\
- } \
- } while(0)
-
-static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
- off_t offset, int length, int inout)
+#define SPRINTF(args...) seq_printf(m, ##args)
+
+static int nsp32_show_info(struct seq_file *m, struct Scsi_Host *host)
{
- char *pos = buffer;
- int thislength;
unsigned long flags;
nsp32_hw_data *data;
int hostno;
@@ -1463,11 +1454,6 @@ static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
int id, speed;
long model;
- /* Write is not supported, just return. */
- if (inout == TRUE) {
- return -EINVAL;
- }
-
hostno = host->host_no;
data = (nsp32_hw_data *)host->hostdata;
base = host->io_port;
@@ -1527,20 +1513,7 @@ static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
}
SPRINTF("\n");
}
-
-
- thislength = pos - (buffer + offset);
-
- if(thislength < 0) {
- *start = NULL;
- return 0;
- }
-
-
- thislength = min(thislength, length);
- *start = buffer + offset;
-
- return thislength;
+ return 0;
}
#undef SPRINTF
@@ -2926,7 +2899,7 @@ static void nsp32_do_bus_reset(nsp32_hw_data *data)
* reset SCSI bus
*/
nsp32_write1(base, SCSI_BUS_CONTROL, BUSCTL_RST);
- udelay(RESET_HOLD_TIME);
+ mdelay(RESET_HOLD_TIME / 1000);
nsp32_write1(base, SCSI_BUS_CONTROL, 0);
for(i = 0; i < 5; i++) {
intrdat = nsp32_read2(base, IRQ_STATUS); /* dummy read */
@@ -3382,7 +3355,7 @@ static int nsp32_resume(struct pci_dev *pdev)
/************************************************************************
* PCI/Cardbus probe/remove routine
*/
-static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int ret;
nsp32_hw_data *data = &nsp32_data_base;
@@ -3418,7 +3391,7 @@ static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_i
return ret;
}
-static void __devexit nsp32_remove(struct pci_dev *pdev)
+static void nsp32_remove(struct pci_dev *pdev)
{
struct Scsi_Host *host = pci_get_drvdata(pdev);
@@ -3435,7 +3408,7 @@ static struct pci_driver nsp32_driver = {
.name = "nsp32",
.id_table = nsp32_pci_table,
.probe = nsp32_probe,
- .remove = __devexit_p(nsp32_remove),
+ .remove = nsp32_remove,
#ifdef CONFIG_PM
.suspend = nsp32_suspend,
.resume = nsp32_resume,
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index c06b8e5..aa66361 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -144,6 +144,10 @@ static int _osd_get_print_system_info(struct osd_dev *od,
odi->osdname_len = get_attrs[a].len;
/* Avoid NULL for memcmp optimization 0-length is good enough */
odi->osdname = kzalloc(odi->osdname_len + 1, GFP_KERNEL);
+ if (!odi->osdname) {
+ ret = -ENOMEM;
+ goto out;
+ }
if (odi->osdname_len)
memcpy(odi->osdname, get_attrs[a].val_ptr, odi->osdname_len);
OSD_INFO("OSD_NAME [%s]\n", odi->osdname);
@@ -1045,7 +1049,7 @@ static struct bio *_create_sg_bios(struct osd_request *or,
bio = bio_kmalloc(GFP_KERNEL, numentries);
if (unlikely(!bio)) {
- OSD_DEBUG("Faild to allocate BIO size=%u\n", numentries);
+ OSD_DEBUG("Failed to allocate BIO size=%u\n", numentries);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 4375417..9d86947 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -268,18 +268,11 @@ static inline bool _the_same_or_null(const u8 *a1, unsigned a1_len,
return 0 == memcmp(a1, a2, a1_len);
}
-struct find_oud_t {
- const struct osd_dev_info *odi;
- struct device *dev;
- struct osd_uld_device *oud;
-} ;
-
-int _mach_odi(struct device *dev, void *find_data)
+static int _match_odi(struct device *dev, const void *find_data)
{
struct osd_uld_device *oud = container_of(dev, struct osd_uld_device,
class_dev);
- struct find_oud_t *fot = find_data;
- const struct osd_dev_info *odi = fot->odi;
+ const struct osd_dev_info *odi = find_data;
if (_the_same_or_null(oud->odi.systemid, oud->odi.systemid_len,
odi->systemid, odi->systemid_len) &&
@@ -287,7 +280,6 @@ int _mach_odi(struct device *dev, void *find_data)
odi->osdname, odi->osdname_len)) {
OSD_DEBUG("found device sysid_len=%d osdname=%d\n",
odi->systemid_len, odi->osdname_len);
- fot->oud = oud;
return 1;
} else {
return 0;
@@ -301,19 +293,19 @@ int _mach_odi(struct device *dev, void *find_data)
*/
struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi)
{
- struct find_oud_t find = {.odi = odi};
-
- find.dev = class_find_device(&osd_uld_class, NULL, &find, _mach_odi);
- if (likely(find.dev)) {
+ struct device *dev = class_find_device(&osd_uld_class, NULL, odi, _match_odi);
+ if (likely(dev)) {
struct osd_dev_handle *odh = kzalloc(sizeof(*odh), GFP_KERNEL);
+ struct osd_uld_device *oud = container_of(dev,
+ struct osd_uld_device, class_dev);
if (unlikely(!odh)) {
- put_device(find.dev);
+ put_device(dev);
return ERR_PTR(-ENOMEM);
}
- odh->od = find.oud->od;
- odh->oud = find.oud;
+ odh->od = oud->od;
+ odh->oud = oud;
return &odh->od;
}
@@ -493,7 +485,7 @@ static int osd_probe(struct device *dev)
oud->class_dev.class = &osd_uld_class;
oud->class_dev.parent = dev;
oud->class_dev.release = __remove;
- error = dev_set_name(&oud->class_dev, disk->disk_name);
+ error = dev_set_name(&oud->class_dev, "%s", disk->disk_name);
if (error) {
OSD_ERR("dev_set_name failed => %d\n", error);
goto err_put_cdev;
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 2f72c98..62f1a60 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -388,7 +388,8 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
int count;
tpnt->proc_name = "pas16";
- tpnt->proc_info = &pas16_proc_info;
+ tpnt->show_info = pas16_show_info;
+ tpnt->write_info = pas16_write_info;
if (pas16_addr != 0) {
overrides[0].io_port = pas16_addr;
diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h
index a04281c..3721342 100644
--- a/drivers/scsi/pas16.h
+++ b/drivers/scsi/pas16.h
@@ -163,7 +163,8 @@ static int pas16_bus_reset(Scsi_Cmnd *);
#define NCR5380_queue_command pas16_queue_command
#define NCR5380_abort pas16_abort
#define NCR5380_bus_reset pas16_bus_reset
-#define NCR5380_proc_info pas16_proc_info
+#define NCR5380_show_info pas16_show_info
+#define NCR5380_write_info pas16_write_info
/* 15 14 12 10 7 5 3
1101 0100 1010 1000 */
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index b61a753..987fbb1 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -76,7 +76,7 @@ MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0
static struct scsi_host_template nsp_driver_template = {
.proc_name = "nsp_cs",
- .proc_info = nsp_proc_info,
+ .show_info = nsp_show_info,
.name = "WorkBit NinjaSCSI-3/32Bi(16bit)",
.info = nsp_info,
.queuecommand = nsp_queuecommand,
@@ -1365,33 +1365,19 @@ static const char *nsp_info(struct Scsi_Host *shpnt)
}
#undef SPRINTF
-#define SPRINTF(args...) \
- do { \
- if(length > (pos - buffer)) { \
- pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
- nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\
- } \
- } while(0)
-
-static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start,
- off_t offset, int length, int inout)
+#define SPRINTF(args...) seq_printf(m, ##args)
+
+static int nsp_show_info(struct seq_file *m, struct Scsi_Host *host)
{
int id;
- char *pos = buffer;
- int thislength;
int speed;
unsigned long flags;
nsp_hw_data *data;
int hostno;
- if (inout) {
- return -EINVAL;
- }
-
hostno = host->host_no;
data = (nsp_hw_data *)host->hostdata;
-
SPRINTF("NinjaSCSI status\n\n");
SPRINTF("Driver version: $Revision: 1.23 $\n");
SPRINTF("SCSI host No.: %d\n", hostno);
@@ -1458,19 +1444,7 @@ static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start,
}
SPRINTF("\n");
}
-
- thislength = pos - (buffer + offset);
-
- if(thislength < 0) {
- *start = NULL;
- return 0;
- }
-
-
- thislength = min(thislength, length);
- *start = buffer + offset;
-
- return thislength;
+ return 0;
}
#undef SPRINTF
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 7fc9a9d..afd64f0 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -292,13 +292,8 @@ static int nsp_cs_config (struct pcmcia_device *link);
/* Linux SCSI subsystem specific functions */
static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht);
static const char *nsp_info (struct Scsi_Host *shpnt);
-static int nsp_proc_info (
- struct Scsi_Host *host,
- char *buffer,
- char **start,
- off_t offset,
- int length,
- int inout);
+static int nsp_show_info (struct seq_file *m,
+ struct Scsi_Host *host);
static int nsp_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
/* Error handler */
diff --git a/drivers/scsi/pm8001/Makefile b/drivers/scsi/pm8001/Makefile
index 52f0429..ce4cd87 100644
--- a/drivers/scsi/pm8001/Makefile
+++ b/drivers/scsi/pm8001/Makefile
@@ -4,9 +4,10 @@
# Copyright (C) 2008-2009 USI Co., Ltd.
-obj-$(CONFIG_SCSI_PM8001) += pm8001.o
-pm8001-y += pm8001_init.o \
+obj-$(CONFIG_SCSI_PM8001) += pm80xx.o
+pm80xx-y += pm8001_init.o \
pm8001_sas.o \
pm8001_ctl.o \
- pm8001_hwi.o
+ pm8001_hwi.o \
+ pm80xx_hwi.o
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 45bc197b..d99f41c 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1,5 +1,5 @@
/*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver
*
* Copyright (c) 2008-2009 USI Co., Ltd.
* All rights reserved.
@@ -58,8 +58,13 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
- return snprintf(buf, PAGE_SIZE, "%d\n",
- pm8001_ha->main_cfg_tbl.interface_rev);
+ if (pm8001_ha->chip_id == chip_8001) {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev);
+ } else {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev);
+ }
}
static
DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
@@ -78,11 +83,19 @@ static ssize_t pm8001_ctl_fw_version_show(struct device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
- return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
- (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24),
- (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16),
- (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8),
- (u8)(pm8001_ha->main_cfg_tbl.firmware_rev));
+ if (pm8001_ha->chip_id == chip_8001) {
+ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+ (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24),
+ (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16),
+ (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8),
+ (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev));
+ } else {
+ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+ (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24),
+ (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16),
+ (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8),
+ (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
+ }
}
static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
/**
@@ -99,8 +112,13 @@ static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
- return snprintf(buf, PAGE_SIZE, "%d\n",
- pm8001_ha->main_cfg_tbl.max_out_io);
+ if (pm8001_ha->chip_id == chip_8001) {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io);
+ } else {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io);
+ }
}
static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL);
/**
@@ -117,8 +135,15 @@ static ssize_t pm8001_ctl_max_devices_show(struct device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
- return snprintf(buf, PAGE_SIZE, "%04d\n",
- (u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16));
+ if (pm8001_ha->chip_id == chip_8001) {
+ return snprintf(buf, PAGE_SIZE, "%04d\n",
+ (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16)
+ );
+ } else {
+ return snprintf(buf, PAGE_SIZE, "%04d\n",
+ (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16)
+ );
+ }
}
static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL);
/**
@@ -136,8 +161,15 @@ static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
- return snprintf(buf, PAGE_SIZE, "%04d\n",
- pm8001_ha->main_cfg_tbl.max_sgl & 0x0000FFFF);
+ if (pm8001_ha->chip_id == chip_8001) {
+ return snprintf(buf, PAGE_SIZE, "%04d\n",
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl & 0x0000FFFF
+ );
+ } else {
+ return snprintf(buf, PAGE_SIZE, "%04d\n",
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl & 0x0000FFFF
+ );
+ }
}
static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL);
@@ -173,7 +205,14 @@ static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev,
struct Scsi_Host *shost = class_to_shost(cdev);
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
- mode = (pm8001_ha->main_cfg_tbl.ctrl_cap_flag & 0xfe000000)>>25;
+ /* fe000000 means supports SAS2.1 */
+ if (pm8001_ha->chip_id == chip_8001)
+ mode = (pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag &
+ 0xfe000000)>>25;
+ else
+ /* fe000000 means supports SAS2.1 */
+ mode = (pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag &
+ 0xfe000000)>>25;
return show_sas_spec_support_status(mode, buf);
}
static DEVICE_ATTR(sas_spec_support, S_IRUGO,
@@ -361,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
goto out;
}
payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
- memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
+ memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
pm8001_ha->fw_image->size);
payload->length = pm8001_ha->fw_image->size;
payload->id = 0;
+ payload->minor_function = 0x1;
pm8001_ha->nvmd_completion = &completion;
ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
wait_for_completion(&completion);
@@ -411,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
payload->length = 1024*16;
payload->id = 0;
fwControl =
- (struct fw_control_info *)payload->func_specific;
+ (struct fw_control_info *)&payload->func_specific;
fwControl->len = IOCTL_BUF_SIZE; /* IN */
fwControl->size = partitionSize + HEADER_LEN;/* IN */
fwControl->retcode = 0;/* OUT */
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index c3d20c8..479c5a7 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -1,5 +1,5 @@
/*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver
*
* Copyright (c) 2008-2009 USI Co., Ltd.
* All rights reserved.
@@ -43,9 +43,12 @@
enum chip_flavors {
chip_8001,
+ chip_8008,
+ chip_8009,
+ chip_8018,
+ chip_8019
};
-#define USI_MAX_MEMCNT 9
-#define PM8001_MAX_DMA_SG SG_ALL
+
enum phy_speed {
PHY_SPEED_15 = 0x01,
PHY_SPEED_30 = 0x02,
@@ -69,23 +72,34 @@ enum port_type {
#define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */
#define PM8001_MAX_INB_NUM 1
#define PM8001_MAX_OUTB_NUM 1
+#define PM8001_MAX_SPCV_INB_NUM 1
+#define PM8001_MAX_SPCV_OUTB_NUM 4
#define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */
+/* Inbound/Outbound queue size */
+#define IOMB_SIZE_SPC 64
+#define IOMB_SIZE_SPCV 128
+
/* unchangeable hardware details */
-#define PM8001_MAX_PHYS 8 /* max. possible phys */
-#define PM8001_MAX_PORTS 8 /* max. possible ports */
-#define PM8001_MAX_DEVICES 1024 /* max supported device */
+#define PM8001_MAX_PHYS 16 /* max. possible phys */
+#define PM8001_MAX_PORTS 16 /* max. possible ports */
+#define PM8001_MAX_DEVICES 2048 /* max supported device */
+#define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */
+#define USI_MAX_MEMCNT_BASE 5
+#define IB (USI_MAX_MEMCNT_BASE + 1)
+#define CI (IB + PM8001_MAX_SPCV_INB_NUM)
+#define OB (CI + PM8001_MAX_SPCV_INB_NUM)
+#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM)
+#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM)
+#define PM8001_MAX_DMA_SG SG_ALL
enum memory_region_num {
AAP1 = 0x0, /* application acceleration processor */
IOP, /* IO processor */
- CI, /* consumer index */
- PI, /* producer index */
- IB, /* inbound queue */
- OB, /* outbound queue */
NVMD, /* NVM device */
DEV_MEM, /* memory for devices */
CCB_MEM, /* memory for command control block */
+ FW_FLASH /* memory for fw flash update */
};
#define PM8001_EVENT_LOG_SIZE (128 * 1024)
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index bf54aaf..5456f5c 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -47,35 +47,42 @@
* read_main_config_table - read the configure table and save it.
* @pm8001_ha: our hba card information
*/
-static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha)
+static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
{
void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
- pm8001_ha->main_cfg_tbl.signature = pm8001_mr32(address, 0x00);
- pm8001_ha->main_cfg_tbl.interface_rev = pm8001_mr32(address, 0x04);
- pm8001_ha->main_cfg_tbl.firmware_rev = pm8001_mr32(address, 0x08);
- pm8001_ha->main_cfg_tbl.max_out_io = pm8001_mr32(address, 0x0C);
- pm8001_ha->main_cfg_tbl.max_sgl = pm8001_mr32(address, 0x10);
- pm8001_ha->main_cfg_tbl.ctrl_cap_flag = pm8001_mr32(address, 0x14);
- pm8001_ha->main_cfg_tbl.gst_offset = pm8001_mr32(address, 0x18);
- pm8001_ha->main_cfg_tbl.inbound_queue_offset =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.signature =
+ pm8001_mr32(address, 0x00);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev =
+ pm8001_mr32(address, 0x04);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev =
+ pm8001_mr32(address, 0x08);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io =
+ pm8001_mr32(address, 0x0C);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl =
+ pm8001_mr32(address, 0x10);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag =
+ pm8001_mr32(address, 0x14);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.gst_offset =
+ pm8001_mr32(address, 0x18);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_queue_offset =
pm8001_mr32(address, MAIN_IBQ_OFFSET);
- pm8001_ha->main_cfg_tbl.outbound_queue_offset =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_queue_offset =
pm8001_mr32(address, MAIN_OBQ_OFFSET);
- pm8001_ha->main_cfg_tbl.hda_mode_flag =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.hda_mode_flag =
pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET);
/* read analog Setting offset from the configuration table */
- pm8001_ha->main_cfg_tbl.anolog_setup_table_offset =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.anolog_setup_table_offset =
pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET);
/* read Error Dump Offset and Length */
- pm8001_ha->main_cfg_tbl.fatal_err_dump_offset0 =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_offset0 =
pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET);
- pm8001_ha->main_cfg_tbl.fatal_err_dump_length0 =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_length0 =
pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH);
- pm8001_ha->main_cfg_tbl.fatal_err_dump_offset1 =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_offset1 =
pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET);
- pm8001_ha->main_cfg_tbl.fatal_err_dump_length1 =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_length1 =
pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH);
}
@@ -83,48 +90,70 @@ static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha)
* read_general_status_table - read the general status table and save it.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-read_general_status_table(struct pm8001_hba_info *pm8001_ha)
+static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
{
void __iomem *address = pm8001_ha->general_stat_tbl_addr;
- pm8001_ha->gs_tbl.gst_len_mpistate = pm8001_mr32(address, 0x00);
- pm8001_ha->gs_tbl.iq_freeze_state0 = pm8001_mr32(address, 0x04);
- pm8001_ha->gs_tbl.iq_freeze_state1 = pm8001_mr32(address, 0x08);
- pm8001_ha->gs_tbl.msgu_tcnt = pm8001_mr32(address, 0x0C);
- pm8001_ha->gs_tbl.iop_tcnt = pm8001_mr32(address, 0x10);
- pm8001_ha->gs_tbl.reserved = pm8001_mr32(address, 0x14);
- pm8001_ha->gs_tbl.phy_state[0] = pm8001_mr32(address, 0x18);
- pm8001_ha->gs_tbl.phy_state[1] = pm8001_mr32(address, 0x1C);
- pm8001_ha->gs_tbl.phy_state[2] = pm8001_mr32(address, 0x20);
- pm8001_ha->gs_tbl.phy_state[3] = pm8001_mr32(address, 0x24);
- pm8001_ha->gs_tbl.phy_state[4] = pm8001_mr32(address, 0x28);
- pm8001_ha->gs_tbl.phy_state[5] = pm8001_mr32(address, 0x2C);
- pm8001_ha->gs_tbl.phy_state[6] = pm8001_mr32(address, 0x30);
- pm8001_ha->gs_tbl.phy_state[7] = pm8001_mr32(address, 0x34);
- pm8001_ha->gs_tbl.reserved1 = pm8001_mr32(address, 0x38);
- pm8001_ha->gs_tbl.reserved2 = pm8001_mr32(address, 0x3C);
- pm8001_ha->gs_tbl.reserved3 = pm8001_mr32(address, 0x40);
- pm8001_ha->gs_tbl.recover_err_info[0] = pm8001_mr32(address, 0x44);
- pm8001_ha->gs_tbl.recover_err_info[1] = pm8001_mr32(address, 0x48);
- pm8001_ha->gs_tbl.recover_err_info[2] = pm8001_mr32(address, 0x4C);
- pm8001_ha->gs_tbl.recover_err_info[3] = pm8001_mr32(address, 0x50);
- pm8001_ha->gs_tbl.recover_err_info[4] = pm8001_mr32(address, 0x54);
- pm8001_ha->gs_tbl.recover_err_info[5] = pm8001_mr32(address, 0x58);
- pm8001_ha->gs_tbl.recover_err_info[6] = pm8001_mr32(address, 0x5C);
- pm8001_ha->gs_tbl.recover_err_info[7] = pm8001_mr32(address, 0x60);
+ pm8001_ha->gs_tbl.pm8001_tbl.gst_len_mpistate =
+ pm8001_mr32(address, 0x00);
+ pm8001_ha->gs_tbl.pm8001_tbl.iq_freeze_state0 =
+ pm8001_mr32(address, 0x04);
+ pm8001_ha->gs_tbl.pm8001_tbl.iq_freeze_state1 =
+ pm8001_mr32(address, 0x08);
+ pm8001_ha->gs_tbl.pm8001_tbl.msgu_tcnt =
+ pm8001_mr32(address, 0x0C);
+ pm8001_ha->gs_tbl.pm8001_tbl.iop_tcnt =
+ pm8001_mr32(address, 0x10);
+ pm8001_ha->gs_tbl.pm8001_tbl.rsvd =
+ pm8001_mr32(address, 0x14);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[0] =
+ pm8001_mr32(address, 0x18);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[1] =
+ pm8001_mr32(address, 0x1C);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[2] =
+ pm8001_mr32(address, 0x20);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[3] =
+ pm8001_mr32(address, 0x24);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[4] =
+ pm8001_mr32(address, 0x28);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[5] =
+ pm8001_mr32(address, 0x2C);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[6] =
+ pm8001_mr32(address, 0x30);
+ pm8001_ha->gs_tbl.pm8001_tbl.phy_state[7] =
+ pm8001_mr32(address, 0x34);
+ pm8001_ha->gs_tbl.pm8001_tbl.gpio_input_val =
+ pm8001_mr32(address, 0x38);
+ pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[0] =
+ pm8001_mr32(address, 0x3C);
+ pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[1] =
+ pm8001_mr32(address, 0x40);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[0] =
+ pm8001_mr32(address, 0x44);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[1] =
+ pm8001_mr32(address, 0x48);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[2] =
+ pm8001_mr32(address, 0x4C);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[3] =
+ pm8001_mr32(address, 0x50);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[4] =
+ pm8001_mr32(address, 0x54);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[5] =
+ pm8001_mr32(address, 0x58);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[6] =
+ pm8001_mr32(address, 0x5C);
+ pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[7] =
+ pm8001_mr32(address, 0x60);
}
/**
* read_inbnd_queue_table - read the inbound queue table and save it.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
{
- int inbQ_num = 1;
int i;
void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
- for (i = 0; i < inbQ_num; i++) {
+ for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
u32 offset = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
@@ -137,13 +166,11 @@ read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
* read_outbnd_queue_table - read the outbound queue table and save it.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
{
- int outbQ_num = 1;
int i;
void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
- for (i = 0; i < outbQ_num; i++) {
+ for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
u32 offset = i * 0x24;
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
@@ -156,57 +183,59 @@ read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
* init_default_table_values - init the default table.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-init_default_table_values(struct pm8001_hba_info *pm8001_ha)
+static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
{
- int qn = 1;
int i;
u32 offsetib, offsetob;
void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
- pm8001_ha->main_cfg_tbl.inbound_q_nppd_hppd = 0;
- pm8001_ha->main_cfg_tbl.outbound_hw_event_pid0_3 = 0;
- pm8001_ha->main_cfg_tbl.outbound_hw_event_pid4_7 = 0;
- pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid0_3 = 0;
- pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid4_7 = 0;
- pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid0_3 = 0;
- pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid4_7 = 0;
- pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid0_3 = 0;
- pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid4_7 = 0;
- pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid0_3 = 0;
- pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid4_7 = 0;
-
- pm8001_ha->main_cfg_tbl.upper_event_log_addr =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid4_7 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid0_3 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid4_7 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ITNexus_event_pid0_3 =
+ 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ITNexus_event_pid4_7 =
+ 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ssp_event_pid0_3 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ssp_event_pid4_7 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_smp_event_pid0_3 = 0;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_smp_event_pid4_7 = 0;
+
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_event_log_addr =
pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;
- pm8001_ha->main_cfg_tbl.lower_event_log_addr =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_event_log_addr =
pm8001_ha->memoryMap.region[AAP1].phys_addr_lo;
- pm8001_ha->main_cfg_tbl.event_log_size = PM8001_EVENT_LOG_SIZE;
- pm8001_ha->main_cfg_tbl.event_log_option = 0x01;
- pm8001_ha->main_cfg_tbl.upper_iop_event_log_addr =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_size =
+ PM8001_EVENT_LOG_SIZE;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_option = 0x01;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_iop_event_log_addr =
pm8001_ha->memoryMap.region[IOP].phys_addr_hi;
- pm8001_ha->main_cfg_tbl.lower_iop_event_log_addr =
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_iop_event_log_addr =
pm8001_ha->memoryMap.region[IOP].phys_addr_lo;
- pm8001_ha->main_cfg_tbl.iop_event_log_size = PM8001_EVENT_LOG_SIZE;
- pm8001_ha->main_cfg_tbl.iop_event_log_option = 0x01;
- pm8001_ha->main_cfg_tbl.fatal_err_interrupt = 0x01;
- for (i = 0; i < qn; i++) {
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_size =
+ PM8001_EVENT_LOG_SIZE;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option = 0x01;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt = 0x01;
+ for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
- pm8001_ha->memoryMap.region[IB].phys_addr_hi;
+ pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].lower_base_addr =
- pm8001_ha->memoryMap.region[IB].phys_addr_lo;
+ pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].base_virt =
- (u8 *)pm8001_ha->memoryMap.region[IB].virt_ptr;
+ (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
pm8001_ha->inbnd_q_tbl[i].total_length =
- pm8001_ha->memoryMap.region[IB].total_len;
+ pm8001_ha->memoryMap.region[IB + i].total_len;
pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr =
- pm8001_ha->memoryMap.region[CI].phys_addr_hi;
+ pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr =
- pm8001_ha->memoryMap.region[CI].phys_addr_lo;
+ pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].ci_virt =
- pm8001_ha->memoryMap.region[CI].virt_ptr;
+ pm8001_ha->memoryMap.region[CI + i].virt_ptr;
offsetib = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
get_pci_bar_index(pm8001_mr32(addressib,
@@ -216,25 +245,25 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;
pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;
}
- for (i = 0; i < qn; i++) {
+ for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
- pm8001_ha->memoryMap.region[OB].phys_addr_hi;
+ pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].lower_base_addr =
- pm8001_ha->memoryMap.region[OB].phys_addr_lo;
+ pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
pm8001_ha->outbnd_q_tbl[i].base_virt =
- (u8 *)pm8001_ha->memoryMap.region[OB].virt_ptr;
+ (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
pm8001_ha->outbnd_q_tbl[i].total_length =
- pm8001_ha->memoryMap.region[OB].total_len;
+ pm8001_ha->memoryMap.region[OB + i].total_len;
pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr =
- pm8001_ha->memoryMap.region[PI].phys_addr_hi;
+ pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
- pm8001_ha->memoryMap.region[PI].phys_addr_lo;
+ pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay =
- 0 | (10 << 16) | (0 << 24);
+ 0 | (10 << 16) | (i << 24);
pm8001_ha->outbnd_q_tbl[i].pi_virt =
- pm8001_ha->memoryMap.region[PI].virt_ptr;
+ pm8001_ha->memoryMap.region[PI + i].virt_ptr;
offsetob = i * 0x24;
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
get_pci_bar_index(pm8001_mr32(addressob,
@@ -250,55 +279,63 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
* update_main_config_table - update the main default table to the HBA.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-update_main_config_table(struct pm8001_hba_info *pm8001_ha)
+static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
{
void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
pm8001_mw32(address, 0x24,
- pm8001_ha->main_cfg_tbl.inbound_q_nppd_hppd);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd);
pm8001_mw32(address, 0x28,
- pm8001_ha->main_cfg_tbl.outbound_hw_event_pid0_3);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3);
pm8001_mw32(address, 0x2C,
- pm8001_ha->main_cfg_tbl.outbound_hw_event_pid4_7);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid4_7);
pm8001_mw32(address, 0x30,
- pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid0_3);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid0_3);
pm8001_mw32(address, 0x34,
- pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid4_7);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid4_7);
pm8001_mw32(address, 0x38,
- pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid0_3);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.
+ outbound_tgt_ITNexus_event_pid0_3);
pm8001_mw32(address, 0x3C,
- pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid4_7);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.
+ outbound_tgt_ITNexus_event_pid4_7);
pm8001_mw32(address, 0x40,
- pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid0_3);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.
+ outbound_tgt_ssp_event_pid0_3);
pm8001_mw32(address, 0x44,
- pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid4_7);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.
+ outbound_tgt_ssp_event_pid4_7);
pm8001_mw32(address, 0x48,
- pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid0_3);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.
+ outbound_tgt_smp_event_pid0_3);
pm8001_mw32(address, 0x4C,
- pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid4_7);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.
+ outbound_tgt_smp_event_pid4_7);
pm8001_mw32(address, 0x50,
- pm8001_ha->main_cfg_tbl.upper_event_log_addr);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_event_log_addr);
pm8001_mw32(address, 0x54,
- pm8001_ha->main_cfg_tbl.lower_event_log_addr);
- pm8001_mw32(address, 0x58, pm8001_ha->main_cfg_tbl.event_log_size);
- pm8001_mw32(address, 0x5C, pm8001_ha->main_cfg_tbl.event_log_option);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_event_log_addr);
+ pm8001_mw32(address, 0x58,
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_size);
+ pm8001_mw32(address, 0x5C,
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_option);
pm8001_mw32(address, 0x60,
- pm8001_ha->main_cfg_tbl.upper_iop_event_log_addr);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_iop_event_log_addr);
pm8001_mw32(address, 0x64,
- pm8001_ha->main_cfg_tbl.lower_iop_event_log_addr);
- pm8001_mw32(address, 0x68, pm8001_ha->main_cfg_tbl.iop_event_log_size);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_iop_event_log_addr);
+ pm8001_mw32(address, 0x68,
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_size);
pm8001_mw32(address, 0x6C,
- pm8001_ha->main_cfg_tbl.iop_event_log_option);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option);
pm8001_mw32(address, 0x70,
- pm8001_ha->main_cfg_tbl.fatal_err_interrupt);
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt);
}
/**
* update_inbnd_queue_table - update the inbound queue table to the HBA.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number)
+static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+ int number)
{
void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
u16 offset = number * 0x20;
@@ -318,8 +355,8 @@ update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number)
* update_outbnd_queue_table - update the outbound queue table to the HBA.
* @pm8001_ha: our hba card information
*/
-static void __devinit
-update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number)
+static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+ int number)
{
void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
u16 offset = number * 0x24;
@@ -370,8 +407,8 @@ int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue)
* @pm8001_ha: our hba card information
* @SSCbit: set SSCbit to 0 to disable all phys ssc; 1 to enable all phys ssc.
*/
-static void __devinit
-mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
+static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha,
+ u32 SSCbit)
{
u32 value, offset, i;
unsigned long flags;
@@ -438,9 +475,8 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
* @pm8001_ha: our hba card information
* @interval - interval time for each OPEN_REJECT (RETRY). The units are in 1us.
*/
-static void __devinit
-mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha,
- u32 interval)
+static void mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha,
+ u32 interval)
{
u32 offset;
u32 value;
@@ -601,8 +637,21 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
* pm8001_chip_init - the main init function that initialize whole PM8001 chip.
* @pm8001_ha: our hba card information
*/
-static int __devinit pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
{
+ u8 i = 0;
+ u16 deviceid;
+ pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
+ /* 8081 controllers need BAR shift to access MPI space
+ * as this is shared with BIOS data */
+ if (deviceid == 0x8081) {
+ if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("Shift Bar4 to 0x%x failed\n",
+ GSM_SM_BASE));
+ return -1;
+ }
+ }
/* check the firmware status */
if (-1 == check_fw_ready(pm8001_ha)) {
PM8001_FAIL_DBG(pm8001_ha,
@@ -619,11 +668,16 @@ static int __devinit pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
read_outbnd_queue_table(pm8001_ha);
/* update main config table ,inbound table and outbound table */
update_main_config_table(pm8001_ha);
- update_inbnd_queue_table(pm8001_ha, 0);
- update_outbnd_queue_table(pm8001_ha, 0);
- mpi_set_phys_g3_with_ssc(pm8001_ha, 0);
- /* 7->130ms, 34->500ms, 119->1.5s */
- mpi_set_open_retry_interval_reg(pm8001_ha, 119);
+ for (i = 0; i < PM8001_MAX_INB_NUM; i++)
+ update_inbnd_queue_table(pm8001_ha, i);
+ for (i = 0; i < PM8001_MAX_OUTB_NUM; i++)
+ update_outbnd_queue_table(pm8001_ha, i);
+ /* 8081 controller donot require these operations */
+ if (deviceid != 0x8081) {
+ mpi_set_phys_g3_with_ssc(pm8001_ha, 0);
+ /* 7->130ms, 34->500ms, 119->1.5s */
+ mpi_set_open_retry_interval_reg(pm8001_ha, 119);
+ }
/* notify firmware update finished and check initialization status */
if (0 == mpi_init_check(pm8001_ha)) {
PM8001_INIT_DBG(pm8001_ha,
@@ -645,6 +699,16 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
u32 max_wait_count;
u32 value;
u32 gst_len_mpistate;
+ u16 deviceid;
+ pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
+ if (deviceid == 0x8081) {
+ if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("Shift Bar4 to 0x%x failed\n",
+ GSM_SM_BASE));
+ return -1;
+ }
+ }
init_pci_device_addresses(pm8001_ha);
/* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
table is stop */
@@ -746,14 +810,14 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha)
* pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all
* the FW register status to the originated status.
* @pm8001_ha: our hba card information
- * @signature: signature in host scratch pad0 register.
*/
static int
-pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature)
+pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
{
u32 regVal, toggleVal;
u32 max_wait_count;
u32 regVal1, regVal2, regVal3;
+ u32 signature = 0x252acbcd; /* for host scratch pad0 */
unsigned long flags;
/* step1: Check FW is ready for soft reset */
@@ -1119,7 +1183,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha)
* pm8001_chip_iounmap - which maped when initialized.
* @pm8001_ha: our hba card information
*/
-static void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
+void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
{
s8 bar, logical = 0;
for (bar = 0; bar < 6; bar++) {
@@ -1198,7 +1262,7 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha,
* @pm8001_ha: our hba card information
*/
static void
-pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
#ifdef PM8001_USE_MSIX
pm8001_chip_msix_interrupt_enable(pm8001_ha, 0);
@@ -1213,7 +1277,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
* @pm8001_ha: our hba card information
*/
static void
-pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
#ifdef PM8001_USE_MSIX
pm8001_chip_msix_interrupt_disable(pm8001_ha, 0);
@@ -1224,12 +1288,13 @@ pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
}
/**
- * mpi_msg_free_get- get the free message buffer for transfer inbound queue.
+ * pm8001_mpi_msg_free_get - get the free message buffer for transfer
+ * inbound queue.
* @circularQ: the inbound queue we want to transfer to HBA.
* @messageSize: the message size of this transfer, normally it is 64 bytes
* @messagePtr: the pointer to message.
*/
-static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
+int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
u16 messageSize, void **messagePtr)
{
u32 offset, consumer_index;
@@ -1237,7 +1302,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
u8 bcCount = 1; /* only support single buffer */
/* Checks is the requested message size can be allocated in this queue*/
- if (messageSize > 64) {
+ if (messageSize > IOMB_SIZE_SPCV) {
*messagePtr = NULL;
return -1;
}
@@ -1251,7 +1316,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
return -1;
}
/* get memory IOMB buffer address */
- offset = circularQ->producer_idx * 64;
+ offset = circularQ->producer_idx * messageSize;
/* increment to next bcCount element */
circularQ->producer_idx = (circularQ->producer_idx + bcCount)
% PM8001_MPI_QUEUE;
@@ -1263,29 +1328,30 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
}
/**
- * mpi_build_cmd- build the message queue for transfer, update the PI to FW
- * to tell the fw to get this message from IOMB.
+ * pm8001_mpi_build_cmd- build the message queue for transfer, update the PI to
+ * FW to tell the fw to get this message from IOMB.
* @pm8001_ha: our hba card information
* @circularQ: the inbound queue we want to transfer to HBA.
* @opCode: the operation code represents commands which LLDD and fw recognized.
* @payload: the command payload of each operation command.
*/
-static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
+int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
struct inbound_queue_table *circularQ,
- u32 opCode, void *payload)
+ u32 opCode, void *payload, u32 responseQueue)
{
u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
- u32 responseQueue = 0;
void *pMessage;
- if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) {
+ if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
+ &pMessage) < 0) {
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("No free mpi buffer\n"));
return -1;
}
BUG_ON(!payload);
/*Copy to the payload*/
- memcpy(pMessage, payload, (64 - sizeof(struct mpi_msg_hdr)));
+ memcpy(pMessage, payload, (pm8001_ha->iomb_size -
+ sizeof(struct mpi_msg_hdr)));
/*Build the header*/
Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24)
@@ -1297,12 +1363,13 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
circularQ->pi_offset, circularQ->producer_idx);
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("after PI= %d CI= %d\n", circularQ->producer_idx,
- circularQ->consumer_index));
+ pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
+ responseQueue, opCode, circularQ->producer_idx,
+ circularQ->consumer_index));
return 0;
}
-static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
+u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
struct outbound_queue_table *circularQ, u8 bc)
{
u32 producer_index;
@@ -1311,7 +1378,7 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
msgHeader = (struct mpi_msg_hdr *)(pMsg - sizeof(struct mpi_msg_hdr));
pOutBoundMsgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt +
- circularQ->consumer_idx * 64);
+ circularQ->consumer_idx * pm8001_ha->iomb_size);
if (pOutBoundMsgHeader != msgHeader) {
PM8001_FAIL_DBG(pm8001_ha,
pm8001_printk("consumer_idx = %d msgHeader = %p\n",
@@ -1342,13 +1409,14 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
}
/**
- * mpi_msg_consume- get the MPI message from outbound queue message table.
+ * pm8001_mpi_msg_consume- get the MPI message from outbound queue
+ * message table.
* @pm8001_ha: our hba card information
* @circularQ: the outbound queue table.
* @messagePtr1: the message contents of this outbound message.
* @pBC: the message size.
*/
-static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
+u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
struct outbound_queue_table *circularQ,
void **messagePtr1, u8 *pBC)
{
@@ -1362,7 +1430,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
/*Get the pointer to the circular queue buffer element*/
msgHeader = (struct mpi_msg_hdr *)
(circularQ->base_virt +
- circularQ->consumer_idx * 64);
+ circularQ->consumer_idx * pm8001_ha->iomb_size);
/* read header */
header_tmp = pm8001_read_32(msgHeader);
msgHeader_tmp = cpu_to_le32(header_tmp);
@@ -1422,7 +1490,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
return MPI_IO_STATUS_BUSY;
}
-static void pm8001_work_fn(struct work_struct *work)
+void pm8001_work_fn(struct work_struct *work)
{
struct pm8001_work *pw = container_of(work, struct pm8001_work, work);
struct pm8001_device *pm8001_dev;
@@ -1437,7 +1505,7 @@ static void pm8001_work_fn(struct work_struct *work)
pm8001_dev = pw->data; /* Most stash device structure */
if ((pm8001_dev == NULL)
|| ((pw->handler != IO_XFER_ERROR_BREAK)
- && (pm8001_dev->dev_type == NO_DEVICE))) {
+ && (pm8001_dev->dev_type == SAS_PHY_UNUSED))) {
kfree(pw);
return;
}
@@ -1602,7 +1670,7 @@ static void pm8001_work_fn(struct work_struct *work)
} break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
dev = pm8001_dev->sas_device;
- pm8001_I_T_nexus_reset(dev);
+ pm8001_I_T_nexus_event_handler(dev);
break;
case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
dev = pm8001_dev->sas_device;
@@ -1620,7 +1688,7 @@ static void pm8001_work_fn(struct work_struct *work)
kfree(pw);
}
-static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
+int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
int handler)
{
struct pm8001_work *pw;
@@ -1639,6 +1707,123 @@ static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
return ret;
}
+static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_ha_dev)
+{
+ int res;
+ u32 ccb_tag;
+ struct pm8001_ccb_info *ccb;
+ struct sas_task *task = NULL;
+ struct task_abort_req task_abort;
+ struct inbound_queue_table *circularQ;
+ u32 opc = OPC_INB_SATA_ABORT;
+ int ret;
+
+ if (!pm8001_ha_dev) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
+ return;
+ }
+
+ task = sas_alloc_slow_task(GFP_ATOMIC);
+
+ if (!task) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
+ "allocate task\n"));
+ return;
+ }
+
+ task->task_done = pm8001_task_done;
+
+ res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+ if (res)
+ return;
+
+ ccb = &pm8001_ha->ccb_info[ccb_tag];
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ memset(&task_abort, 0, sizeof(task_abort));
+ task_abort.abort_all = cpu_to_le32(1);
+ task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+ task_abort.tag = cpu_to_le32(ccb_tag);
+
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+
+}
+
+static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_ha_dev)
+{
+ struct sata_start_req sata_cmd;
+ int res;
+ u32 ccb_tag;
+ struct pm8001_ccb_info *ccb;
+ struct sas_task *task = NULL;
+ struct host_to_dev_fis fis;
+ struct domain_device *dev;
+ struct inbound_queue_table *circularQ;
+ u32 opc = OPC_INB_SATA_HOST_OPSTART;
+
+ task = sas_alloc_slow_task(GFP_ATOMIC);
+
+ if (!task) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("cannot allocate task !!!\n"));
+ return;
+ }
+ task->task_done = pm8001_task_done;
+
+ res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+ if (res) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("cannot allocate tag !!!\n"));
+ return;
+ }
+
+ /* allocate domain device by ourselves as libsas
+ * is not going to provide any
+ */
+ dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
+ if (!dev) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("Domain device cannot be allocated\n"));
+ sas_free_task(task);
+ return;
+ } else {
+ task->dev = dev;
+ task->dev->lldd_dev = pm8001_ha_dev;
+ }
+
+ ccb = &pm8001_ha->ccb_info[ccb_tag];
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
+ pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
+ pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
+
+ memset(&sata_cmd, 0, sizeof(sata_cmd));
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ /* construct read log FIS */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.fis_type = 0x27;
+ fis.flags = 0x80;
+ fis.command = ATA_CMD_READ_LOG_EXT;
+ fis.lbal = 0x10;
+ fis.sector_count = 0x1;
+
+ sata_cmd.tag = cpu_to_le32(ccb_tag);
+ sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+ sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
+ memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+ res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+
+}
+
/**
* mpi_ssp_completion- process the event that FW response to the SSP request.
* @pm8001_ha: our hba card information
@@ -1873,7 +2058,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
break;
}
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("scsi_status = %x \n ",
+ pm8001_printk("scsi_status = %x\n ",
psspPayload->ssp_resp_iu.status));
spin_lock_irqsave(&t->task_state_lock, flags);
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
@@ -2102,16 +2287,44 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
status = le32_to_cpu(psataPayload->status);
tag = le32_to_cpu(psataPayload->tag);
+ if (!tag) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("tag null\n"));
+ return;
+ }
ccb = &pm8001_ha->ccb_info[tag];
param = le32_to_cpu(psataPayload->param);
- t = ccb->task;
+ if (ccb) {
+ t = ccb->task;
+ pm8001_dev = ccb->device;
+ } else {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("ccb null\n"));
+ return;
+ }
+
+ if (t) {
+ if (t->dev && (t->dev->lldd_dev))
+ pm8001_dev = t->dev->lldd_dev;
+ } else {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task null\n"));
+ return;
+ }
+
+ if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
+ && unlikely(!t || !t->lldd_task || !t->dev)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task or dev null\n"));
+ return;
+ }
+
ts = &t->task_status;
- pm8001_dev = ccb->device;
- if (status)
+ if (!ts) {
PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("sata IO status 0x%x\n", status));
- if (unlikely(!t || !t->lldd_task || !t->dev))
+ pm8001_printk("ts null\n"));
return;
+ }
switch (status) {
case IO_SUCCESS:
@@ -2119,6 +2332,19 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
+ /* check if response is for SEND READ LOG */
+ if (pm8001_dev &&
+ (pm8001_dev->id & NCQ_READ_LOG_FLAG)) {
+ /* set new bit for abort_all */
+ pm8001_dev->id |= NCQ_ABORT_ALL_FLAG;
+ /* clear bit for read log */
+ pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF;
+ pm8001_send_abort_all(pm8001_ha, pm8001_dev);
+ /* Free the tag */
+ pm8001_tag_free(pm8001_ha, tag);
+ sas_free_task(t);
+ return;
+ }
} else {
u8 len;
ts->resp = SAS_TASK_COMPLETE;
@@ -2430,6 +2656,29 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
unsigned long flags;
ccb = &pm8001_ha->ccb_info[tag];
+
+ if (ccb) {
+ t = ccb->task;
+ pm8001_dev = ccb->device;
+ } else {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("No CCB !!!. returning\n"));
+ }
+ if (event)
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("SATA EVENT 0x%x\n", event));
+
+ /* Check if this is NCQ error */
+ if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
+ /* find device using device id */
+ pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
+ /* send read log extension */
+ if (pm8001_dev)
+ pm8001_send_read_log(pm8001_ha, pm8001_dev);
+ return;
+ }
+
+ ccb = &pm8001_ha->ccb_info[tag];
t = ccb->task;
pm8001_dev = ccb->device;
if (event)
@@ -2438,9 +2687,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("port_id = %x,device_id = %x\n",
- port_id, dev_id));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
+ port_id, dev_id, tag, event));
switch (event) {
case IO_OVERFLOW:
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
@@ -2828,8 +3077,8 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
}
}
-static void
-mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
{
struct set_dev_state_resp *pPayload =
(struct set_dev_state_resp *)(piomb + 4);
@@ -2849,8 +3098,7 @@ mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_ccb_free(pm8001_ha, tag);
}
-static void
-mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
struct get_nvm_data_resp *pPayload =
(struct get_nvm_data_resp *)(piomb + 4);
@@ -2869,8 +3117,8 @@ mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_ccb_free(pm8001_ha, tag);
}
-static void
-mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+void
+pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
struct fw_control_ex *fw_control_context;
struct get_nvm_data_resp *pPayload =
@@ -2931,7 +3179,7 @@ mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_ccb_free(pm8001_ha, tag);
}
-static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
struct local_phy_ctl_resp *pPayload =
(struct local_phy_ctl_resp *)(piomb + 4);
@@ -2960,7 +3208,7 @@ static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
* while receive a broadcast(change) primitive just tell the sas
* layer to discover the changed domain rather than the whole domain.
*/
-static void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i)
+void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i)
{
struct pm8001_phy *phy = &pm8001_ha->phy[i];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -2994,7 +3242,7 @@ static void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i)
}
/* Get the link rate speed */
-static void get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)
+void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)
{
struct sas_phy *sas_phy = phy->sas_phy.phy;
@@ -3031,7 +3279,7 @@ static void get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)
* LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
* buffer.
*/
-static void pm8001_get_attached_sas_addr(struct pm8001_phy *phy,
+void pm8001_get_attached_sas_addr(struct pm8001_phy *phy,
u8 *sas_addr)
{
if (phy->sas_phy.frame_rcvd[0] == 0x34
@@ -3073,7 +3321,7 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
((phyId & 0x0F) << 4) | (port_id & 0x0F));
payload.param0 = cpu_to_le32(param0);
payload.param1 = cpu_to_le32(param1);
- mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
}
static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -3118,19 +3366,19 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
PHY_NOTIFY_ENABLE_SPINUP);
port->port_attached = 1;
- get_lrate_mode(phy, link_rate);
+ pm8001_get_lrate_mode(phy, link_rate);
break;
case SAS_EDGE_EXPANDER_DEVICE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("expander device.\n"));
port->port_attached = 1;
- get_lrate_mode(phy, link_rate);
+ pm8001_get_lrate_mode(phy, link_rate);
break;
case SAS_FANOUT_EXPANDER_DEVICE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("fanout expander device.\n"));
port->port_attached = 1;
- get_lrate_mode(phy, link_rate);
+ pm8001_get_lrate_mode(phy, link_rate);
break;
default:
PM8001_MSG_DBG(pm8001_ha,
@@ -3185,7 +3433,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
" phy id = %d\n", port_id, phy_id));
port->port_state = portstate;
port->port_attached = 1;
- get_lrate_mode(phy, link_rate);
+ pm8001_get_lrate_mode(phy, link_rate);
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
@@ -3195,7 +3443,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
sizeof(struct dev_to_host_fis));
phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
- phy->identify.device_type = SATA_DEV;
+ phy->identify.device_type = SAS_SATA_DEV;
pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
pm8001_bytes_dmaed(pm8001_ha, phy_id);
@@ -3266,7 +3514,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
}
/**
- * mpi_reg_resp -process register device ID response.
+ * pm8001_mpi_reg_resp -process register device ID response.
* @pm8001_ha: our hba card information
* @piomb: IO message buffer
*
@@ -3275,7 +3523,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
* has assigned, from now,inter-communication with FW is no longer using the
* SAS address, use device ID which FW assigned.
*/
-static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
u32 status;
u32 device_id;
@@ -3337,7 +3585,7 @@ static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
return 0;
}
-static int mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
u32 status;
u32 device_id;
@@ -3353,8 +3601,13 @@ static int mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
return 0;
}
-static int
-mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+/**
+ * fw_flash_update_resp - Response from FW for flash update command.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
{
u32 status;
struct fw_control_ex fw_control_context;
@@ -3409,10 +3662,6 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
}
ccb->fw_control_context->fw_control->retcode = status;
- pci_free_consistent(pm8001_ha->pdev,
- fw_control_context.len,
- fw_control_context.virtAddr,
- fw_control_context.phys_addr);
complete(pm8001_ha->nvmd_completion);
ccb->task = NULL;
ccb->ccb_tag = 0xFFFFFFFF;
@@ -3420,8 +3669,7 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
return 0;
}
-static int
-mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
+int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
{
u32 status;
int i;
@@ -3437,8 +3685,7 @@ mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
return 0;
}
-static int
-mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
struct sas_task *t;
struct pm8001_ccb_info *ccb;
@@ -3446,19 +3693,29 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 status ;
u32 tag, scp;
struct task_status_struct *ts;
+ struct pm8001_device *pm8001_dev;
struct task_abort_resp *pPayload =
(struct task_abort_resp *)(piomb + 4);
status = le32_to_cpu(pPayload->status);
tag = le32_to_cpu(pPayload->tag);
+ if (!tag) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk(" TAG NULL. RETURNING !!!"));
+ return -1;
+ }
+
scp = le32_to_cpu(pPayload->scp);
ccb = &pm8001_ha->ccb_info[tag];
t = ccb->task;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk(" status = 0x%x\n", status));
- if (t == NULL)
+ pm8001_dev = ccb->device; /* retrieve device */
+
+ if (!t) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk(" TASK NULL. RETURNING !!!"));
return -1;
+ }
ts = &t->task_status;
if (status != 0)
PM8001_FAIL_DBG(pm8001_ha,
@@ -3482,7 +3739,15 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
spin_unlock_irqrestore(&t->task_state_lock, flags);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();
- t->task_done(t);
+
+ if (pm8001_dev->id & NCQ_ABORT_ALL_FLAG) {
+ pm8001_tag_free(pm8001_ha, tag);
+ sas_free_task(t);
+ /* clear the flag */
+ pm8001_dev->id &= 0xBFFFFFFF;
+ } else
+ t->task_done(t);
+
return 0;
}
@@ -3733,17 +3998,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
case OPC_OUB_LOCAL_PHY_CNTRL:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n"));
- mpi_local_phy_ctl(pm8001_ha, piomb);
+ pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
break;
case OPC_OUB_DEV_REGIST:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_DEV_REGIST\n"));
- mpi_reg_resp(pm8001_ha, piomb);
+ pm8001_mpi_reg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEREG_DEV:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("unregister the device\n"));
- mpi_dereg_resp(pm8001_ha, piomb);
+ pm8001_mpi_dereg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEV_HANDLE:
PM8001_MSG_DBG(pm8001_ha,
@@ -3781,7 +4046,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
case OPC_OUB_FW_FLASH_UPDATE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n"));
- mpi_fw_flash_update_resp(pm8001_ha, piomb);
+ pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GPIO_RESPONSE:
PM8001_MSG_DBG(pm8001_ha,
@@ -3794,17 +4059,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
case OPC_OUB_GENERAL_EVENT:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_GENERAL_EVENT\n"));
- mpi_general_event(pm8001_ha, piomb);
+ pm8001_mpi_general_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_ABORT_RSP:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n"));
- mpi_task_abort_resp(pm8001_ha, piomb);
+ pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_ABORT_RSP:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n"));
- mpi_task_abort_resp(pm8001_ha, piomb);
+ pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SAS_DIAG_MODE_START_END:
PM8001_MSG_DBG(pm8001_ha,
@@ -3829,17 +4094,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
case OPC_OUB_SMP_ABORT_RSP:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n"));
- mpi_task_abort_resp(pm8001_ha, piomb);
+ pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_NVMD_DATA:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_GET_NVMD_DATA\n"));
- mpi_get_nvmd_resp(pm8001_ha, piomb);
+ pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SET_NVMD_DATA:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_SET_NVMD_DATA\n"));
- mpi_set_nvmd_resp(pm8001_ha, piomb);
+ pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEVICE_HANDLE_REMOVAL:
PM8001_MSG_DBG(pm8001_ha,
@@ -3848,7 +4113,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
case OPC_OUB_SET_DEVICE_STATE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n"));
- mpi_set_dev_state_resp(pm8001_ha, piomb);
+ pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEVICE_STATE:
PM8001_MSG_DBG(pm8001_ha,
@@ -3870,7 +4135,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
}
}
-static int process_oq(struct pm8001_hba_info *pm8001_ha)
+static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
struct outbound_queue_table *circularQ;
void *pMsg1 = NULL;
@@ -3879,14 +4144,15 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha)
unsigned long flags;
spin_lock_irqsave(&pm8001_ha->lock, flags);
- circularQ = &pm8001_ha->outbnd_q_tbl[0];
+ circularQ = &pm8001_ha->outbnd_q_tbl[vec];
do {
- ret = mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
+ ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
if (MPI_IO_STATUS_SUCCESS == ret) {
/* process the outbound message */
process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4));
/* free the message from the outbound circular buffer */
- mpi_msg_free_set(pm8001_ha, pMsg1, circularQ, bc);
+ pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,
+ circularQ, bc);
}
if (MPI_IO_STATUS_BUSY == ret) {
/* Update the producer index from SPC */
@@ -3909,7 +4175,7 @@ static const u8 data_dir_flags[] = {
[PCI_DMA_FROMDEVICE] = DATA_DIR_IN,/* INBOUND */
[PCI_DMA_NONE] = DATA_DIR_NONE,/* NO TRANSFER */
};
-static void
+void
pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd)
{
int i;
@@ -3984,7 +4250,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
smp_cmd.long_smp_req.long_resp_size =
cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
- mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd);
+ pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
return 0;
err_out_2:
@@ -4025,7 +4291,8 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
ssp_cmd.ssp_iu.efb_prio_attr |= 0x80;
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
- memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cdb, 16);
+ memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
+ task->ssp_task.cmd->cmd_len);
circularQ = &pm8001_ha->inbnd_q_tbl[0];
/* fill in PRD (scatter/gather) table, if any */
@@ -4048,7 +4315,7 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
ssp_cmd.esgl = 0;
}
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0);
return ret;
}
@@ -4066,6 +4333,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
u32 ATAP = 0x0;
u32 dir;
struct inbound_queue_table *circularQ;
+ unsigned long flags;
u32 opc = OPC_INB_SATA_HOST_OPSTART;
memset(&sata_cmd, 0, sizeof(sata_cmd));
circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -4086,8 +4354,10 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
}
}
- if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
+ if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
+ task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
ncg_tag = hdr_tag;
+ }
dir = data_dir_flags[task->data_dir] << 8;
sata_cmd.tag = cpu_to_le32(tag);
sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
@@ -4118,7 +4388,55 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
sata_cmd.len = cpu_to_le32(task->total_xfer_len);
sata_cmd.esgl = 0;
}
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd);
+
+ /* Check for read log for failed drive and return */
+ if (sata_cmd.sata_fis.command == 0x2f) {
+ if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
+ (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
+ (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
+ struct task_status_struct *ts;
+
+ pm8001_ha_dev->id &= 0xDFFFFFFF;
+ ts = &task->task_status;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_GOOD;
+ task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((task->task_state_flags &
+ SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&task->task_state_lock,
+ flags);
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task 0x%p resp 0x%x "
+ " stat 0x%x but aborted by upper layer "
+ "\n", task, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+ } else if (task->uldd_task) {
+ spin_unlock_irqrestore(&task->task_state_lock,
+ flags);
+ pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+ mb();/* ditto */
+ spin_unlock_irq(&pm8001_ha->lock);
+ task->task_done(task);
+ spin_lock_irq(&pm8001_ha->lock);
+ return 0;
+ } else if (!task->uldd_task) {
+ spin_unlock_irqrestore(&task->task_state_lock,
+ flags);
+ pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ task->task_done(task);
+ spin_lock_irq(&pm8001_ha->lock);
+ return 0;
+ }
+ }
+ }
+
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
return ret;
}
@@ -4148,12 +4466,12 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
LINKMODE_AUTO | LINKRATE_15 |
LINKRATE_30 | LINKRATE_60 | phy_id);
- payload.sas_identify.dev_type = SAS_END_DEV;
+ payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
pm8001_ha->sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
- ret = mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
return ret;
}
@@ -4163,7 +4481,7 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
* @num: the inbound queue number
* @phy_id: the phy id which we wanted to start up.
*/
-static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
u8 phy_id)
{
struct phy_stop_req payload;
@@ -4175,12 +4493,12 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
payload.phy_id = cpu_to_le32(phy_id);
- ret = mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
return ret;
}
/**
- * see comments on mpi_reg_resp.
+ * see comments on pm8001_mpi_reg_resp.
*/
static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *pm8001_dev, u32 flag)
@@ -4210,11 +4528,11 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
if (flag == 1)
stp_sspsmp_sata = 0x02; /*direct attached sata */
else {
- if (pm8001_dev->dev_type == SATA_DEV)
+ if (pm8001_dev->dev_type == SAS_SATA_DEV)
stp_sspsmp_sata = 0x00; /* stp*/
- else if (pm8001_dev->dev_type == SAS_END_DEV ||
- pm8001_dev->dev_type == EDGE_DEV ||
- pm8001_dev->dev_type == FANOUT_DEV)
+ else if (pm8001_dev->dev_type == SAS_END_DEVICE ||
+ pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
stp_sspsmp_sata = 0x01; /*ssp or smp*/
}
if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
@@ -4234,14 +4552,14 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
SAS_ADDR_SIZE);
- rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return rc;
}
/**
- * see comments on mpi_reg_resp.
+ * see comments on pm8001_mpi_reg_resp.
*/
-static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
u32 device_id)
{
struct dereg_dev_req payload;
@@ -4255,7 +4573,7 @@ static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
payload.device_id = cpu_to_le32(device_id);
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("unregister device device_id = %d\n", device_id));
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return ret;
}
@@ -4278,7 +4596,7 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
payload.tag = cpu_to_le32(1);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F));
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return ret;
}
@@ -4302,11 +4620,11 @@ static u32 pm8001_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
* @stat: stat.
*/
static irqreturn_t
-pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
- pm8001_chip_interrupt_disable(pm8001_ha);
- process_oq(pm8001_ha);
- pm8001_chip_interrupt_enable(pm8001_ha);
+ pm8001_chip_interrupt_disable(pm8001_ha, vec);
+ process_oq(pm8001_ha, vec);
+ pm8001_chip_interrupt_enable(pm8001_ha, vec);
return IRQ_HANDLED;
}
@@ -4328,7 +4646,7 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
task_abort.device_id = cpu_to_le32(dev_id);
task_abort.tag = cpu_to_le32(cmd_tag);
}
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
return ret;
}
@@ -4337,16 +4655,17 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
* @task: the task we wanted to aborted.
* @flag: the abort flag.
*/
-static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag)
{
u32 opc, device_id;
int rc = TMF_RESP_FUNC_FAILED;
- PM8001_EH_DBG(pm8001_ha, pm8001_printk("cmd_tag = %x, abort task tag"
- " = %x", cmd_tag, task_tag));
- if (pm8001_dev->dev_type == SAS_END_DEV)
+ PM8001_EH_DBG(pm8001_ha,
+ pm8001_printk("cmd_tag = %x, abort task tag = 0x%x",
+ cmd_tag, task_tag));
+ if (pm8001_dev->dev_type == SAS_END_DEVICE)
opc = OPC_INB_SSP_ABORT;
- else if (pm8001_dev->dev_type == SATA_DEV)
+ else if (pm8001_dev->dev_type == SAS_SATA_DEV)
opc = OPC_INB_SATA_ABORT;
else
opc = OPC_INB_SMP_ABORT;/* SMP */
@@ -4364,7 +4683,7 @@ static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
* @ccb: the ccb information.
* @tmf: task management function.
*/
-static int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf)
{
struct sas_task *task = ccb->task;
@@ -4382,11 +4701,11 @@ static int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8);
sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag);
circularQ = &pm8001_ha->inbnd_q_tbl[0];
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0);
return ret;
}
-static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
void *payload)
{
u32 opc = OPC_INB_GET_NVMD_DATA;
@@ -4403,7 +4722,7 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
if (!fw_control_context)
return -ENOMEM;
- fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
+ fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
fw_control_context->len = ioctl_payload->length;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memset(&nvmd_req, 0, sizeof(nvmd_req));
@@ -4462,11 +4781,11 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
default:
break;
}
- rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
return rc;
}
-static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
void *payload)
{
u32 opc = OPC_INB_SET_NVMD_DATA;
@@ -4485,7 +4804,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
return -ENOMEM;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
- ioctl_payload->func_specific,
+ &ioctl_payload->func_specific,
ioctl_payload->length);
memset(&nvmd_req, 0, sizeof(nvmd_req));
rc = pm8001_tag_alloc(pm8001_ha, &tag);
@@ -4542,7 +4861,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
default:
break;
}
- rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
return rc;
}
@@ -4551,7 +4870,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
* @pm8001_ha: our hba card information.
* @fw_flash_updata_info: firmware flash update param
*/
-static int
+int
pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
void *fw_flash_updata_info, u32 tag)
{
@@ -4573,11 +4892,11 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr)));
payload.sgl_addr_hi =
cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr)));
- ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return ret;
}
-static int
+int
pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
void *payload)
{
@@ -4587,29 +4906,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
int rc;
u32 tag;
struct pm8001_ccb_info *ccb;
- void *buffer = NULL;
- dma_addr_t phys_addr;
- u32 phys_addr_hi;
- u32 phys_addr_lo;
+ void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr;
+ dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr;
struct pm8001_ioctl_payload *ioctl_payload = payload;
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
if (!fw_control_context)
return -ENOMEM;
- fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0];
- if (fw_control->len != 0) {
- if (pm8001_mem_alloc(pm8001_ha->pdev,
- (void **)&buffer,
- &phys_addr,
- &phys_addr_hi,
- &phys_addr_lo,
- fw_control->len, 0) != 0) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Mem alloc failure\n"));
- kfree(fw_control_context);
- return -ENOMEM;
- }
- }
+ fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
memcpy(buffer, fw_control->buffer, fw_control->len);
flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len);
@@ -4619,6 +4923,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
flash_update_info.total_image_len = fw_control->size;
fw_control_context->fw_control = fw_control;
fw_control_context->virtAddr = buffer;
+ fw_control_context->phys_addr = phys_addr;
fw_control_context->len = fw_control->len;
rc = pm8001_tag_alloc(pm8001_ha, &tag);
if (rc) {
@@ -4633,7 +4938,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
return rc;
}
-static int
+int
pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *pm8001_dev, u32 state)
{
@@ -4654,7 +4959,7 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
payload.tag = cpu_to_le32(tag);
payload.device_id = cpu_to_le32(pm8001_dev->device_id);
payload.nds = cpu_to_le32(state);
- rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return rc;
}
@@ -4679,7 +4984,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
payload.SSAHOLT = cpu_to_le32(0xd << 25);
payload.sata_hol_tmo = cpu_to_le32(80);
payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
- rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
return rc;
}
@@ -4712,4 +5017,3 @@ const struct pm8001_dispatch pm8001_8001_dispatch = {
.set_dev_state_req = pm8001_chip_set_dev_state_req,
.sas_re_init_req = pm8001_chip_sas_re_initialization,
};
-
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index d437309..d7c1e20 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -131,6 +131,8 @@
#define LINKRATE_30 (0x02 << 8)
#define LINKRATE_60 (0x04 << 8)
+/* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
+#define GSM_SM_BASE 0x4F0000
struct mpi_msg_hdr{
__le32 header; /* Bits [11:0] - Message operation code */
/* Bits [15:12] - Message Category */
@@ -298,7 +300,7 @@ struct local_phy_ctl_resp {
#define OP_BITS 0x0000FF00
-#define ID_BITS 0x0000000F
+#define ID_BITS 0x000000FF
/*
* brief the data structure of PORT Control Command
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 0267c22..3861aa1f 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1,5 +1,5 @@
/*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
*
* Copyright (c) 2008-2009 USI Co., Ltd.
* All rights reserved.
@@ -44,8 +44,16 @@
static struct scsi_transport_template *pm8001_stt;
+/**
+ * chip info structure to identify chip key functionality as
+ * encryption available/not, no of ports, hw specific function ref
+ */
static const struct pm8001_chip_info pm8001_chips[] = {
- [chip_8001] = { 8, &pm8001_8001_dispatch,},
+ [chip_8001] = {0, 8, &pm8001_8001_dispatch,},
+ [chip_8008] = {0, 8, &pm8001_80xx_dispatch,},
+ [chip_8009] = {1, 8, &pm8001_80xx_dispatch,},
+ [chip_8018] = {0, 16, &pm8001_80xx_dispatch,},
+ [chip_8019] = {1, 16, &pm8001_80xx_dispatch,},
};
static int pm8001_id;
@@ -104,8 +112,7 @@ static struct sas_domain_function_template pm8001_transport_ops = {
*@pm8001_ha: our hba structure.
*@phy_id: phy id.
*/
-static void __devinit pm8001_phy_init(struct pm8001_hba_info *pm8001_ha,
- int phy_id)
+static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id)
{
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -141,7 +148,8 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
for (i = 0; i < USI_MAX_MEMCNT; i++) {
if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) {
pci_free_consistent(pm8001_ha->pdev,
- pm8001_ha->memoryMap.region[i].element_size,
+ (pm8001_ha->memoryMap.region[i].total_len +
+ pm8001_ha->memoryMap.region[i].alignment),
pm8001_ha->memoryMap.region[i].virt_ptr,
pm8001_ha->memoryMap.region[i].phys_addr);
}
@@ -155,37 +163,75 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
}
#ifdef PM8001_USE_TASKLET
+
+/**
+ * tasklet for 64 msi-x interrupt handler
+ * @opaque: the passed general host adapter struct
+ * Note: pm8001_tasklet is common for pm8001 & pm80xx
+ */
static void pm8001_tasklet(unsigned long opaque)
{
struct pm8001_hba_info *pm8001_ha;
+ u32 vec;
pm8001_ha = (struct pm8001_hba_info *)opaque;
if (unlikely(!pm8001_ha))
BUG_ON(1);
- PM8001_CHIP_DISP->isr(pm8001_ha);
+ vec = pm8001_ha->int_vector;
+ PM8001_CHIP_DISP->isr(pm8001_ha, vec);
+}
+#endif
+
+static struct pm8001_hba_info *outq_to_hba(u8 *outq)
+{
+ return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
}
+
+/**
+ * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
+ * It obtains the vector number and calls the equivalent bottom
+ * half or services directly.
+ * @opaque: the passed outbound queue/vector. Host structure is
+ * retrieved from the same.
+ */
+static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
+{
+ struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
+ u8 outq = *(u8 *)opaque;
+ irqreturn_t ret = IRQ_HANDLED;
+ if (unlikely(!pm8001_ha))
+ return IRQ_NONE;
+ if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
+ return IRQ_NONE;
+ pm8001_ha->int_vector = outq;
+#ifdef PM8001_USE_TASKLET
+ tasklet_schedule(&pm8001_ha->tasklet);
+#else
+ ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
#endif
+ return ret;
+}
+/**
+ * pm8001_interrupt_handler_intx - main INTx interrupt handler.
+ * @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure.
+ */
- /**
- * pm8001_interrupt - when HBA originate a interrupt,we should invoke this
- * dispatcher to handle each case.
- * @irq: irq number.
- * @opaque: the passed general host adapter struct
- */
-static irqreturn_t pm8001_interrupt(int irq, void *opaque)
+static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
{
struct pm8001_hba_info *pm8001_ha;
irqreturn_t ret = IRQ_HANDLED;
- struct sas_ha_struct *sha = opaque;
+ struct sas_ha_struct *sha = dev_id;
pm8001_ha = sha->lldd_ha;
if (unlikely(!pm8001_ha))
return IRQ_NONE;
if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
return IRQ_NONE;
+
+ pm8001_ha->int_vector = 0;
#ifdef PM8001_USE_TASKLET
tasklet_schedule(&pm8001_ha->tasklet);
#else
- ret = PM8001_CHIP_DISP->isr(pm8001_ha);
+ ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
#endif
return ret;
}
@@ -195,10 +241,14 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque)
* @pm8001_ha:our hba structure.
*
*/
-static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
+ const struct pci_device_id *ent)
{
int i;
spin_lock_init(&pm8001_ha->lock);
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("pm8001_alloc: PHY:%x\n",
+ pm8001_ha->chip->n_phy));
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
pm8001_phy_init(pm8001_ha, i);
pm8001_ha->port[i].wide_port_phymap = 0;
@@ -222,30 +272,57 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE;
pm8001_ha->memoryMap.region[IOP].alignment = 32;
- /* MPI Memory region 3 for consumer Index of inbound queues */
- pm8001_ha->memoryMap.region[CI].num_elements = 1;
- pm8001_ha->memoryMap.region[CI].element_size = 4;
- pm8001_ha->memoryMap.region[CI].total_len = 4;
- pm8001_ha->memoryMap.region[CI].alignment = 4;
-
- /* MPI Memory region 4 for producer Index of outbound queues */
- pm8001_ha->memoryMap.region[PI].num_elements = 1;
- pm8001_ha->memoryMap.region[PI].element_size = 4;
- pm8001_ha->memoryMap.region[PI].total_len = 4;
- pm8001_ha->memoryMap.region[PI].alignment = 4;
-
- /* MPI Memory region 5 inbound queues */
- pm8001_ha->memoryMap.region[IB].num_elements = PM8001_MPI_QUEUE;
- pm8001_ha->memoryMap.region[IB].element_size = 64;
- pm8001_ha->memoryMap.region[IB].total_len = PM8001_MPI_QUEUE * 64;
- pm8001_ha->memoryMap.region[IB].alignment = 64;
-
- /* MPI Memory region 6 outbound queues */
- pm8001_ha->memoryMap.region[OB].num_elements = PM8001_MPI_QUEUE;
- pm8001_ha->memoryMap.region[OB].element_size = 64;
- pm8001_ha->memoryMap.region[OB].total_len = PM8001_MPI_QUEUE * 64;
- pm8001_ha->memoryMap.region[OB].alignment = 64;
+ for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+ /* MPI Memory region 3 for consumer Index of inbound queues */
+ pm8001_ha->memoryMap.region[CI+i].num_elements = 1;
+ pm8001_ha->memoryMap.region[CI+i].element_size = 4;
+ pm8001_ha->memoryMap.region[CI+i].total_len = 4;
+ pm8001_ha->memoryMap.region[CI+i].alignment = 4;
+
+ if ((ent->driver_data) != chip_8001) {
+ /* MPI Memory region 5 inbound queues */
+ pm8001_ha->memoryMap.region[IB+i].num_elements =
+ PM8001_MPI_QUEUE;
+ pm8001_ha->memoryMap.region[IB+i].element_size = 128;
+ pm8001_ha->memoryMap.region[IB+i].total_len =
+ PM8001_MPI_QUEUE * 128;
+ pm8001_ha->memoryMap.region[IB+i].alignment = 128;
+ } else {
+ pm8001_ha->memoryMap.region[IB+i].num_elements =
+ PM8001_MPI_QUEUE;
+ pm8001_ha->memoryMap.region[IB+i].element_size = 64;
+ pm8001_ha->memoryMap.region[IB+i].total_len =
+ PM8001_MPI_QUEUE * 64;
+ pm8001_ha->memoryMap.region[IB+i].alignment = 64;
+ }
+ }
+
+ for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+ /* MPI Memory region 4 for producer Index of outbound queues */
+ pm8001_ha->memoryMap.region[PI+i].num_elements = 1;
+ pm8001_ha->memoryMap.region[PI+i].element_size = 4;
+ pm8001_ha->memoryMap.region[PI+i].total_len = 4;
+ pm8001_ha->memoryMap.region[PI+i].alignment = 4;
+
+ if (ent->driver_data != chip_8001) {
+ /* MPI Memory region 6 Outbound queues */
+ pm8001_ha->memoryMap.region[OB+i].num_elements =
+ PM8001_MPI_QUEUE;
+ pm8001_ha->memoryMap.region[OB+i].element_size = 128;
+ pm8001_ha->memoryMap.region[OB+i].total_len =
+ PM8001_MPI_QUEUE * 128;
+ pm8001_ha->memoryMap.region[OB+i].alignment = 128;
+ } else {
+ /* MPI Memory region 6 Outbound queues */
+ pm8001_ha->memoryMap.region[OB+i].num_elements =
+ PM8001_MPI_QUEUE;
+ pm8001_ha->memoryMap.region[OB+i].element_size = 64;
+ pm8001_ha->memoryMap.region[OB+i].total_len =
+ PM8001_MPI_QUEUE * 64;
+ pm8001_ha->memoryMap.region[OB+i].alignment = 64;
+ }
+ }
/* Memory region write DMA*/
pm8001_ha->memoryMap.region[NVMD].num_elements = 1;
pm8001_ha->memoryMap.region[NVMD].element_size = 4096;
@@ -264,6 +341,9 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB *
sizeof(struct pm8001_ccb_info);
+ /* Memory region for fw flash */
+ pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;
+
for (i = 0; i < USI_MAX_MEMCNT; i++) {
if (pm8001_mem_alloc(pm8001_ha->pdev,
&pm8001_ha->memoryMap.region[i].virt_ptr,
@@ -281,7 +361,7 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr;
for (i = 0; i < PM8001_MAX_DEVICES; i++) {
- pm8001_ha->devices[i].dev_type = NO_DEVICE;
+ pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
pm8001_ha->devices[i].id = i;
pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
pm8001_ha->devices[i].running_req = 0;
@@ -339,10 +419,12 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
ioremap(pm8001_ha->io_mem[logicalBar].membase,
pm8001_ha->io_mem[logicalBar].memsize);
PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PCI: bar %d, logicalBar %d "
- "virt_addr=%lx,len=%d\n", bar, logicalBar,
- (unsigned long)
- pm8001_ha->io_mem[logicalBar].memvirtaddr,
+ pm8001_printk("PCI: bar %d, logicalBar %d ",
+ bar, logicalBar));
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "base addr %llx virt_addr=%llx len=%d\n",
+ (u64)pm8001_ha->io_mem[logicalBar].membase,
+ (u64)pm8001_ha->io_mem[logicalBar].memvirtaddr,
pm8001_ha->io_mem[logicalBar].memsize));
} else {
pm8001_ha->io_mem[logicalBar].membase = 0;
@@ -360,8 +442,10 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
* @ent: ent
* @shost: scsi host struct which has been initialized before.
*/
-static struct pm8001_hba_info *__devinit
-pm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost)
+static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
+ const struct pci_device_id *ent,
+ struct Scsi_Host *shost)
+
{
struct pm8001_hba_info *pm8001_ha;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
@@ -373,7 +457,7 @@ pm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost)
pm8001_ha->pdev = pdev;
pm8001_ha->dev = &pdev->dev;
- pm8001_ha->chip_id = chip_id;
+ pm8001_ha->chip_id = ent->driver_data;
pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id];
pm8001_ha->irq = pdev->irq;
pm8001_ha->sas = sha;
@@ -381,12 +465,22 @@ pm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost)
pm8001_ha->id = pm8001_id++;
pm8001_ha->logging_level = 0x01;
sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
+ /* IOMB size is 128 for 8088/89 controllers */
+ if (pm8001_ha->chip_id != chip_8001)
+ pm8001_ha->iomb_size = IOMB_SIZE_SPCV;
+ else
+ pm8001_ha->iomb_size = IOMB_SIZE_SPC;
+
#ifdef PM8001_USE_TASKLET
+ /**
+ * default tasklet for non msi-x interrupt handler/first msi-x
+ * interrupt handler
+ **/
tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
- (unsigned long)pm8001_ha);
+ (unsigned long)pm8001_ha);
#endif
pm8001_ioremap(pm8001_ha);
- if (!pm8001_alloc(pm8001_ha))
+ if (!pm8001_alloc(pm8001_ha, ent))
return pm8001_ha;
pm8001_free(pm8001_ha);
return NULL;
@@ -433,8 +527,8 @@ static int pci_go_44(struct pci_dev *pdev)
* @shost: scsi host which has been allocated outside.
* @chip_info: our ha struct.
*/
-static int __devinit pm8001_prep_sas_ha_init(struct Scsi_Host * shost,
- const struct pm8001_chip_info *chip_info)
+static int pm8001_prep_sas_ha_init(struct Scsi_Host *shost,
+ const struct pm8001_chip_info *chip_info)
{
int phy_nr, port_nr;
struct asd_sas_phy **arr_phy;
@@ -479,8 +573,8 @@ exit:
* @shost: scsi host which has been allocated outside
* @chip_info: our ha struct.
*/
-static void __devinit pm8001_post_sas_ha_init(struct Scsi_Host *shost,
- const struct pm8001_chip_info *chip_info)
+static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
+ const struct pm8001_chip_info *chip_info)
{
int i = 0;
struct pm8001_hba_info *pm8001_ha;
@@ -511,21 +605,50 @@ static void __devinit pm8001_post_sas_ha_init(struct Scsi_Host *shost,
*/
static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
{
- u8 i;
+ u8 i, j;
#ifdef PM8001_READ_VPD
+ /* For new SPC controllers WWN is stored in flash vpd
+ * For SPC/SPCve controllers WWN is stored in EEPROM
+ * For Older SPC WWN is stored in NVMD
+ */
DECLARE_COMPLETION_ONSTACK(completion);
struct pm8001_ioctl_payload payload;
+ u16 deviceid;
+ pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
pm8001_ha->nvmd_completion = &completion;
- payload.minor_function = 0;
- payload.length = 128;
- payload.func_specific = kzalloc(128, GFP_KERNEL);
+
+ if (pm8001_ha->chip_id == chip_8001) {
+ if (deviceid == 0x8081) {
+ payload.minor_function = 4;
+ payload.length = 4096;
+ } else {
+ payload.minor_function = 0;
+ payload.length = 128;
+ }
+ } else {
+ payload.minor_function = 1;
+ payload.length = 4096;
+ }
+ payload.offset = 0;
+ payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
wait_for_completion(&completion);
+
+ for (i = 0, j = 0; i <= 7; i++, j++) {
+ if (pm8001_ha->chip_id == chip_8001) {
+ if (deviceid == 0x8081)
+ pm8001_ha->sas_addr[j] =
+ payload.func_specific[0x704 + i];
+ } else
+ pm8001_ha->sas_addr[j] =
+ payload.func_specific[0x804 + i];
+ }
+
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
- memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr,
- SAS_ADDR_SIZE);
+ memcpy(&pm8001_ha->phy[i].dev_sas_addr,
+ pm8001_ha->sas_addr, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("phy %d sas_addr = %016llx \n", i,
+ pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));
}
#else
@@ -546,31 +669,50 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
* @chip_info: our ha struct.
* @irq_handler: irq_handler
*/
-static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha,
- irq_handler_t irq_handler)
+static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
{
u32 i = 0, j = 0;
- u32 number_of_intr = 1;
+ u32 number_of_intr;
int flag = 0;
u32 max_entry;
int rc;
+ static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
+
+ /* SPCv controllers supports 64 msi-x */
+ if (pm8001_ha->chip_id == chip_8001) {
+ number_of_intr = 1;
+ flag |= IRQF_DISABLED;
+ } else {
+ number_of_intr = PM8001_MAX_MSIX_VEC;
+ flag &= ~IRQF_SHARED;
+ flag |= IRQF_DISABLED;
+ }
+
max_entry = sizeof(pm8001_ha->msix_entries) /
sizeof(pm8001_ha->msix_entries[0]);
- flag |= IRQF_DISABLED;
for (i = 0; i < max_entry ; i++)
pm8001_ha->msix_entries[i].entry = i;
rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries,
number_of_intr);
pm8001_ha->number_of_intr = number_of_intr;
if (!rc) {
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "pci_enable_msix request ret:%d no of intr %d\n",
+ rc, pm8001_ha->number_of_intr));
+
+ for (i = 0; i < number_of_intr; i++)
+ pm8001_ha->outq[i] = i;
+
for (i = 0; i < number_of_intr; i++) {
+ snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
+ DRV_NAME"%d", i);
if (request_irq(pm8001_ha->msix_entries[i].vector,
- irq_handler, flag, DRV_NAME,
- SHOST_TO_SAS_HA(pm8001_ha->shost))) {
+ pm8001_interrupt_handler_msix, flag,
+ intr_drvname[i], &pm8001_ha->outq[i])) {
for (j = 0; j < i; j++)
free_irq(
pm8001_ha->msix_entries[j].vector,
- SHOST_TO_SAS_HA(pm8001_ha->shost));
+ &pm8001_ha->outq[j]);
pci_disable_msix(pm8001_ha->pdev);
break;
}
@@ -587,22 +729,24 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha,
static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
{
struct pci_dev *pdev;
- irq_handler_t irq_handler = pm8001_interrupt;
int rc;
pdev = pm8001_ha->pdev;
#ifdef PM8001_USE_MSIX
if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
- return pm8001_setup_msix(pm8001_ha, irq_handler);
- else
+ return pm8001_setup_msix(pm8001_ha);
+ else {
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("MSIX not supported!!!\n"));
goto intx;
+ }
#endif
intx:
/* initialize the INT-X interrupt */
- rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME,
- SHOST_TO_SAS_HA(pm8001_ha->shost));
+ rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
+ DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
return rc;
}
@@ -615,17 +759,18 @@ intx:
* pci driver it is invoked, all struct an hardware initilization should be done
* here, also, register interrupt
*/
-static int __devinit pm8001_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int pm8001_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
unsigned int rc;
u32 pci_reg;
+ u8 i = 0;
struct pm8001_hba_info *pm8001_ha;
struct Scsi_Host *shost = NULL;
const struct pm8001_chip_info *chip;
dev_printk(KERN_INFO, &pdev->dev,
- "pm8001: driver version %s\n", DRV_VERSION);
+ "pm80xx: driver version %s\n", DRV_VERSION);
rc = pci_enable_device(pdev);
if (rc)
goto err_out_enable;
@@ -664,25 +809,39 @@ static int __devinit pm8001_pci_probe(struct pci_dev *pdev,
goto err_out_free;
}
pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost));
- pm8001_ha = pm8001_pci_alloc(pdev, chip_8001, shost);
+ /* ent->driver variable is used to differentiate between controllers */
+ pm8001_ha = pm8001_pci_alloc(pdev, ent, shost);
if (!pm8001_ha) {
rc = -ENOMEM;
goto err_out_free;
}
list_add_tail(&pm8001_ha->list, &hba_list);
- PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+ PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
- if (rc)
+ if (rc) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+ "chip_init failed [ret: %d]\n", rc));
goto err_out_ha_free;
+ }
rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha_free;
rc = pm8001_request_irq(pm8001_ha);
- if (rc)
+ if (rc) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+ "pm8001_request_irq failed [ret: %d]\n", rc));
goto err_out_shost;
+ }
+
+ PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
+ if (pm8001_ha->chip_id != chip_8001) {
+ for (i = 1; i < pm8001_ha->number_of_intr; i++)
+ PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
+ /* setup thermal configuration. */
+ pm80xx_set_thermal_config(pm8001_ha);
+ }
- PM8001_CHIP_DISP->interrupt_enable(pm8001_ha);
pm8001_init_sas_add(pm8001_ha);
pm8001_post_sas_ha_init(shost, chip);
rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
@@ -707,7 +866,7 @@ err_out_enable:
return rc;
}
-static void __devexit pm8001_pci_remove(struct pci_dev *pdev)
+static void pm8001_pci_remove(struct pci_dev *pdev)
{
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
struct pm8001_hba_info *pm8001_ha;
@@ -718,14 +877,15 @@ static void __devexit pm8001_pci_remove(struct pci_dev *pdev)
sas_remove_host(pm8001_ha->shost);
list_del(&pm8001_ha->list);
scsi_remove_host(pm8001_ha->shost);
- PM8001_CHIP_DISP->interrupt_disable(pm8001_ha);
- PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+ PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
+ PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
#ifdef PM8001_USE_MSIX
for (i = 0; i < pm8001_ha->number_of_intr; i++)
synchronize_irq(pm8001_ha->msix_entries[i].vector);
for (i = 0; i < pm8001_ha->number_of_intr; i++)
- free_irq(pm8001_ha->msix_entries[i].vector, sha);
+ free_irq(pm8001_ha->msix_entries[i].vector,
+ &pm8001_ha->outq[i]);
pci_disable_msix(pdev);
#else
free_irq(pm8001_ha->irq, sha);
@@ -752,23 +912,23 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
struct pm8001_hba_info *pm8001_ha;
- int i , pos;
+ int i;
u32 device_state;
pm8001_ha = sha->lldd_ha;
flush_workqueue(pm8001_wq);
scsi_block_requests(pm8001_ha->shost);
- pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pos == 0) {
- printk(KERN_ERR " PCI PM not supported\n");
+ if (!pdev->pm_cap) {
+ dev_err(&pdev->dev, " PCI PM not supported\n");
return -ENODEV;
}
- PM8001_CHIP_DISP->interrupt_disable(pm8001_ha);
- PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+ PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
+ PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
#ifdef PM8001_USE_MSIX
for (i = 0; i < pm8001_ha->number_of_intr; i++)
synchronize_irq(pm8001_ha->msix_entries[i].vector);
for (i = 0; i < pm8001_ha->number_of_intr; i++)
- free_irq(pm8001_ha->msix_entries[i].vector, sha);
+ free_irq(pm8001_ha->msix_entries[i].vector,
+ &pm8001_ha->outq[i]);
pci_disable_msix(pdev);
#else
free_irq(pm8001_ha->irq, sha);
@@ -797,6 +957,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
struct pm8001_hba_info *pm8001_ha;
int rc;
+ u8 i = 0;
u32 device_state;
pm8001_ha = sha->lldd_ha;
device_state = pdev->current_state;
@@ -819,19 +980,33 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
if (rc)
goto err_out_disable;
- PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+ /* chip soft rst only for spc */
+ if (pm8001_ha->chip_id == chip_8001) {
+ PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("chip soft reset successful\n"));
+ }
rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
if (rc)
goto err_out_disable;
- PM8001_CHIP_DISP->interrupt_disable(pm8001_ha);
+
+ /* disable all the interrupt bits */
+ PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
+
rc = pm8001_request_irq(pm8001_ha);
if (rc)
goto err_out_disable;
- #ifdef PM8001_USE_TASKLET
+#ifdef PM8001_USE_TASKLET
+ /* default tasklet for non msi-x interrupt handler/first msi-x
+ * interrupt handler */
tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
- (unsigned long)pm8001_ha);
- #endif
- PM8001_CHIP_DISP->interrupt_enable(pm8001_ha);
+ (unsigned long)pm8001_ha);
+#endif
+ PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
+ if (pm8001_ha->chip_id != chip_8001) {
+ for (i = 1; i < pm8001_ha->number_of_intr; i++)
+ PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
+ }
scsi_unblock_requests(pm8001_ha->shost);
return 0;
@@ -842,14 +1017,45 @@ err_out_enable:
return rc;
}
-static struct pci_device_id __devinitdata pm8001_pci_table[] = {
- {
- PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001
- },
+/* update of pci device, vendor id and driver data with
+ * unique value for each of the controller
+ */
+static struct pci_device_id pm8001_pci_table[] = {
+ { PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 },
{
PCI_DEVICE(0x117c, 0x0042),
.driver_data = chip_8001
},
+ /* Support for SPC/SPCv/SPCve controllers */
+ { PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 },
+ { PCI_VDEVICE(PMC_Sierra, 0x8008), chip_8008 },
+ { PCI_VDEVICE(ADAPTEC2, 0x8008), chip_8008 },
+ { PCI_VDEVICE(PMC_Sierra, 0x8018), chip_8018 },
+ { PCI_VDEVICE(ADAPTEC2, 0x8018), chip_8018 },
+ { PCI_VDEVICE(PMC_Sierra, 0x8009), chip_8009 },
+ { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 },
+ { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 },
+ { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8081,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8081,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8001 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8008 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8008 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8009 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8009 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8018 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+ PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8018 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+ PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 },
+ { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+ PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 },
{} /* terminate list */
};
@@ -857,7 +1063,7 @@ static struct pci_driver pm8001_pci_driver = {
.name = DRV_NAME,
.id_table = pm8001_pci_table,
.probe = pm8001_pci_probe,
- .remove = __devexit_p(pm8001_pci_remove),
+ .remove = pm8001_pci_remove,
.suspend = pm8001_pci_suspend,
.resume = pm8001_pci_resume,
};
@@ -869,7 +1075,7 @@ static int __init pm8001_init(void)
{
int rc = -ENOMEM;
- pm8001_wq = alloc_workqueue("pm8001", 0, 0);
+ pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
if (!pm8001_wq)
goto err;
@@ -901,7 +1107,8 @@ module_init(pm8001_init);
module_exit(pm8001_exit);
MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
-MODULE_DESCRIPTION("PMC-Sierra PM8001 SAS/SATA controller driver");
+MODULE_DESCRIPTION(
+ "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver");
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, pm8001_pci_table);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index b961112..a85d73d 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1,5 +1,5 @@
/*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
*
* Copyright (c) 2008-2009 USI Co., Ltd.
* All rights reserved.
@@ -68,7 +68,7 @@ static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag)
clear_bit(tag, bitmap);
}
-static void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
+void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
{
pm8001_tag_clear(pm8001_ha, tag);
}
@@ -212,10 +212,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_GET_EVENTS:
spin_lock_irqsave(&pm8001_ha->lock, flags);
- if (-1 == pm8001_bar4_shift(pm8001_ha,
+ if (pm8001_ha->chip_id == chip_8001) {
+ if (-1 == pm8001_bar4_shift(pm8001_ha,
(phy_id < 4) ? 0x30000 : 0x40000)) {
- spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- return -EINVAL;
+ spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+ return -EINVAL;
+ }
}
{
struct sas_phy *phy = sas_phy->phy;
@@ -228,7 +230,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
phy->loss_of_dword_sync_count = qp[3];
phy->phy_reset_problem_count = qp[4];
}
- pm8001_bar4_shift(pm8001_ha, 0);
+ if (pm8001_ha->chip_id == chip_8001)
+ pm8001_bar4_shift(pm8001_ha, 0);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
return 0;
default:
@@ -249,7 +252,9 @@ void pm8001_scan_start(struct Scsi_Host *shost)
struct pm8001_hba_info *pm8001_ha;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
pm8001_ha = sha->lldd_ha;
- PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
+ /* SAS_RE_INITIALIZATION not available in SPCv/ve */
+ if (pm8001_ha->chip_id == chip_8001)
+ PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
}
@@ -352,7 +357,7 @@ static int sas_find_local_port_id(struct domain_device *dev)
* @tmf: the task management IU
*/
#define DEV_IS_GONE(pm8001_dev) \
- ((!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE)))
+ ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
static int pm8001_task_exec(struct sas_task *task, const int num,
gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
{
@@ -370,7 +375,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
struct task_status_struct *tsm = &t->task_status;
tsm->resp = SAS_TASK_UNDELIVERED;
tsm->stat = SAS_PHY_DOWN;
- if (dev->dev_type != SATA_DEV)
+ if (dev->dev_type != SAS_SATA_DEV)
t->task_done(t);
return 0;
}
@@ -548,7 +553,7 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
{
u32 dev;
for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
- if (pm8001_ha->devices[dev].dev_type == NO_DEVICE) {
+ if (pm8001_ha->devices[dev].dev_type == SAS_PHY_UNUSED) {
pm8001_ha->devices[dev].id = dev;
return &pm8001_ha->devices[dev];
}
@@ -560,13 +565,31 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
}
return NULL;
}
+/**
+ * pm8001_find_dev - find a matching pm8001_device
+ * @pm8001_ha: our hba card information
+ */
+struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
+ u32 device_id)
+{
+ u32 dev;
+ for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
+ if (pm8001_ha->devices[dev].device_id == device_id)
+ return &pm8001_ha->devices[dev];
+ }
+ if (dev == PM8001_MAX_DEVICES) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING "
+ "DEVICE FOUND !!!\n"));
+ }
+ return NULL;
+}
static void pm8001_free_dev(struct pm8001_device *pm8001_dev)
{
u32 id = pm8001_dev->id;
memset(pm8001_dev, 0, sizeof(*pm8001_dev));
pm8001_dev->id = id;
- pm8001_dev->dev_type = NO_DEVICE;
+ pm8001_dev->dev_type = SAS_PHY_UNUSED;
pm8001_dev->device_id = PM8001_MAX_DEVICES;
pm8001_dev->sas_device = NULL;
}
@@ -624,7 +647,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
res = -1;
}
} else {
- if (dev->dev_type == SATA_DEV) {
+ if (dev->dev_type == SAS_SATA_DEV) {
pm8001_device->attached_phy =
dev->rphy->identify.phy_identifier;
flag = 1; /* directly sata*/
@@ -634,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
wait_for_completion(&completion);
- if (dev->dev_type == SAS_END_DEV)
+ if (dev->dev_type == SAS_END_DEVICE)
msleep(50);
pm8001_ha->flags = PM8001F_RUN_TIME;
return 0;
@@ -648,7 +671,7 @@ int pm8001_dev_found(struct domain_device *dev)
return pm8001_dev_found_notify(dev);
}
-static void pm8001_task_done(struct sas_task *task)
+void pm8001_task_done(struct sas_task *task)
{
if (!del_timer(&task->slow_task->timer))
return;
@@ -904,7 +927,7 @@ void pm8001_open_reject_retry(
struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i];
pm8001_dev = ccb->device;
- if (!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE))
+ if (!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))
continue;
if (!device_to_close) {
uintptr_t d = (uintptr_t)pm8001_dev
@@ -995,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
return rc;
}
+/*
+* This function handle the IT_NEXUS_XXX event or completion
+* status code for SSP/SATA/SMP I/O request.
+*/
+int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
+{
+ int rc = TMF_RESP_FUNC_FAILED;
+ struct pm8001_device *pm8001_dev;
+ struct pm8001_hba_info *pm8001_ha;
+ struct sas_phy *phy;
+ u32 device_id = 0;
+
+ if (!dev || !dev->lldd_dev)
+ return -1;
+
+ pm8001_dev = dev->lldd_dev;
+ device_id = pm8001_dev->device_id;
+ pm8001_ha = pm8001_find_ha_by_dev(dev);
+
+ PM8001_EH_DBG(pm8001_ha,
+ pm8001_printk("I_T_Nexus handler invoked !!"));
+
+ phy = sas_get_local_phy(dev);
+
+ if (dev_is_sata(dev)) {
+ DECLARE_COMPLETION_ONSTACK(completion_setstate);
+ if (scsi_is_sas_phy_local(phy)) {
+ rc = 0;
+ goto out;
+ }
+ /* send internal ssp/sata/smp abort command to FW */
+ rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+ dev, 1, 0);
+ msleep(100);
+
+ /* deregister the target device */
+ pm8001_dev_gone_notify(dev);
+ msleep(200);
+
+ /*send phy reset to hard reset target */
+ rc = sas_phy_reset(phy, 1);
+ msleep(2000);
+ pm8001_dev->setds_completion = &completion_setstate;
+
+ wait_for_completion(&completion_setstate);
+ } else {
+ /* send internal ssp/sata/smp abort command to FW */
+ rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+ dev, 1, 0);
+ msleep(100);
+
+ /* deregister the target device */
+ pm8001_dev_gone_notify(dev);
+ msleep(200);
+
+ /*send phy reset to hard reset target */
+ rc = sas_phy_reset(phy, 1);
+ msleep(2000);
+ }
+ PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
+ pm8001_dev->device_id, rc));
+out:
+ sas_put_local_phy(phy);
+
+ return rc;
+}
/* mandatory SAM-3, the task reset the specified LUN*/
int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
{
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 1100820..5708194 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -1,5 +1,5 @@
/*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
*
* Copyright (c) 2008-2009 USI Co., Ltd.
* All rights reserved.
@@ -57,8 +57,8 @@
#include <linux/atomic.h>
#include "pm8001_defs.h"
-#define DRV_NAME "pm8001"
-#define DRV_VERSION "0.1.36"
+#define DRV_NAME "pm80xx"
+#define DRV_VERSION "0.1.37"
#define PM8001_FAIL_LOGGING 0x01 /* Error message logging */
#define PM8001_INIT_LOGGING 0x02 /* driver init logging */
#define PM8001_DISC_LOGGING 0x04 /* discovery layer logging */
@@ -66,8 +66,8 @@
#define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/
#define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */
#define PM8001_MSG_LOGGING 0x40 /* misc message logging */
-#define pm8001_printk(format, arg...) printk(KERN_INFO "%s %d:" format,\
- __func__, __LINE__, ## arg)
+#define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \
+ format, __func__, __LINE__, ## arg)
#define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \
do { \
if (unlikely(HBA->logging_level & LEVEL)) \
@@ -103,11 +103,12 @@ do { \
#define PM8001_READ_VPD
-#define DEV_IS_EXPANDER(type) ((type == EDGE_DEV) || (type == FANOUT_DEV))
+#define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
#define PM8001_NAME_LENGTH 32/* generic length of strings */
extern struct list_head hba_list;
extern const struct pm8001_dispatch pm8001_8001_dispatch;
+extern const struct pm8001_dispatch pm8001_80xx_dispatch;
struct pm8001_hba_info;
struct pm8001_ccb_info;
@@ -131,15 +132,15 @@ struct pm8001_ioctl_payload {
struct pm8001_dispatch {
char *name;
int (*chip_init)(struct pm8001_hba_info *pm8001_ha);
- int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha, u32 signature);
+ int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha);
void (*chip_rst)(struct pm8001_hba_info *pm8001_ha);
int (*chip_ioremap)(struct pm8001_hba_info *pm8001_ha);
void (*chip_iounmap)(struct pm8001_hba_info *pm8001_ha);
- irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha);
+ irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha, u8 vec);
u32 (*is_our_interupt)(struct pm8001_hba_info *pm8001_ha);
- int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha);
- void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha);
- void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha);
+ int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha, u8 vec);
+ void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha, u8 vec);
+ void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha, u8 vec);
void (*make_prd)(struct scatterlist *scatter, int nr, void *prd);
int (*smp_req)(struct pm8001_hba_info *pm8001_ha,
struct pm8001_ccb_info *ccb);
@@ -173,6 +174,7 @@ struct pm8001_dispatch {
};
struct pm8001_chip_info {
+ u32 encrypt;
u32 n_phy;
const struct pm8001_dispatch *dispatch;
};
@@ -204,7 +206,7 @@ struct pm8001_phy {
};
struct pm8001_device {
- enum sas_dev_type dev_type;
+ enum sas_device_type dev_type;
struct domain_device *sas_device;
u32 attached_phy;
u32 id;
@@ -256,7 +258,20 @@ struct mpi_mem_req {
struct mpi_mem region[USI_MAX_MEMCNT];
};
-struct main_cfg_table {
+struct encrypt {
+ u32 cipher_mode;
+ u32 sec_mode;
+ u32 status;
+ u32 flag;
+};
+
+struct sas_phy_attribute_table {
+ u32 phystart1_16[16];
+ u32 outbound_hw_event_pid1_16[16];
+};
+
+union main_cfg_table {
+ struct {
u32 signature;
u32 interface_rev;
u32 firmware_rev;
@@ -292,19 +307,69 @@ struct main_cfg_table {
u32 fatal_err_dump_length1;
u32 hda_mode_flag;
u32 anolog_setup_table_offset;
+ u32 rsvd[4];
+ } pm8001_tbl;
+
+ struct {
+ u32 signature;
+ u32 interface_rev;
+ u32 firmware_rev;
+ u32 max_out_io;
+ u32 max_sgl;
+ u32 ctrl_cap_flag;
+ u32 gst_offset;
+ u32 inbound_queue_offset;
+ u32 outbound_queue_offset;
+ u32 inbound_q_nppd_hppd;
+ u32 rsvd[8];
+ u32 crc_core_dump;
+ u32 rsvd1;
+ u32 upper_event_log_addr;
+ u32 lower_event_log_addr;
+ u32 event_log_size;
+ u32 event_log_severity;
+ u32 upper_pcs_event_log_addr;
+ u32 lower_pcs_event_log_addr;
+ u32 pcs_event_log_size;
+ u32 pcs_event_log_severity;
+ u32 fatal_err_interrupt;
+ u32 fatal_err_dump_offset0;
+ u32 fatal_err_dump_length0;
+ u32 fatal_err_dump_offset1;
+ u32 fatal_err_dump_length1;
+ u32 gpio_led_mapping;
+ u32 analog_setup_table_offset;
+ u32 int_vec_table_offset;
+ u32 phy_attr_table_offset;
+ u32 port_recovery_timer;
+ u32 interrupt_reassertion_delay;
+ } pm80xx_tbl;
};
-struct general_status_table {
+
+union general_status_table {
+ struct {
u32 gst_len_mpistate;
u32 iq_freeze_state0;
u32 iq_freeze_state1;
u32 msgu_tcnt;
u32 iop_tcnt;
- u32 reserved;
+ u32 rsvd;
u32 phy_state[8];
- u32 reserved1;
- u32 reserved2;
- u32 reserved3;
+ u32 gpio_input_val;
+ u32 rsvd1[2];
+ u32 recover_err_info[8];
+ } pm8001_tbl;
+ struct {
+ u32 gst_len_mpistate;
+ u32 iq_freeze_state0;
+ u32 iq_freeze_state1;
+ u32 msgu_tcnt;
+ u32 iop_tcnt;
+ u32 rsvd[9];
+ u32 gpio_input_val;
+ u32 rsvd1[2];
u32 recover_err_info[8];
+ } pm80xx_tbl;
};
struct inbound_queue_table {
u32 element_pri_size_cnt;
@@ -351,15 +416,21 @@ struct pm8001_hba_info {
struct device *dev;
struct pm8001_hba_memspace io_mem[6];
struct mpi_mem_req memoryMap;
+ struct encrypt encrypt_info; /* support encryption */
void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/
void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/
void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/
void __iomem *inbnd_q_tbl_addr;/*Inbound Queue Config Table Addr*/
void __iomem *outbnd_q_tbl_addr;/*Outbound Queue Config Table Addr*/
- struct main_cfg_table main_cfg_tbl;
- struct general_status_table gs_tbl;
- struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM];
- struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM];
+ void __iomem *pspa_q_tbl_addr;
+ /*MPI SAS PHY attributes Queue Config Table Addr*/
+ void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */
+ union main_cfg_table main_cfg_tbl;
+ union general_status_table gs_tbl;
+ struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM];
+ struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM];
+ struct sas_phy_attribute_table phy_attr_table;
+ /* MPI SAS PHY attributes */
u8 sas_addr[SAS_ADDR_SIZE];
struct sas_ha_struct *sas;/* SCSI/SAS glue */
struct Scsi_Host *shost;
@@ -372,10 +443,12 @@ struct pm8001_hba_info {
struct pm8001_port port[PM8001_MAX_PHYS];
u32 id;
u32 irq;
+ u32 iomb_size; /* SPC and SPCV IOMB size */
struct pm8001_device *devices;
struct pm8001_ccb_info *ccb_info;
#ifdef PM8001_USE_MSIX
- struct msix_entry msix_entries[16];/*for msi-x interrupt*/
+ struct msix_entry msix_entries[PM8001_MAX_MSIX_VEC];
+ /*for msi-x interrupt*/
int number_of_intr;/*will be used in remove()*/
#endif
#ifdef PM8001_USE_TASKLET
@@ -383,7 +456,10 @@ struct pm8001_hba_info {
#endif
u32 logging_level;
u32 fw_status;
+ u32 smp_exp_mode;
+ u32 int_vector;
const struct firmware *fw_image;
+ u8 outq[PM8001_MAX_MSIX_VEC];
};
struct pm8001_work {
@@ -419,6 +495,9 @@ struct pm8001_fw_image_header {
#define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10
#define FLASH_UPDATE_DISABLED 0x11
+#define NCQ_READ_LOG_FLAG 0x80000000
+#define NCQ_ABORT_ALL_FLAG 0x40000000
+#define NCQ_2ND_RLE_FLAG 0x20000000
/**
* brief param structure for firmware flash update.
*/
@@ -484,6 +563,7 @@ int pm8001_dev_found(struct domain_device *dev);
void pm8001_dev_gone(struct domain_device *dev);
int pm8001_lu_reset(struct domain_device *dev, u8 *lun);
int pm8001_I_T_nexus_reset(struct domain_device *dev);
+int pm8001_I_T_nexus_event_handler(struct domain_device *dev);
int pm8001_query_task(struct sas_task *task);
void pm8001_open_reject_retry(
struct pm8001_hba_info *pm8001_ha,
@@ -493,6 +573,61 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo,
u32 mem_size, u32 align);
+void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha);
+int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
+ struct inbound_queue_table *circularQ,
+ u32 opCode, void *payload, u32 responseQueue);
+int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
+ u16 messageSize, void **messagePtr);
+u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
+ struct outbound_queue_table *circularQ, u8 bc);
+u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
+ struct outbound_queue_table *circularQ,
+ void **messagePtr1, u8 *pBC);
+int pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_dev, u32 state);
+int pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
+ void *payload);
+int pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
+ void *fw_flash_updata_info, u32 tag);
+int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload);
+int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload);
+int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_ccb_info *ccb,
+ struct pm8001_tmf_task *tmf);
+int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_dev,
+ u8 flag, u32 task_tag, u32 cmd_tag);
+int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, u32 device_id);
+void pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd);
+void pm8001_work_fn(struct work_struct *work);
+int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha,
+ void *data, int handler);
+void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb);
+void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb);
+void pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb);
+int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha,
+ void *piomb);
+void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate);
+void pm8001_get_attached_sas_addr(struct pm8001_phy *phy, u8 *sas_addr);
+void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i);
+int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb);
+int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb);
+int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+struct sas_task *pm8001_alloc_task(void);
+void pm8001_task_done(struct sas_task *task);
+void pm8001_free_task(struct sas_task *task);
+void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag);
+struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
+ u32 device_id);
+int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
+
int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
/* ctl shared API */
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
new file mode 100644
index 0000000..7f77210
--- /dev/null
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -0,0 +1,4131 @@
+/*
+ * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver
+ *
+ * Copyright (c) 2008-2009 PMC-Sierra, Inc.,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+ #include <linux/slab.h>
+ #include "pm8001_sas.h"
+ #include "pm80xx_hwi.h"
+ #include "pm8001_chips.h"
+ #include "pm8001_ctl.h"
+
+#define SMP_DIRECT 1
+#define SMP_INDIRECT 2
+/**
+ * read_main_config_table - read the configure table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
+{
+ void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
+
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature =
+ pm8001_mr32(address, MAIN_SIGNATURE_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev =
+ pm8001_mr32(address, MAIN_INTERFACE_REVISION);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev =
+ pm8001_mr32(address, MAIN_FW_REVISION);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io =
+ pm8001_mr32(address, MAIN_MAX_OUTSTANDING_IO_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl =
+ pm8001_mr32(address, MAIN_MAX_SGL_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag =
+ pm8001_mr32(address, MAIN_CNTRL_CAP_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset =
+ pm8001_mr32(address, MAIN_GST_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset =
+ pm8001_mr32(address, MAIN_IBQ_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset =
+ pm8001_mr32(address, MAIN_OBQ_OFFSET);
+
+ /* read Error Dump Offset and Length */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset0 =
+ pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length0 =
+ pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset1 =
+ pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length1 =
+ pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH);
+
+ /* read GPIO LED settings from the configuration table */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping =
+ pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET);
+
+ /* read analog Setting offset from the configuration table */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.analog_setup_table_offset =
+ pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET);
+
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset =
+ pm8001_mr32(address, MAIN_INT_VECTOR_TABLE_OFFSET);
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset =
+ pm8001_mr32(address, MAIN_SAS_PHY_ATTR_TABLE_OFFSET);
+}
+
+/**
+ * read_general_status_table - read the general status table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
+{
+ void __iomem *address = pm8001_ha->general_stat_tbl_addr;
+ pm8001_ha->gs_tbl.pm80xx_tbl.gst_len_mpistate =
+ pm8001_mr32(address, GST_GSTLEN_MPIS_OFFSET);
+ pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state0 =
+ pm8001_mr32(address, GST_IQ_FREEZE_STATE0_OFFSET);
+ pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state1 =
+ pm8001_mr32(address, GST_IQ_FREEZE_STATE1_OFFSET);
+ pm8001_ha->gs_tbl.pm80xx_tbl.msgu_tcnt =
+ pm8001_mr32(address, GST_MSGUTCNT_OFFSET);
+ pm8001_ha->gs_tbl.pm80xx_tbl.iop_tcnt =
+ pm8001_mr32(address, GST_IOPTCNT_OFFSET);
+ pm8001_ha->gs_tbl.pm80xx_tbl.gpio_input_val =
+ pm8001_mr32(address, GST_GPIO_INPUT_VAL);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[0] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET0);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[1] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET1);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[2] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET2);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[3] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET3);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[4] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET4);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[5] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET5);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[6] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET6);
+ pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[7] =
+ pm8001_mr32(address, GST_RERRINFO_OFFSET7);
+}
+/**
+ * read_phy_attr_table - read the phy attribute table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_phy_attr_table(struct pm8001_hba_info *pm8001_ha)
+{
+ void __iomem *address = pm8001_ha->pspa_q_tbl_addr;
+ pm8001_ha->phy_attr_table.phystart1_16[0] =
+ pm8001_mr32(address, PSPA_PHYSTATE0_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[1] =
+ pm8001_mr32(address, PSPA_PHYSTATE1_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[2] =
+ pm8001_mr32(address, PSPA_PHYSTATE2_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[3] =
+ pm8001_mr32(address, PSPA_PHYSTATE3_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[4] =
+ pm8001_mr32(address, PSPA_PHYSTATE4_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[5] =
+ pm8001_mr32(address, PSPA_PHYSTATE5_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[6] =
+ pm8001_mr32(address, PSPA_PHYSTATE6_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[7] =
+ pm8001_mr32(address, PSPA_PHYSTATE7_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[8] =
+ pm8001_mr32(address, PSPA_PHYSTATE8_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[9] =
+ pm8001_mr32(address, PSPA_PHYSTATE9_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[10] =
+ pm8001_mr32(address, PSPA_PHYSTATE10_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[11] =
+ pm8001_mr32(address, PSPA_PHYSTATE11_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[12] =
+ pm8001_mr32(address, PSPA_PHYSTATE12_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[13] =
+ pm8001_mr32(address, PSPA_PHYSTATE13_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[14] =
+ pm8001_mr32(address, PSPA_PHYSTATE14_OFFSET);
+ pm8001_ha->phy_attr_table.phystart1_16[15] =
+ pm8001_mr32(address, PSPA_PHYSTATE15_OFFSET);
+
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[0] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID0_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[1] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID1_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[2] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID2_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[3] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID3_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[4] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID4_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[5] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID5_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[6] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID6_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[7] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID7_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[8] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID8_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[9] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID9_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[10] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID10_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[11] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID11_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[12] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID12_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[13] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID13_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[14] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID14_OFFSET);
+ pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[15] =
+ pm8001_mr32(address, PSPA_OB_HW_EVENT_PID15_OFFSET);
+
+}
+
+/**
+ * read_inbnd_queue_table - read the inbound queue table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+{
+ int i;
+ void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
+ for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+ u32 offset = i * 0x20;
+ pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
+ get_pci_bar_index(pm8001_mr32(address,
+ (offset + IB_PIPCI_BAR)));
+ pm8001_ha->inbnd_q_tbl[i].pi_offset =
+ pm8001_mr32(address, (offset + IB_PIPCI_BAR_OFFSET));
+ }
+}
+
+/**
+ * read_outbnd_queue_table - read the outbound queue table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+{
+ int i;
+ void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
+ for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+ u32 offset = i * 0x24;
+ pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
+ get_pci_bar_index(pm8001_mr32(address,
+ (offset + OB_CIPCI_BAR)));
+ pm8001_ha->outbnd_q_tbl[i].ci_offset =
+ pm8001_mr32(address, (offset + OB_CIPCI_BAR_OFFSET));
+ }
+}
+
+/**
+ * init_default_table_values - init the default table.
+ * @pm8001_ha: our hba card information
+ */
+static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
+{
+ int i;
+ u32 offsetib, offsetob;
+ void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
+ void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
+
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr =
+ pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr =
+ pm8001_ha->memoryMap.region[AAP1].phys_addr_lo;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size =
+ PM8001_EVENT_LOG_SIZE;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity = 0x01;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr =
+ pm8001_ha->memoryMap.region[IOP].phys_addr_hi;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr =
+ pm8001_ha->memoryMap.region[IOP].phys_addr_lo;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size =
+ PM8001_EVENT_LOG_SIZE;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01;
+
+ /* Disable end to end CRC checking */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
+
+ for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+ pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
+ PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
+ pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
+ pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
+ pm8001_ha->inbnd_q_tbl[i].lower_base_addr =
+ pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
+ pm8001_ha->inbnd_q_tbl[i].base_virt =
+ (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
+ pm8001_ha->inbnd_q_tbl[i].total_length =
+ pm8001_ha->memoryMap.region[IB + i].total_len;
+ pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr =
+ pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
+ pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr =
+ pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
+ pm8001_ha->inbnd_q_tbl[i].ci_virt =
+ pm8001_ha->memoryMap.region[CI + i].virt_ptr;
+ offsetib = i * 0x20;
+ pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
+ get_pci_bar_index(pm8001_mr32(addressib,
+ (offsetib + 0x14)));
+ pm8001_ha->inbnd_q_tbl[i].pi_offset =
+ pm8001_mr32(addressib, (offsetib + 0x18));
+ pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;
+ pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;
+ }
+ for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+ pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
+ PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
+ pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
+ pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
+ pm8001_ha->outbnd_q_tbl[i].lower_base_addr =
+ pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
+ pm8001_ha->outbnd_q_tbl[i].base_virt =
+ (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
+ pm8001_ha->outbnd_q_tbl[i].total_length =
+ pm8001_ha->memoryMap.region[OB + i].total_len;
+ pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr =
+ pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
+ pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
+ pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
+ /* interrupt vector based on oq */
+ pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24);
+ pm8001_ha->outbnd_q_tbl[i].pi_virt =
+ pm8001_ha->memoryMap.region[PI + i].virt_ptr;
+ offsetob = i * 0x24;
+ pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
+ get_pci_bar_index(pm8001_mr32(addressob,
+ offsetob + 0x14));
+ pm8001_ha->outbnd_q_tbl[i].ci_offset =
+ pm8001_mr32(addressob, (offsetob + 0x18));
+ pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0;
+ pm8001_ha->outbnd_q_tbl[i].producer_index = 0;
+ }
+}
+
+/**
+ * update_main_config_table - update the main default table to the HBA.
+ * @pm8001_ha: our hba card information
+ */
+static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
+{
+ void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
+ pm8001_mw32(address, MAIN_IQNPPD_HPPD_OFFSET,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_q_nppd_hppd);
+ pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_HI,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr);
+ pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_LO,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr);
+ pm8001_mw32(address, MAIN_EVENT_LOG_BUFF_SIZE,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size);
+ pm8001_mw32(address, MAIN_EVENT_LOG_OPTION,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity);
+ pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_HI,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr);
+ pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_LO,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr);
+ pm8001_mw32(address, MAIN_PCS_EVENT_LOG_BUFF_SIZE,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
+ pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
+ pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
+ pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);
+
+ /* SPCv specific */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF;
+ /* Set GPIOLED to 0x2 for LED indicator */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;
+ pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);
+
+ pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
+ pm8001_mw32(address, MAIN_INT_REASSERTION_DELAY,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.interrupt_reassertion_delay);
+}
+
+/**
+ * update_inbnd_queue_table - update the inbound queue table to the HBA.
+ * @pm8001_ha: our hba card information
+ */
+static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+ int number)
+{
+ void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
+ u16 offset = number * 0x20;
+ pm8001_mw32(address, offset + IB_PROPERITY_OFFSET,
+ pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);
+ pm8001_mw32(address, offset + IB_BASE_ADDR_HI_OFFSET,
+ pm8001_ha->inbnd_q_tbl[number].upper_base_addr);
+ pm8001_mw32(address, offset + IB_BASE_ADDR_LO_OFFSET,
+ pm8001_ha->inbnd_q_tbl[number].lower_base_addr);
+ pm8001_mw32(address, offset + IB_CI_BASE_ADDR_HI_OFFSET,
+ pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);
+ pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,
+ pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
+}
+
+/**
+ * update_outbnd_queue_table - update the outbound queue table to the HBA.
+ * @pm8001_ha: our hba card information
+ */
+static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+ int number)
+{
+ void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
+ u16 offset = number * 0x24;
+ pm8001_mw32(address, offset + OB_PROPERITY_OFFSET,
+ pm8001_ha->outbnd_q_tbl[number].element_size_cnt);
+ pm8001_mw32(address, offset + OB_BASE_ADDR_HI_OFFSET,
+ pm8001_ha->outbnd_q_tbl[number].upper_base_addr);
+ pm8001_mw32(address, offset + OB_BASE_ADDR_LO_OFFSET,
+ pm8001_ha->outbnd_q_tbl[number].lower_base_addr);
+ pm8001_mw32(address, offset + OB_PI_BASE_ADDR_HI_OFFSET,
+ pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr);
+ pm8001_mw32(address, offset + OB_PI_BASE_ADDR_LO_OFFSET,
+ pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
+ pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,
+ pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);
+}
+
+/**
+ * mpi_init_check - check firmware initialization status.
+ * @pm8001_ha: our hba card information
+ */
+static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 max_wait_count;
+ u32 value;
+ u32 gst_len_mpistate;
+
+ /* Write bit0=1 to Inbound DoorBell Register to tell the SPC FW the
+ table is updated */
+ pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);
+ /* wait until Inbound DoorBell Clear Register toggled */
+ max_wait_count = 2 * 1000 * 1000;/* 2 sec for spcv/ve */
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);
+ value &= SPCv_MSGU_CFG_TABLE_UPDATE;
+ } while ((value != 0) && (--max_wait_count));
+
+ if (!max_wait_count)
+ return -1;
+ /* check the MPI-State for initialization upto 100ms*/
+ max_wait_count = 100 * 1000;/* 100 msec */
+ do {
+ udelay(1);
+ gst_len_mpistate =
+ pm8001_mr32(pm8001_ha->general_stat_tbl_addr,
+ GST_GSTLEN_MPIS_OFFSET);
+ } while ((GST_MPI_STATE_INIT !=
+ (gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count));
+ if (!max_wait_count)
+ return -1;
+
+ /* check MPI Initialization error */
+ gst_len_mpistate = gst_len_mpistate >> 16;
+ if (0x0000 != gst_len_mpistate)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * check_fw_ready - The LLDD check if the FW is ready, if not, return error.
+ * @pm8001_ha: our hba card information
+ */
+static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 value;
+ u32 max_wait_count;
+ u32 max_wait_time;
+ int ret = 0;
+
+ /* reset / PCIe ready */
+ max_wait_time = max_wait_count = 100 * 1000; /* 100 milli sec */
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+ } while ((value == 0xFFFFFFFF) && (--max_wait_count));
+
+ /* check ila status */
+ max_wait_time = max_wait_count = 1000 * 1000; /* 1000 milli sec */
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+ } while (((value & SCRATCH_PAD_ILA_READY) !=
+ SCRATCH_PAD_ILA_READY) && (--max_wait_count));
+ if (!max_wait_count)
+ ret = -1;
+ else {
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" ila ready status in %d millisec\n",
+ (max_wait_time - max_wait_count)));
+ }
+
+ /* check RAAE status */
+ max_wait_time = max_wait_count = 1800 * 1000; /* 1800 milli sec */
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+ } while (((value & SCRATCH_PAD_RAAE_READY) !=
+ SCRATCH_PAD_RAAE_READY) && (--max_wait_count));
+ if (!max_wait_count)
+ ret = -1;
+ else {
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" raae ready status in %d millisec\n",
+ (max_wait_time - max_wait_count)));
+ }
+
+ /* check iop0 status */
+ max_wait_time = max_wait_count = 600 * 1000; /* 600 milli sec */
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+ } while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) &&
+ (--max_wait_count));
+ if (!max_wait_count)
+ ret = -1;
+ else {
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" iop0 ready status in %d millisec\n",
+ (max_wait_time - max_wait_count)));
+ }
+
+ /* check iop1 status only for 16 port controllers */
+ if ((pm8001_ha->chip_id != chip_8008) &&
+ (pm8001_ha->chip_id != chip_8009)) {
+ /* 200 milli sec */
+ max_wait_time = max_wait_count = 200 * 1000;
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+ } while (((value & SCRATCH_PAD_IOP1_READY) !=
+ SCRATCH_PAD_IOP1_READY) && (--max_wait_count));
+ if (!max_wait_count)
+ ret = -1;
+ else {
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "iop1 ready status in %d millisec\n",
+ (max_wait_time - max_wait_count)));
+ }
+ }
+
+ return ret;
+}
+
+static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
+{
+ void __iomem *base_addr;
+ u32 value;
+ u32 offset;
+ u32 pcibar;
+ u32 pcilogic;
+
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
+ offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n",
+ offset, value));
+ pcilogic = (value & 0xFC000000) >> 26;
+ pcibar = get_pci_bar_index(pcilogic);
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar));
+ pm8001_ha->main_cfg_tbl_addr = base_addr =
+ pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
+ pm8001_ha->general_stat_tbl_addr =
+ base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x18) &
+ 0xFFFFFF);
+ pm8001_ha->inbnd_q_tbl_addr =
+ base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C) &
+ 0xFFFFFF);
+ pm8001_ha->outbnd_q_tbl_addr =
+ base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x20) &
+ 0xFFFFFF);
+ pm8001_ha->ivt_tbl_addr =
+ base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C) &
+ 0xFFFFFF);
+ pm8001_ha->pspa_q_tbl_addr =
+ base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) &
+ 0xFFFFFF);
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("GST OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x18)));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("INBND OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C)));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("OBND OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x20)));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("IVT OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C)));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("PSPA OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x90)));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("addr - main cfg %p general status %p\n",
+ pm8001_ha->main_cfg_tbl_addr,
+ pm8001_ha->general_stat_tbl_addr));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("addr - inbnd %p obnd %p\n",
+ pm8001_ha->inbnd_q_tbl_addr,
+ pm8001_ha->outbnd_q_tbl_addr));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("addr - pspa %p ivt %p\n",
+ pm8001_ha->pspa_q_tbl_addr,
+ pm8001_ha->ivt_tbl_addr));
+}
+
+/**
+ * pm80xx_set_thermal_config - support the thermal configuration
+ * @pm8001_ha: our hba card information.
+ */
+int
+pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
+{
+ struct set_ctrl_cfg_req payload;
+ struct inbound_queue_table *circularQ;
+ int rc;
+ u32 tag;
+ u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
+
+ memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
+ rc = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (rc)
+ return -1;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ payload.tag = cpu_to_le32(tag);
+ payload.cfg_pg[0] = (THERMAL_LOG_ENABLE << 9) |
+ (THERMAL_ENABLE << 8) | THERMAL_OP_CODE;
+ payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ return rc;
+
+}
+
+/**
+* pm80xx_set_sas_protocol_timer_config - support the SAS Protocol
+* Timer configuration page
+* @pm8001_ha: our hba card information.
+*/
+static int
+pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
+{
+ struct set_ctrl_cfg_req payload;
+ struct inbound_queue_table *circularQ;
+ SASProtocolTimerConfig_t SASConfigPage;
+ int rc;
+ u32 tag;
+ u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
+
+ memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
+ memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t));
+
+ rc = pm8001_tag_alloc(pm8001_ha, &tag);
+
+ if (rc)
+ return -1;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ payload.tag = cpu_to_le32(tag);
+
+ SASConfigPage.pageCode = SAS_PROTOCOL_TIMER_CONFIG_PAGE;
+ SASConfigPage.MST_MSI = 3 << 15;
+ SASConfigPage.STP_SSP_MCT_TMO = (STP_MCT_TMO << 16) | SSP_MCT_TMO;
+ SASConfigPage.STP_FRM_TMO = (SAS_MAX_OPEN_TIME << 24) |
+ (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER;
+ SASConfigPage.STP_IDLE_TMO = STP_IDLE_TIME;
+
+ if (SASConfigPage.STP_IDLE_TMO > 0x3FFFFFF)
+ SASConfigPage.STP_IDLE_TMO = 0x3FFFFFF;
+
+
+ SASConfigPage.OPNRJT_RTRY_INTVL = (SAS_MFD << 16) |
+ SAS_OPNRJT_RTRY_INTVL;
+ SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO = (SAS_DOPNRJT_RTRY_TMO << 16)
+ | SAS_COPNRJT_RTRY_TMO;
+ SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR = (SAS_DOPNRJT_RTRY_THR << 16)
+ | SAS_COPNRJT_RTRY_THR;
+ SASConfigPage.MAX_AIP = SAS_MAX_AIP;
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.pageCode "
+ "0x%08x\n", SASConfigPage.pageCode));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.MST_MSI "
+ " 0x%08x\n", SASConfigPage.MST_MSI));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.STP_SSP_MCT_TMO "
+ " 0x%08x\n", SASConfigPage.STP_SSP_MCT_TMO));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.STP_FRM_TMO "
+ " 0x%08x\n", SASConfigPage.STP_FRM_TMO));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.STP_IDLE_TMO "
+ " 0x%08x\n", SASConfigPage.STP_IDLE_TMO));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.OPNRJT_RTRY_INTVL "
+ " 0x%08x\n", SASConfigPage.OPNRJT_RTRY_INTVL));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO "
+ " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR "
+ " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SASConfigPage.MAX_AIP "
+ " 0x%08x\n", SASConfigPage.MAX_AIP));
+
+ memcpy(&payload.cfg_pg, &SASConfigPage,
+ sizeof(SASProtocolTimerConfig_t));
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+
+ return rc;
+}
+
+/**
+ * pm80xx_get_encrypt_info - Check for encryption
+ * @pm8001_ha: our hba card information.
+ */
+static int
+pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 scratch3_value;
+ int ret;
+
+ /* Read encryption status from SCRATCH PAD 3 */
+ scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
+
+ if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
+ SCRATCH_PAD3_ENC_READY) {
+ if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
+ pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMF_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMA_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMB_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
+ pm8001_ha->encrypt_info.status = 0;
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X."
+ "Cipher mode 0x%x Sec mode 0x%x status 0x%x\n",
+ scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
+ pm8001_ha->encrypt_info.sec_mode,
+ pm8001_ha->encrypt_info.status));
+ ret = 0;
+ } else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) ==
+ SCRATCH_PAD3_ENC_DISABLED) {
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n",
+ scratch3_value));
+ pm8001_ha->encrypt_info.status = 0xFFFFFFFF;
+ pm8001_ha->encrypt_info.cipher_mode = 0;
+ pm8001_ha->encrypt_info.sec_mode = 0;
+ return 0;
+ } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
+ SCRATCH_PAD3_ENC_DIS_ERR) {
+ pm8001_ha->encrypt_info.status =
+ (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;
+ if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
+ pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMF_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMA_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMB_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X."
+ "Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
+ scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
+ pm8001_ha->encrypt_info.sec_mode,
+ pm8001_ha->encrypt_info.status));
+ ret = -1;
+ } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
+ SCRATCH_PAD3_ENC_ENA_ERR) {
+
+ pm8001_ha->encrypt_info.status =
+ (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;
+ if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
+ pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMF_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMA_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
+ if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+ SCRATCH_PAD3_SMB_ENABLED)
+ pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
+
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X."
+ "Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
+ scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
+ pm8001_ha->encrypt_info.sec_mode,
+ pm8001_ha->encrypt_info.status));
+ ret = -1;
+ }
+ return ret;
+}
+
+/**
+ * pm80xx_encrypt_update - update flash with encryption informtion
+ * @pm8001_ha: our hba card information.
+ */
+static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
+{
+ struct kek_mgmt_req payload;
+ struct inbound_queue_table *circularQ;
+ int rc;
+ u32 tag;
+ u32 opc = OPC_INB_KEK_MANAGEMENT;
+
+ memset(&payload, 0, sizeof(struct kek_mgmt_req));
+ rc = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (rc)
+ return -1;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ payload.tag = cpu_to_le32(tag);
+ /* Currently only one key is used. New KEK index is 1.
+ * Current KEK index is 1. Store KEK to NVRAM is 1.
+ */
+ payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
+ KEK_MGMT_SUBOP_KEYCARDUPDATE);
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+
+ return rc;
+}
+
+/**
+ * pm8001_chip_init - the main init function that initialize whole PM8001 chip.
+ * @pm8001_ha: our hba card information
+ */
+static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
+{
+ int ret;
+ u8 i = 0;
+
+ /* check the firmware status */
+ if (-1 == check_fw_ready(pm8001_ha)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("Firmware is not ready!\n"));
+ return -EBUSY;
+ }
+
+ /* Initialize pci space address eg: mpi offset */
+ init_pci_device_addresses(pm8001_ha);
+ init_default_table_values(pm8001_ha);
+ read_main_config_table(pm8001_ha);
+ read_general_status_table(pm8001_ha);
+ read_inbnd_queue_table(pm8001_ha);
+ read_outbnd_queue_table(pm8001_ha);
+ read_phy_attr_table(pm8001_ha);
+
+ /* update main config table ,inbound table and outbound table */
+ update_main_config_table(pm8001_ha);
+ for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++)
+ update_inbnd_queue_table(pm8001_ha, i);
+ for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++)
+ update_outbnd_queue_table(pm8001_ha, i);
+
+ /* notify firmware update finished and check initialization status */
+ if (0 == mpi_init_check(pm8001_ha)) {
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("MPI initialize successful!\n"));
+ } else
+ return -EBUSY;
+
+ /* send SAS protocol timer configuration page to FW */
+ ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha);
+
+ /* Check for encryption */
+ if (pm8001_ha->chip->encrypt) {
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("Checking for encryption\n"));
+ ret = pm80xx_get_encrypt_info(pm8001_ha);
+ if (ret == -1) {
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("Encryption error !!\n"));
+ if (pm8001_ha->encrypt_info.status == 0x81) {
+ PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+ "Encryption enabled with error."
+ "Saving encryption key to flash\n"));
+ pm80xx_encrypt_update(pm8001_ha);
+ }
+ }
+ }
+ return 0;
+}
+
+static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 max_wait_count;
+ u32 value;
+ u32 gst_len_mpistate;
+ init_pci_device_addresses(pm8001_ha);
+ /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
+ table is stop */
+ pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET);
+
+ /* wait until Inbound DoorBell Clear Register toggled */
+ max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */
+ do {
+ udelay(1);
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);
+ value &= SPCv_MSGU_CFG_TABLE_RESET;
+ } while ((value != 0) && (--max_wait_count));
+
+ if (!max_wait_count) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("TIMEOUT:IBDB value/=%x\n", value));
+ return -1;
+ }
+
+ /* check the MPI-State for termination in progress */
+ /* wait until Inbound DoorBell Clear Register toggled */
+ max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */
+ do {
+ udelay(1);
+ gst_len_mpistate =
+ pm8001_mr32(pm8001_ha->general_stat_tbl_addr,
+ GST_GSTLEN_MPIS_OFFSET);
+ if (GST_MPI_STATE_UNINIT ==
+ (gst_len_mpistate & GST_MPI_STATE_MASK))
+ break;
+ } while (--max_wait_count);
+ if (!max_wait_count) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk(" TIME OUT MPI State = 0x%x\n",
+ gst_len_mpistate & GST_MPI_STATE_MASK));
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all
+ * the FW register status to the originated status.
+ * @pm8001_ha: our hba card information
+ */
+
+static int
+pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 regval;
+ u32 bootloader_state;
+
+ /* Check if MPI is in ready state to reset */
+ if (mpi_uninit_check(pm8001_ha) != 0) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("MPI state is not ready\n"));
+ return -1;
+ }
+
+ /* checked for reset register normal state; 0x0 */
+ regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("reset register before write : 0x%x\n", regval));
+
+ pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);
+ mdelay(500);
+
+ regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("reset register after write 0x%x\n", regval));
+
+ if ((regval & SPCv_SOFT_RESET_READ_MASK) ==
+ SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) {
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" soft reset successful [regval: 0x%x]\n",
+ regval));
+ } else {
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" soft reset failed [regval: 0x%x]\n",
+ regval));
+
+ /* check bootloader is successfully executed or in HDA mode */
+ bootloader_state =
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1) &
+ SCRATCH_PAD1_BOOTSTATE_MASK;
+
+ if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) {
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "Bootloader state - HDA mode SEEPROM\n"));
+ } else if (bootloader_state ==
+ SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) {
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "Bootloader state - HDA mode Bootstrap Pin\n"));
+ } else if (bootloader_state ==
+ SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) {
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "Bootloader state - HDA mode soft reset\n"));
+ } else if (bootloader_state ==
+ SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) {
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "Bootloader state-HDA mode critical error\n"));
+ }
+ return -EBUSY;
+ }
+
+ /* check the firmware status after reset */
+ if (-1 == check_fw_ready(pm8001_ha)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("Firmware is not ready!\n"));
+ return -EBUSY;
+ }
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SPCv soft reset Complete\n"));
+ return 0;
+}
+
+static void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 i;
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("chip reset start\n"));
+
+ /* do SPCv chip reset. */
+ pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11);
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("SPC soft reset Complete\n"));
+
+ /* Check this ..whether delay is required or no */
+ /* delay 10 usec */
+ udelay(10);
+
+ /* wait for 20 msec until the firmware gets reloaded */
+ i = 20;
+ do {
+ mdelay(1);
+ } while ((--i) != 0);
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("chip reset finished\n"));
+}
+
+/**
+ * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_intx_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
+{
+ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL);
+ pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL);
+}
+
+/**
+ * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
+{
+ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, ODMR_MASK_ALL);
+}
+
+/**
+ * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+#ifdef PM8001_USE_MSIX
+ u32 mask;
+ mask = (u32)(1 << vec);
+
+ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, (u32)(mask & 0xFFFFFFFF));
+ return;
+#endif
+ pm80xx_chip_intx_interrupt_enable(pm8001_ha);
+
+}
+
+/**
+ * pm8001_chip_interrupt_disable- disable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+#ifdef PM8001_USE_MSIX
+ u32 mask;
+ if (vec == 0xFF)
+ mask = 0xFFFFFFFF;
+ else
+ mask = (u32)(1 << vec);
+ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, (u32)(mask & 0xFFFFFFFF));
+ return;
+#endif
+ pm80xx_chip_intx_interrupt_disable(pm8001_ha);
+}
+
+static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_ha_dev)
+{
+ int res;
+ u32 ccb_tag;
+ struct pm8001_ccb_info *ccb;
+ struct sas_task *task = NULL;
+ struct task_abort_req task_abort;
+ struct inbound_queue_table *circularQ;
+ u32 opc = OPC_INB_SATA_ABORT;
+ int ret;
+
+ if (!pm8001_ha_dev) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
+ return;
+ }
+
+ task = sas_alloc_slow_task(GFP_ATOMIC);
+
+ if (!task) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
+ "allocate task\n"));
+ return;
+ }
+
+ task->task_done = pm8001_task_done;
+
+ res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+ if (res)
+ return;
+
+ ccb = &pm8001_ha->ccb_info[ccb_tag];
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
+
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ memset(&task_abort, 0, sizeof(task_abort));
+ task_abort.abort_all = cpu_to_le32(1);
+ task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+ task_abort.tag = cpu_to_le32(ccb_tag);
+
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+
+}
+
+static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_ha_dev)
+{
+ struct sata_start_req sata_cmd;
+ int res;
+ u32 ccb_tag;
+ struct pm8001_ccb_info *ccb;
+ struct sas_task *task = NULL;
+ struct host_to_dev_fis fis;
+ struct domain_device *dev;
+ struct inbound_queue_table *circularQ;
+ u32 opc = OPC_INB_SATA_HOST_OPSTART;
+
+ task = sas_alloc_slow_task(GFP_ATOMIC);
+
+ if (!task) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("cannot allocate task !!!\n"));
+ return;
+ }
+ task->task_done = pm8001_task_done;
+
+ res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+ if (res) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("cannot allocate tag !!!\n"));
+ return;
+ }
+
+ /* allocate domain device by ourselves as libsas
+ * is not going to provide any
+ */
+ dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
+ if (!dev) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("Domain device cannot be allocated\n"));
+ sas_free_task(task);
+ return;
+ } else {
+ task->dev = dev;
+ task->dev->lldd_dev = pm8001_ha_dev;
+ }
+
+ ccb = &pm8001_ha->ccb_info[ccb_tag];
+ ccb->device = pm8001_ha_dev;
+ ccb->ccb_tag = ccb_tag;
+ ccb->task = task;
+ pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
+ pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
+
+ memset(&sata_cmd, 0, sizeof(sata_cmd));
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ /* construct read log FIS */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.fis_type = 0x27;
+ fis.flags = 0x80;
+ fis.command = ATA_CMD_READ_LOG_EXT;
+ fis.lbal = 0x10;
+ fis.sector_count = 0x1;
+
+ sata_cmd.tag = cpu_to_le32(ccb_tag);
+ sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+ sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
+ memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+ res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+
+}
+
+/**
+ * mpi_ssp_completion- process the event that FW response to the SSP request.
+ * @pm8001_ha: our hba card information
+ * @piomb: the message contents of this outbound message.
+ *
+ * When FW has completed a ssp request for example a IO request, after it has
+ * filled the SG data with the data, it will trigger this event represent
+ * that he has finished the job,please check the coresponding buffer.
+ * So we will tell the caller who maybe waiting the result to tell upper layer
+ * that the task has been finished.
+ */
+static void
+mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
+{
+ struct sas_task *t;
+ struct pm8001_ccb_info *ccb;
+ unsigned long flags;
+ u32 status;
+ u32 param;
+ u32 tag;
+ struct ssp_completion_resp *psspPayload;
+ struct task_status_struct *ts;
+ struct ssp_response_iu *iu;
+ struct pm8001_device *pm8001_dev;
+ psspPayload = (struct ssp_completion_resp *)(piomb + 4);
+ status = le32_to_cpu(psspPayload->status);
+ tag = le32_to_cpu(psspPayload->tag);
+ ccb = &pm8001_ha->ccb_info[tag];
+ if ((status == IO_ABORTED) && ccb->open_retry) {
+ /* Being completed by another */
+ ccb->open_retry = 0;
+ return;
+ }
+ pm8001_dev = ccb->device;
+ param = le32_to_cpu(psspPayload->param);
+ t = ccb->task;
+
+ if (status && status != IO_UNDERFLOW)
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("sas IO status 0x%x\n", status));
+ if (unlikely(!t || !t->lldd_task || !t->dev))
+ return;
+ ts = &t->task_status;
+ switch (status) {
+ case IO_SUCCESS:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_SUCCESS ,param = 0x%x\n",
+ param));
+ if (param == 0) {
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_GOOD;
+ } else {
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_PROTO_RESPONSE;
+ ts->residual = param;
+ iu = &psspPayload->ssp_resp_iu;
+ sas_ssp_task_response(pm8001_ha->dev, t, iu);
+ }
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_ABORTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_ABORTED IOMB Tag\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_ABORTED_TASK;
+ break;
+ case IO_UNDERFLOW:
+ /* SSP Completion with error */
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_UNDERFLOW ,param = 0x%x\n",
+ param));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_UNDERRUN;
+ ts->residual = param;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_NO_DEVICE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_NO_DEVICE\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_PHY_DOWN;
+ break;
+ case IO_XFER_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ /* Force the midlayer to retry */
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_XFER_ERROR_PHY_NOT_READY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_EPROTO;
+ break;
+ case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ break;
+ case IO_OPEN_CNX_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+ case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ if (!t->uldd_task)
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+ break;
+ case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+ break;
+ case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ break;
+ case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ break;
+ case IO_XFER_ERROR_NAK_RECEIVED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_NAK_R_ERR;
+ break;
+ case IO_XFER_ERROR_DMA:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_DMA\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ case IO_XFER_OPEN_RETRY_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_XFER_ERROR_OFFSET_MISMATCH:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ case IO_PORT_IN_RESET:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_PORT_IN_RESET\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ case IO_DS_NON_OPERATIONAL:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ if (!t->uldd_task)
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_DS_NON_OPERATIONAL);
+ break;
+ case IO_DS_IN_RECOVERY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ case IO_TM_TAG_NOT_FOUND:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_TM_TAG_NOT_FOUND\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ default:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("Unknown status 0x%x\n", status));
+ /* not allowed case. Therefore, return failed status */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ break;
+ }
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("scsi_status = 0x%x\n ",
+ psspPayload->ssp_resp_iu.status));
+ spin_lock_irqsave(&t->task_state_lock, flags);
+ t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ t->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+ "task 0x%p done with io_status 0x%x resp 0x%x "
+ "stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ } else {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/* in order to force CPU ordering */
+ t->task_done(t);
+ }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
+{
+ struct sas_task *t;
+ unsigned long flags;
+ struct task_status_struct *ts;
+ struct pm8001_ccb_info *ccb;
+ struct pm8001_device *pm8001_dev;
+ struct ssp_event_resp *psspPayload =
+ (struct ssp_event_resp *)(piomb + 4);
+ u32 event = le32_to_cpu(psspPayload->event);
+ u32 tag = le32_to_cpu(psspPayload->tag);
+ u32 port_id = le32_to_cpu(psspPayload->port_id);
+
+ ccb = &pm8001_ha->ccb_info[tag];
+ t = ccb->task;
+ pm8001_dev = ccb->device;
+ if (event)
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("sas IO status 0x%x\n", event));
+ if (unlikely(!t || !t->lldd_task || !t->dev))
+ return;
+ ts = &t->task_status;
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
+ port_id, tag, event));
+ switch (event) {
+ case IO_OVERFLOW:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");)
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ ts->residual = 0;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_XFER_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK);
+ return;
+ case IO_XFER_ERROR_PHY_NOT_READY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_EPROTO;
+ break;
+ case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ break;
+ case IO_OPEN_CNX_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+ case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ if (!t->uldd_task)
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+ break;
+ case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+ break;
+ case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ break;
+ case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ break;
+ case IO_XFER_ERROR_NAK_RECEIVED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_NAK_R_ERR;
+ break;
+ case IO_XFER_OPEN_RETRY_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT);
+ return;
+ case IO_XFER_ERROR_UNEXPECTED_PHASE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_ERROR_XFER_RDY_OVERRUN:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_ERROR_OFFSET_MISMATCH:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
+ /* TBC: used default set values */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ case IO_XFER_CMD_FRAME_ISSUED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+ return;
+ default:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("Unknown status 0x%x\n", event));
+ /* not allowed case. Therefore, return failed status */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ break;
+ }
+ spin_lock_irqsave(&t->task_state_lock, flags);
+ t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ t->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+ "task 0x%p done with event 0x%x resp 0x%x "
+ "stat 0x%x but aborted by upper layer!\n",
+ t, event, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ } else {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/* in order to force CPU ordering */
+ t->task_done(t);
+ }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void
+mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct sas_task *t;
+ struct pm8001_ccb_info *ccb;
+ u32 param;
+ u32 status;
+ u32 tag;
+ struct sata_completion_resp *psataPayload;
+ struct task_status_struct *ts;
+ struct ata_task_resp *resp ;
+ u32 *sata_resp;
+ struct pm8001_device *pm8001_dev;
+ unsigned long flags;
+
+ psataPayload = (struct sata_completion_resp *)(piomb + 4);
+ status = le32_to_cpu(psataPayload->status);
+ tag = le32_to_cpu(psataPayload->tag);
+
+ if (!tag) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("tag null\n"));
+ return;
+ }
+ ccb = &pm8001_ha->ccb_info[tag];
+ param = le32_to_cpu(psataPayload->param);
+ if (ccb) {
+ t = ccb->task;
+ pm8001_dev = ccb->device;
+ } else {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("ccb null\n"));
+ return;
+ }
+
+ if (t) {
+ if (t->dev && (t->dev->lldd_dev))
+ pm8001_dev = t->dev->lldd_dev;
+ } else {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task null\n"));
+ return;
+ }
+
+ if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
+ && unlikely(!t || !t->lldd_task || !t->dev)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task or dev null\n"));
+ return;
+ }
+
+ ts = &t->task_status;
+ if (!ts) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("ts null\n"));
+ return;
+ }
+
+ switch (status) {
+ case IO_SUCCESS:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ if (param == 0) {
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_GOOD;
+ /* check if response is for SEND READ LOG */
+ if (pm8001_dev &&
+ (pm8001_dev->id & NCQ_READ_LOG_FLAG)) {
+ /* set new bit for abort_all */
+ pm8001_dev->id |= NCQ_ABORT_ALL_FLAG;
+ /* clear bit for read log */
+ pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF;
+ pm80xx_send_abort_all(pm8001_ha, pm8001_dev);
+ /* Free the tag */
+ pm8001_tag_free(pm8001_ha, tag);
+ sas_free_task(t);
+ return;
+ }
+ } else {
+ u8 len;
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_PROTO_RESPONSE;
+ ts->residual = param;
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("SAS_PROTO_RESPONSE len = %d\n",
+ param));
+ sata_resp = &psataPayload->sata_resp[0];
+ resp = (struct ata_task_resp *)ts->buf;
+ if (t->ata_task.dma_xfer == 0 &&
+ t->data_dir == PCI_DMA_FROMDEVICE) {
+ len = sizeof(struct pio_setup_fis);
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("PIO read len = %d\n", len));
+ } else if (t->ata_task.use_ncq) {
+ len = sizeof(struct set_dev_bits_fis);
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("FPDMA len = %d\n", len));
+ } else {
+ len = sizeof(struct dev_to_host_fis);
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("other len = %d\n", len));
+ }
+ if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
+ resp->frame_len = len;
+ memcpy(&resp->ending_fis[0], sata_resp, len);
+ ts->buf_valid_size = sizeof(*resp);
+ } else
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("response to large\n"));
+ }
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_ABORTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_ABORTED IOMB Tag\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_ABORTED_TASK;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ /* following cases are to do cases */
+ case IO_UNDERFLOW:
+ /* SATA Completion with error */
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_UNDERFLOW param = %d\n", param));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_UNDERRUN;
+ ts->residual = param;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_NO_DEVICE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_NO_DEVICE\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_PHY_DOWN;
+ break;
+ case IO_XFER_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_INTERRUPTED;
+ break;
+ case IO_XFER_ERROR_PHY_NOT_READY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_EPROTO;
+ break;
+ case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ break;
+ case IO_OPEN_CNX_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+ break;
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+ case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ if (!t->uldd_task) {
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_QUEUE_FULL;
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*in order to force CPU ordering*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ return;
+ }
+ break;
+ case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+ if (!t->uldd_task) {
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_QUEUE_FULL;
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ return;
+ }
+ break;
+ case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ break;
+ case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ if (!t->uldd_task) {
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_QUEUE_FULL;
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/* ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ return;
+ }
+ break;
+ case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ break;
+ case IO_XFER_ERROR_NAK_RECEIVED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_NAK_R_ERR;
+ break;
+ case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_NAK_R_ERR;
+ break;
+ case IO_XFER_ERROR_DMA:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_DMA\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_ABORTED_TASK;
+ break;
+ case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ break;
+ case IO_XFER_ERROR_REJECTED_NCQ_MODE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_UNDERRUN;
+ break;
+ case IO_XFER_OPEN_RETRY_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_PORT_IN_RESET:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_PORT_IN_RESET\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ break;
+ case IO_DS_NON_OPERATIONAL:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ if (!t->uldd_task) {
+ pm8001_handle_event(pm8001_ha, pm8001_dev,
+ IO_DS_NON_OPERATIONAL);
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_QUEUE_FULL;
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ return;
+ }
+ break;
+ case IO_DS_IN_RECOVERY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ break;
+ case IO_DS_IN_ERROR:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_IN_ERROR\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ if (!t->uldd_task) {
+ pm8001_handle_event(pm8001_ha, pm8001_dev,
+ IO_DS_IN_ERROR);
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_QUEUE_FULL;
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ return;
+ }
+ break;
+ case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ default:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("Unknown status 0x%x\n", status));
+ /* not allowed case. Therefore, return failed status */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ break;
+ }
+ spin_lock_irqsave(&t->task_state_lock, flags);
+ t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ t->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task 0x%p done with io_status 0x%x"
+ " resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ } else if (t->uldd_task) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/* ditto */
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ } else if (!t->uldd_task) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
+{
+ struct sas_task *t;
+ struct task_status_struct *ts;
+ struct pm8001_ccb_info *ccb;
+ struct pm8001_device *pm8001_dev;
+ struct sata_event_resp *psataPayload =
+ (struct sata_event_resp *)(piomb + 4);
+ u32 event = le32_to_cpu(psataPayload->event);
+ u32 tag = le32_to_cpu(psataPayload->tag);
+ u32 port_id = le32_to_cpu(psataPayload->port_id);
+ u32 dev_id = le32_to_cpu(psataPayload->device_id);
+ unsigned long flags;
+
+ ccb = &pm8001_ha->ccb_info[tag];
+
+ if (ccb) {
+ t = ccb->task;
+ pm8001_dev = ccb->device;
+ } else {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("No CCB !!!. returning\n"));
+ return;
+ }
+ if (event)
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("SATA EVENT 0x%x\n", event));
+
+ /* Check if this is NCQ error */
+ if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
+ /* find device using device id */
+ pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
+ /* send read log extension */
+ if (pm8001_dev)
+ pm80xx_send_read_log(pm8001_ha, pm8001_dev);
+ return;
+ }
+
+ if (unlikely(!t || !t->lldd_task || !t->dev)) {
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task or dev null\n"));
+ return;
+ }
+
+ ts = &t->task_status;
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
+ port_id, tag, event));
+ switch (event) {
+ case IO_OVERFLOW:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ ts->residual = 0;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_XFER_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_INTERRUPTED;
+ break;
+ case IO_XFER_ERROR_PHY_NOT_READY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_EPROTO;
+ break;
+ case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ break;
+ case IO_OPEN_CNX_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+ break;
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+ case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ if (!t->uldd_task) {
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_QUEUE_FULL;
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ return;
+ }
+ break;
+ case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ ts->resp = SAS_TASK_UNDELIVERED;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+ break;
+ case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ break;
+ case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ break;
+ case IO_XFER_ERROR_NAK_RECEIVED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_NAK_R_ERR;
+ break;
+ case IO_XFER_ERROR_PEER_ABORTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_NAK_R_ERR;
+ break;
+ case IO_XFER_ERROR_REJECTED_NCQ_MODE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_UNDERRUN;
+ break;
+ case IO_XFER_OPEN_RETRY_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_ERROR_UNEXPECTED_PHASE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_ERROR_XFER_RDY_OVERRUN:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_ERROR_OFFSET_MISMATCH:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_CMD_FRAME_ISSUED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+ break;
+ case IO_XFER_PIO_SETUP_ERROR:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
+ /* TBC: used default set values */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ case IO_XFER_DMA_ACTIVATE_TIMEOUT:
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("IO_XFR_DMA_ACTIVATE_TIMEOUT\n"));
+ /* TBC: used default set values */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ default:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("Unknown status 0x%x\n", event));
+ /* not allowed case. Therefore, return failed status */
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_TO;
+ break;
+ }
+ spin_lock_irqsave(&t->task_state_lock, flags);
+ t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ t->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task 0x%p done with io_status 0x%x"
+ " resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, event, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ } else if (t->uldd_task) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/* ditto */
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ } else if (!t->uldd_task) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ t->task_done(t);
+ spin_lock_irq(&pm8001_ha->lock);
+ }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void
+mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ u32 param, i;
+ struct sas_task *t;
+ struct pm8001_ccb_info *ccb;
+ unsigned long flags;
+ u32 status;
+ u32 tag;
+ struct smp_completion_resp *psmpPayload;
+ struct task_status_struct *ts;
+ struct pm8001_device *pm8001_dev;
+ char *pdma_respaddr = NULL;
+
+ psmpPayload = (struct smp_completion_resp *)(piomb + 4);
+ status = le32_to_cpu(psmpPayload->status);
+ tag = le32_to_cpu(psmpPayload->tag);
+
+ ccb = &pm8001_ha->ccb_info[tag];
+ param = le32_to_cpu(psmpPayload->param);
+ t = ccb->task;
+ ts = &t->task_status;
+ pm8001_dev = ccb->device;
+ if (status)
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("smp IO status 0x%x\n", status));
+ if (unlikely(!t || !t->lldd_task || !t->dev))
+ return;
+
+ switch (status) {
+
+ case IO_SUCCESS:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_GOOD;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("DIRECT RESPONSE Length:%d\n",
+ param));
+ pdma_respaddr = (char *)(phys_to_virt(cpu_to_le64
+ ((u64)sg_dma_address
+ (&t->smp_task.smp_resp))));
+ for (i = 0; i < param; i++) {
+ *(pdma_respaddr+i) = psmpPayload->_r_a[i];
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "SMP Byte%d DMA data 0x%x psmp 0x%x\n",
+ i, *(pdma_respaddr+i),
+ psmpPayload->_r_a[i]));
+ }
+ }
+ break;
+ case IO_ABORTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_ABORTED IOMB\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_ABORTED_TASK;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_OVERFLOW:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DATA_OVERRUN;
+ ts->residual = 0;
+ if (pm8001_dev)
+ pm8001_dev->running_req--;
+ break;
+ case IO_NO_DEVICE:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_PHY_DOWN;
+ break;
+ case IO_ERROR_HW_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_ERROR_HW_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_BUSY;
+ break;
+ case IO_XFER_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_BUSY;
+ break;
+ case IO_XFER_ERROR_PHY_NOT_READY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_BUSY;
+ break;
+ case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ break;
+ case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ break;
+ case IO_OPEN_CNX_ERROR_BREAK:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+ break;
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+ case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+ case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ pm8001_handle_event(pm8001_ha,
+ pm8001_dev,
+ IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+ break;
+ case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+ break;
+ case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(\
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ break;
+ case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ break;
+ case IO_XFER_ERROR_RX_FRAME:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_ERROR_RX_FRAME\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ break;
+ case IO_XFER_OPEN_RETRY_TIMEOUT:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_ERROR_INTERNAL_SMP_RESOURCE:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_QUEUE_FULL;
+ break;
+ case IO_PORT_IN_RESET:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_PORT_IN_RESET\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_DS_NON_OPERATIONAL:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ break;
+ case IO_DS_IN_RECOVERY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_OPEN_REJECT;
+ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
+ default:
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("Unknown status 0x%x\n", status));
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAS_DEV_NO_RESPONSE;
+ /* not allowed case. Therefore, return failed status */
+ break;
+ }
+ spin_lock_irqsave(&t->task_state_lock, flags);
+ t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ t->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+ "task 0x%p done with io_status 0x%x resp 0x%x"
+ "stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ } else {
+ spin_unlock_irqrestore(&t->task_state_lock, flags);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+ mb();/* in order to force CPU ordering */
+ t->task_done(t);
+ }
+}
+
+/**
+ * pm80xx_hw_event_ack_req- For PM8001,some events need to acknowage to FW.
+ * @pm8001_ha: our hba card information
+ * @Qnum: the outbound queue message number.
+ * @SEA: source of event to ack
+ * @port_id: port id.
+ * @phyId: phy id.
+ * @param0: parameter 0.
+ * @param1: parameter 1.
+ */
+static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
+ u32 Qnum, u32 SEA, u32 port_id, u32 phyId, u32 param0, u32 param1)
+{
+ struct hw_event_ack_req payload;
+ u32 opc = OPC_INB_SAS_HW_EVENT_ACK;
+
+ struct inbound_queue_table *circularQ;
+
+ memset((u8 *)&payload, 0, sizeof(payload));
+ circularQ = &pm8001_ha->inbnd_q_tbl[Qnum];
+ payload.tag = cpu_to_le32(1);
+ payload.phyid_sea_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) |
+ ((phyId & 0xFF) << 24) | (port_id & 0xFF));
+ payload.param0 = cpu_to_le32(param0);
+ payload.param1 = cpu_to_le32(param1);
+ pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+}
+
+static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
+ u32 phyId, u32 phy_op);
+
+/**
+ * hw_event_sas_phy_up -FW tells me a SAS phy up event.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void
+hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct hw_event_resp *pPayload =
+ (struct hw_event_resp *)(piomb + 4);
+ u32 lr_status_evt_portid =
+ le32_to_cpu(pPayload->lr_status_evt_portid);
+ u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+
+ u8 link_rate =
+ (u8)((lr_status_evt_portid & 0xF0000000) >> 28);
+ u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+ u8 phy_id =
+ (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+ u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
+
+ struct pm8001_port *port = &pm8001_ha->port[port_id];
+ struct sas_ha_struct *sas_ha = pm8001_ha->sas;
+ struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+ unsigned long flags;
+ u8 deviceType = pPayload->sas_identify.dev_type;
+ port->port_state = portstate;
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "portid:%d; phyid:%d; linkrate:%d; "
+ "portstate:%x; devicetype:%x\n",
+ port_id, phy_id, link_rate, portstate, deviceType));
+
+ switch (deviceType) {
+ case SAS_PHY_UNUSED:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("device type no device.\n"));
+ break;
+ case SAS_END_DEVICE:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
+ pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,
+ PHY_NOTIFY_ENABLE_SPINUP);
+ port->port_attached = 1;
+ pm8001_get_lrate_mode(phy, link_rate);
+ break;
+ case SAS_EDGE_EXPANDER_DEVICE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("expander device.\n"));
+ port->port_attached = 1;
+ pm8001_get_lrate_mode(phy, link_rate);
+ break;
+ case SAS_FANOUT_EXPANDER_DEVICE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("fanout expander device.\n"));
+ port->port_attached = 1;
+ pm8001_get_lrate_mode(phy, link_rate);
+ break;
+ default:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("unknown device type(%x)\n", deviceType));
+ break;
+ }
+ phy->phy_type |= PORT_TYPE_SAS;
+ phy->identify.device_type = deviceType;
+ phy->phy_attached = 1;
+ if (phy->identify.device_type == SAS_END_DEVICE)
+ phy->identify.target_port_protocols = SAS_PROTOCOL_SSP;
+ else if (phy->identify.device_type != SAS_PHY_UNUSED)
+ phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
+ phy->sas_phy.oob_mode = SAS_OOB_MODE;
+ sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
+ memcpy(phy->frame_rcvd, &pPayload->sas_identify,
+ sizeof(struct sas_identify_frame)-4);
+ phy->frame_rcvd_size = sizeof(struct sas_identify_frame) - 4;
+ pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
+ spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+ if (pm8001_ha->flags == PM8001F_RUN_TIME)
+ mdelay(200);/*delay a moment to wait disk to spinup*/
+ pm8001_bytes_dmaed(pm8001_ha, phy_id);
+}
+
+/**
+ * hw_event_sata_phy_up -FW tells me a SATA phy up event.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void
+hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct hw_event_resp *pPayload =
+ (struct hw_event_resp *)(piomb + 4);
+ u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+ u32 lr_status_evt_portid =
+ le32_to_cpu(pPayload->lr_status_evt_portid);
+ u8 link_rate =
+ (u8)((lr_status_evt_portid & 0xF0000000) >> 28);
+ u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+ u8 phy_id =
+ (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+
+ u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
+
+ struct pm8001_port *port = &pm8001_ha->port[port_id];
+ struct sas_ha_struct *sas_ha = pm8001_ha->sas;
+ struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+ unsigned long flags;
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "port id %d, phy id %d link_rate %d portstate 0x%x\n",
+ port_id, phy_id, link_rate, portstate));
+
+ port->port_state = portstate;
+ port->port_attached = 1;
+ pm8001_get_lrate_mode(phy, link_rate);
+ phy->phy_type |= PORT_TYPE_SATA;
+ phy->phy_attached = 1;
+ phy->sas_phy.oob_mode = SATA_OOB_MODE;
+ sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
+ memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4),
+ sizeof(struct dev_to_host_fis));
+ phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
+ phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
+ phy->identify.device_type = SAS_SATA_DEV;
+ pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
+ spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+ pm8001_bytes_dmaed(pm8001_ha, phy_id);
+}
+
+/**
+ * hw_event_phy_down -we should notify the libsas the phy is down.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void
+hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct hw_event_resp *pPayload =
+ (struct hw_event_resp *)(piomb + 4);
+
+ u32 lr_status_evt_portid =
+ le32_to_cpu(pPayload->lr_status_evt_portid);
+ u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+ u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+ u8 phy_id =
+ (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+ u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
+
+ struct pm8001_port *port = &pm8001_ha->port[port_id];
+ struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+ port->port_state = portstate;
+ phy->phy_type = 0;
+ phy->identify.device_type = 0;
+ phy->phy_attached = 0;
+ memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
+ switch (portstate) {
+ case PORT_VALID:
+ break;
+ case PORT_INVALID:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" PortInvalid portID %d\n", port_id));
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" Last phy Down and port invalid\n"));
+ port->port_attached = 0;
+ pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
+ port_id, phy_id, 0, 0);
+ break;
+ case PORT_IN_RESET:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" Port In Reset portID %d\n", port_id));
+ break;
+ case PORT_NOT_ESTABLISHED:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
+ port->port_attached = 0;
+ break;
+ case PORT_LOSTCOMM:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" Last phy Down and port invalid\n"));
+ port->port_attached = 0;
+ pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
+ port_id, phy_id, 0, 0);
+ break;
+ default:
+ port->port_attached = 0;
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" phy Down and(default) = 0x%x\n",
+ portstate));
+ break;
+
+ }
+}
+
+static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct phy_start_resp *pPayload =
+ (struct phy_start_resp *)(piomb + 4);
+ u32 status =
+ le32_to_cpu(pPayload->status);
+ u32 phy_id =
+ le32_to_cpu(pPayload->phyid);
+ struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n",
+ status, phy_id));
+ if (status == 0) {
+ phy->phy_state = 1;
+ if (pm8001_ha->flags == PM8001F_RUN_TIME)
+ complete(phy->enable_completion);
+ }
+ return 0;
+
+}
+
+/**
+ * mpi_thermal_hw_event -The hw event has come.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct thermal_hw_event *pPayload =
+ (struct thermal_hw_event *)(piomb + 4);
+
+ u32 thermal_event = le32_to_cpu(pPayload->thermal_event);
+ u32 rht_lht = le32_to_cpu(pPayload->rht_lht);
+
+ if (thermal_event & 0x40) {
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Thermal Event: Local high temperature violated!\n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Thermal Event: Measured local high temperature %d\n",
+ ((rht_lht & 0xFF00) >> 8)));
+ }
+ if (thermal_event & 0x10) {
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Thermal Event: Remote high temperature violated!\n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Thermal Event: Measured remote high temperature %d\n",
+ ((rht_lht & 0xFF000000) >> 24)));
+ }
+ return 0;
+}
+
+/**
+ * mpi_hw_event -The hw event has come.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ unsigned long flags;
+ struct hw_event_resp *pPayload =
+ (struct hw_event_resp *)(piomb + 4);
+ u32 lr_status_evt_portid =
+ le32_to_cpu(pPayload->lr_status_evt_portid);
+ u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+ u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+ u8 phy_id =
+ (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+ u16 eventType =
+ (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8);
+ u8 status =
+ (u8)((lr_status_evt_portid & 0x0F000000) >> 24);
+
+ struct sas_ha_struct *sas_ha = pm8001_ha->sas;
+ struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+ struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n",
+ port_id, phy_id, eventType, status));
+
+ switch (eventType) {
+
+ case HW_EVENT_SAS_PHY_UP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PHY_START_STATUS\n"));
+ hw_event_sas_phy_up(pm8001_ha, piomb);
+ break;
+ case HW_EVENT_SATA_PHY_UP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_SATA_PHY_UP\n"));
+ hw_event_sata_phy_up(pm8001_ha, piomb);
+ break;
+ case HW_EVENT_SATA_SPINUP_HOLD:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
+ sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
+ break;
+ case HW_EVENT_PHY_DOWN:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PHY_DOWN\n"));
+ sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
+ phy->phy_attached = 0;
+ phy->phy_state = 0;
+ hw_event_phy_down(pm8001_ha, piomb);
+ break;
+ case HW_EVENT_PORT_INVALID:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PORT_INVALID\n"));
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ /* the broadcast change primitive received, tell the LIBSAS this event
+ to revalidate the sas domain*/
+ case HW_EVENT_BROADCAST_CHANGE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE,
+ port_id, phy_id, 1, 0);
+ spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
+ sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
+ spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
+ sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ break;
+ case HW_EVENT_PHY_ERROR:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PHY_ERROR\n"));
+ sas_phy_disconnected(&phy->sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
+ break;
+ case HW_EVENT_BROADCAST_EXP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_BROADCAST_EXP\n"));
+ spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
+ sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP;
+ spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
+ sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ break;
+ case HW_EVENT_LINK_ERR_INVALID_DWORD:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_LINK_ERR_DISPARITY_ERROR,
+ port_id, phy_id, 0, 0);
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_LINK_ERR_CODE_VIOLATION:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_LINK_ERR_CODE_VIOLATION,
+ port_id, phy_id, 0, 0);
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
+ port_id, phy_id, 0, 0);
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_MALFUNCTION:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_MALFUNCTION\n"));
+ break;
+ case HW_EVENT_BROADCAST_SES:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_BROADCAST_SES\n"));
+ spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
+ sas_phy->sas_prim = HW_EVENT_BROADCAST_SES;
+ spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
+ sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ break;
+ case HW_EVENT_INBOUND_CRC_ERROR:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_INBOUND_CRC_ERROR,
+ port_id, phy_id, 0, 0);
+ break;
+ case HW_EVENT_HARD_RESET_RECEIVED:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n"));
+ sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
+ break;
+ case HW_EVENT_ID_FRAME_TIMEOUT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n"));
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
+ port_id, phy_id, 0, 0);
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_PORT_RESET_TIMER_TMO:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));
+ pm80xx_hw_event_ack_req(pm8001_ha, 0,
+ HW_EVENT_PORT_RECOVERY_TIMER_TMO,
+ port_id, phy_id, 0, 0);
+ sas_phy_disconnected(sas_phy);
+ phy->phy_attached = 0;
+ sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ break;
+ case HW_EVENT_PORT_RECOVER:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PORT_RECOVER\n"));
+ break;
+ case HW_EVENT_PORT_RESET_COMPLETE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
+ break;
+ case EVENT_BROADCAST_ASYNCH_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
+ break;
+ default:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("Unknown event type 0x%x\n", eventType));
+ break;
+ }
+ return 0;
+}
+
+/**
+ * mpi_phy_stop_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ struct phy_stop_resp *pPayload =
+ (struct phy_stop_resp *)(piomb + 4);
+ u32 status =
+ le32_to_cpu(pPayload->status);
+ u32 phyid =
+ le32_to_cpu(pPayload->phyid);
+ struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("phy:0x%x status:0x%x\n",
+ phyid, status));
+ if (status == 0)
+ phy->phy_state = 0;
+ return 0;
+}
+
+/**
+ * mpi_set_controller_config_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ struct set_ctrl_cfg_resp *pPayload =
+ (struct set_ctrl_cfg_resp *)(piomb + 4);
+ u32 status = le32_to_cpu(pPayload->status);
+ u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd);
+
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
+ status, err_qlfr_pgcd));
+
+ return 0;
+}
+
+/**
+ * mpi_get_controller_config_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" pm80xx_addition_functionality\n"));
+
+ return 0;
+}
+
+/**
+ * mpi_get_phy_profile_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" pm80xx_addition_functionality\n"));
+
+ return 0;
+}
+
+/**
+ * mpi_flash_op_ext_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" pm80xx_addition_functionality\n"));
+
+ return 0;
+}
+
+/**
+ * mpi_set_phy_profile_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" pm80xx_addition_functionality\n"));
+
+ return 0;
+}
+
+/**
+ * mpi_kek_management_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ struct kek_mgmt_resp *pPayload = (struct kek_mgmt_resp *)(piomb + 4);
+
+ u32 status = le32_to_cpu(pPayload->status);
+ u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop);
+ u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr);
+
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n",
+ status, kidx_new_curr_ksop, err_qlfr));
+
+ return 0;
+}
+
+/**
+ * mpi_dek_management_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" pm80xx_addition_functionality\n"));
+
+ return 0;
+}
+
+/**
+ * ssp_coalesced_comp_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
+ void *piomb)
+{
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk(" pm80xx_addition_functionality\n"));
+
+ return 0;
+}
+
+/**
+ * process_one_iomb - process one outbound Queue memory block
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+ __le32 pHeader = *(__le32 *)piomb;
+ u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF);
+
+ switch (opc) {
+ case OPC_OUB_ECHO:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n"));
+ break;
+ case OPC_OUB_HW_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_HW_EVENT\n"));
+ mpi_hw_event(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_THERM_HW_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_THERMAL_EVENT\n"));
+ mpi_thermal_hw_event(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SSP_COMP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SSP_COMP\n"));
+ mpi_ssp_completion(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SMP_COMP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SMP_COMP\n"));
+ mpi_smp_completion(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_LOCAL_PHY_CNTRL:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n"));
+ pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_DEV_REGIST:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_DEV_REGIST\n"));
+ pm8001_mpi_reg_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_DEREG_DEV:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("unregister the device\n"));
+ pm8001_mpi_dereg_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_GET_DEV_HANDLE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n"));
+ break;
+ case OPC_OUB_SATA_COMP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SATA_COMP\n"));
+ mpi_sata_completion(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SATA_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SATA_EVENT\n"));
+ mpi_sata_event(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SSP_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SSP_EVENT\n"));
+ mpi_ssp_event(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_DEV_HANDLE_ARRIV:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n"));
+ /*This is for target*/
+ break;
+ case OPC_OUB_SSP_RECV_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n"));
+ /*This is for target*/
+ break;
+ case OPC_OUB_FW_FLASH_UPDATE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n"));
+ pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_GPIO_RESPONSE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GPIO_RESPONSE\n"));
+ break;
+ case OPC_OUB_GPIO_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GPIO_EVENT\n"));
+ break;
+ case OPC_OUB_GENERAL_EVENT:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GENERAL_EVENT\n"));
+ pm8001_mpi_general_event(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SSP_ABORT_RSP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n"));
+ pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SATA_ABORT_RSP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n"));
+ pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SAS_DIAG_MODE_START_END:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n"));
+ break;
+ case OPC_OUB_SAS_DIAG_EXECUTE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n"));
+ break;
+ case OPC_OUB_GET_TIME_STAMP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GET_TIME_STAMP\n"));
+ break;
+ case OPC_OUB_SAS_HW_EVENT_ACK:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n"));
+ break;
+ case OPC_OUB_PORT_CONTROL:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_PORT_CONTROL\n"));
+ break;
+ case OPC_OUB_SMP_ABORT_RSP:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n"));
+ pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_GET_NVMD_DATA:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GET_NVMD_DATA\n"));
+ pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SET_NVMD_DATA:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SET_NVMD_DATA\n"));
+ pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_DEVICE_HANDLE_REMOVAL:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n"));
+ break;
+ case OPC_OUB_SET_DEVICE_STATE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n"));
+ pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_GET_DEVICE_STATE:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n"));
+ break;
+ case OPC_OUB_SET_DEV_INFO:
+ PM8001_MSG_DBG(pm8001_ha,
+ pm8001_printk("OPC_OUB_SET_DEV_INFO\n"));
+ break;
+ /* spcv specifc commands */
+ case OPC_OUB_PHY_START_RESP:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_PHY_START_RESP opcode:%x\n", opc));
+ mpi_phy_start_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_PHY_STOP_RESP:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc));
+ mpi_phy_stop_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SET_CONTROLLER_CONFIG:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc));
+ mpi_set_controller_config_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_GET_CONTROLLER_CONFIG:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc));
+ mpi_get_controller_config_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_GET_PHY_PROFILE:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc));
+ mpi_get_phy_profile_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_FLASH_OP_EXT:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc));
+ mpi_flash_op_ext_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SET_PHY_PROFILE:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc));
+ mpi_set_phy_profile_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_KEK_MANAGEMENT_RESP:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc));
+ mpi_kek_management_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_DEK_MANAGEMENT_RESP:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc));
+ mpi_dek_management_resp(pm8001_ha, piomb);
+ break;
+ case OPC_OUB_SSP_COALESCED_COMP_RESP:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc));
+ ssp_coalesced_comp_resp(pm8001_ha, piomb);
+ break;
+ default:
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+ "Unknown outbound Queue IOMB OPC = 0x%x\n", opc));
+ break;
+ }
+}
+
+static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+ struct outbound_queue_table *circularQ;
+ void *pMsg1 = NULL;
+ u8 uninitialized_var(bc);
+ u32 ret = MPI_IO_STATUS_FAIL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pm8001_ha->lock, flags);
+ circularQ = &pm8001_ha->outbnd_q_tbl[vec];
+ do {
+ ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
+ if (MPI_IO_STATUS_SUCCESS == ret) {
+ /* process the outbound message */
+ process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4));
+ /* free the message from the outbound circular buffer */
+ pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,
+ circularQ, bc);
+ }
+ if (MPI_IO_STATUS_BUSY == ret) {
+ /* Update the producer index from SPC */
+ circularQ->producer_index =
+ cpu_to_le32(pm8001_read_32(circularQ->pi_virt));
+ if (le32_to_cpu(circularQ->producer_index) ==
+ circularQ->consumer_idx)
+ /* OQ is empty */
+ break;
+ }
+ } while (1);
+ spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+ return ret;
+}
+
+/* PCI_DMA_... to our direction translation. */
+static const u8 data_dir_flags[] = {
+ [PCI_DMA_BIDIRECTIONAL] = DATA_DIR_BYRECIPIENT,/* UNSPECIFIED */
+ [PCI_DMA_TODEVICE] = DATA_DIR_OUT,/* OUTBOUND */
+ [PCI_DMA_FROMDEVICE] = DATA_DIR_IN,/* INBOUND */
+ [PCI_DMA_NONE] = DATA_DIR_NONE,/* NO TRANSFER */
+};
+
+static void build_smp_cmd(u32 deviceID, __le32 hTag,
+ struct smp_req *psmp_cmd, int mode, int length)
+{
+ psmp_cmd->tag = hTag;
+ psmp_cmd->device_id = cpu_to_le32(deviceID);
+ if (mode == SMP_DIRECT) {
+ length = length - 4; /* subtract crc */
+ psmp_cmd->len_ip_ir = cpu_to_le32(length << 16);
+ } else {
+ psmp_cmd->len_ip_ir = cpu_to_le32(1|(1 << 1));
+ }
+}
+
+/**
+ * pm8001_chip_smp_req - send a SMP task to FW
+ * @pm8001_ha: our hba card information.
+ * @ccb: the ccb information this request used.
+ */
+static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_ccb_info *ccb)
+{
+ int elem, rc;
+ struct sas_task *task = ccb->task;
+ struct domain_device *dev = task->dev;
+ struct pm8001_device *pm8001_dev = dev->lldd_dev;
+ struct scatterlist *sg_req, *sg_resp;
+ u32 req_len, resp_len;
+ struct smp_req smp_cmd;
+ u32 opc;
+ struct inbound_queue_table *circularQ;
+ char *preq_dma_addr = NULL;
+ __le64 tmp_addr;
+ u32 i, length;
+
+ memset(&smp_cmd, 0, sizeof(smp_cmd));
+ /*
+ * DMA-map SMP request, response buffers
+ */
+ sg_req = &task->smp_task.smp_req;
+ elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, PCI_DMA_TODEVICE);
+ if (!elem)
+ return -ENOMEM;
+ req_len = sg_dma_len(sg_req);
+
+ sg_resp = &task->smp_task.smp_resp;
+ elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, PCI_DMA_FROMDEVICE);
+ if (!elem) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ resp_len = sg_dma_len(sg_resp);
+ /* must be in dwords */
+ if ((req_len & 0x3) || (resp_len & 0x3)) {
+ rc = -EINVAL;
+ goto err_out_2;
+ }
+
+ opc = OPC_INB_SMP_REQUEST;
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);
+
+ length = sg_req->length;
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("SMP Frame Length %d\n", sg_req->length));
+ if (!(length - 8))
+ pm8001_ha->smp_exp_mode = SMP_DIRECT;
+ else
+ pm8001_ha->smp_exp_mode = SMP_INDIRECT;
+
+ /* DIRECT MODE support only in spcv/ve */
+ pm8001_ha->smp_exp_mode = SMP_DIRECT;
+
+ tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req));
+ preq_dma_addr = (char *)phys_to_virt(tmp_addr);
+
+ /* INDIRECT MODE command settings. Use DMA */
+ if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) {
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("SMP REQUEST INDIRECT MODE\n"));
+ /* for SPCv indirect mode. Place the top 4 bytes of
+ * SMP Request header here. */
+ for (i = 0; i < 4; i++)
+ smp_cmd.smp_req16[i] = *(preq_dma_addr + i);
+ /* exclude top 4 bytes for SMP req header */
+ smp_cmd.long_smp_req.long_req_addr =
+ cpu_to_le64((u64)sg_dma_address
+ (&task->smp_task.smp_req) - 4);
+ /* exclude 4 bytes for SMP req header and CRC */
+ smp_cmd.long_smp_req.long_req_size =
+ cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8);
+ smp_cmd.long_smp_req.long_resp_addr =
+ cpu_to_le64((u64)sg_dma_address
+ (&task->smp_task.smp_resp));
+ smp_cmd.long_smp_req.long_resp_size =
+ cpu_to_le32((u32)sg_dma_len
+ (&task->smp_task.smp_resp)-4);
+ } else { /* DIRECT MODE */
+ smp_cmd.long_smp_req.long_req_addr =
+ cpu_to_le64((u64)sg_dma_address
+ (&task->smp_task.smp_req));
+ smp_cmd.long_smp_req.long_req_size =
+ cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-4);
+ smp_cmd.long_smp_req.long_resp_addr =
+ cpu_to_le64((u64)sg_dma_address
+ (&task->smp_task.smp_resp));
+ smp_cmd.long_smp_req.long_resp_size =
+ cpu_to_le32
+ ((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
+ }
+ if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
+ PM8001_IO_DBG(pm8001_ha,
+ pm8001_printk("SMP REQUEST DIRECT MODE\n"));
+ for (i = 0; i < length; i++)
+ if (i < 16) {
+ smp_cmd.smp_req16[i] = *(preq_dma_addr+i);
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Byte[%d]:%x (DMA data:%x)\n",
+ i, smp_cmd.smp_req16[i],
+ *(preq_dma_addr)));
+ } else {
+ smp_cmd.smp_req[i] = *(preq_dma_addr+i);
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Byte[%d]:%x (DMA data:%x)\n",
+ i, smp_cmd.smp_req[i],
+ *(preq_dma_addr)));
+ }
+ }
+
+ build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
+ &smp_cmd, pm8001_ha->smp_exp_mode, length);
+ pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
+ return 0;
+
+err_out_2:
+ dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_resp, 1,
+ PCI_DMA_FROMDEVICE);
+err_out:
+ dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_req, 1,
+ PCI_DMA_TODEVICE);
+ return rc;
+}
+
+static int check_enc_sas_cmd(struct sas_task *task)
+{
+ u8 cmd = task->ssp_task.cmd->cmnd[0];
+
+ if (cmd == READ_10 || cmd == WRITE_10 || cmd == WRITE_VERIFY)
+ return 1;
+ else
+ return 0;
+}
+
+static int check_enc_sat_cmd(struct sas_task *task)
+{
+ int ret = 0;
+ switch (task->ata_task.fis.command) {
+ case ATA_CMD_FPDMA_READ:
+ case ATA_CMD_READ_EXT:
+ case ATA_CMD_READ:
+ case ATA_CMD_FPDMA_WRITE:
+ case ATA_CMD_WRITE_EXT:
+ case ATA_CMD_WRITE:
+ case ATA_CMD_PIO_READ:
+ case ATA_CMD_PIO_READ_EXT:
+ case ATA_CMD_PIO_WRITE:
+ case ATA_CMD_PIO_WRITE_EXT:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+/**
+ * pm80xx_chip_ssp_io_req - send a SSP task to FW
+ * @pm8001_ha: our hba card information.
+ * @ccb: the ccb information this request used.
+ */
+static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_ccb_info *ccb)
+{
+ struct sas_task *task = ccb->task;
+ struct domain_device *dev = task->dev;
+ struct pm8001_device *pm8001_dev = dev->lldd_dev;
+ struct ssp_ini_io_start_req ssp_cmd;
+ u32 tag = ccb->ccb_tag;
+ int ret;
+ u64 phys_addr;
+ struct inbound_queue_table *circularQ;
+ static u32 inb;
+ static u32 outb;
+ u32 opc = OPC_INB_SSPINIIOSTART;
+ memset(&ssp_cmd, 0, sizeof(ssp_cmd));
+ memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
+ /* data address domain added for spcv; set to 0 by host,
+ * used internally by controller
+ * 0 for SAS 1.1 and SAS 2.0 compatible TLR
+ */
+ ssp_cmd.dad_dir_m_tlr =
+ cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0);
+ ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
+ ssp_cmd.tag = cpu_to_le32(tag);
+ if (task->ssp_task.enable_first_burst)
+ ssp_cmd.ssp_iu.efb_prio_attr |= 0x80;
+ ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
+ ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
+ memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
+ task->ssp_task.cmd->cmd_len);
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ /* Check if encryption is set */
+ if (pm8001_ha->chip->encrypt &&
+ !(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) {
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Encryption enabled.Sending Encrypt SAS command 0x%x\n",
+ task->ssp_task.cmd->cmnd[0]));
+ opc = OPC_INB_SSP_INI_DIF_ENC_IO;
+ /* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/
+ ssp_cmd.dad_dir_m_tlr = cpu_to_le32
+ ((data_dir_flags[task->data_dir] << 8) | 0x20 | 0x0);
+
+ /* fill in PRD (scatter/gather) table, if any */
+ if (task->num_scatter > 1) {
+ pm8001_chip_make_sg(task->scatter,
+ ccb->n_elem, ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle +
+ offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ ssp_cmd.enc_addr_low =
+ cpu_to_le32(lower_32_bits(phys_addr));
+ ssp_cmd.enc_addr_high =
+ cpu_to_le32(upper_32_bits(phys_addr));
+ ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
+ ssp_cmd.enc_addr_low =
+ cpu_to_le32(lower_32_bits(dma_addr));
+ ssp_cmd.enc_addr_high =
+ cpu_to_le32(upper_32_bits(dma_addr));
+ ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.enc_esgl = 0;
+ } else if (task->num_scatter == 0) {
+ ssp_cmd.enc_addr_low = 0;
+ ssp_cmd.enc_addr_high = 0;
+ ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.enc_esgl = 0;
+ }
+ /* XTS mode. All other fields are 0 */
+ ssp_cmd.key_cmode = 0x6 << 4;
+ /* set tweak values. Should be the start lba */
+ ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cmd->cmnd[2] << 24) |
+ (task->ssp_task.cmd->cmnd[3] << 16) |
+ (task->ssp_task.cmd->cmnd[4] << 8) |
+ (task->ssp_task.cmd->cmnd[5]));
+ } else {
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Sending Normal SAS command 0x%x inb q %x\n",
+ task->ssp_task.cmd->cmnd[0], inb));
+ /* fill in PRD (scatter/gather) table, if any */
+ if (task->num_scatter > 1) {
+ pm8001_chip_make_sg(task->scatter, ccb->n_elem,
+ ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle +
+ offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ ssp_cmd.addr_low =
+ cpu_to_le32(lower_32_bits(phys_addr));
+ ssp_cmd.addr_high =
+ cpu_to_le32(upper_32_bits(phys_addr));
+ ssp_cmd.esgl = cpu_to_le32(1<<31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
+ ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr));
+ ssp_cmd.addr_high =
+ cpu_to_le32(upper_32_bits(dma_addr));
+ ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.esgl = 0;
+ } else if (task->num_scatter == 0) {
+ ssp_cmd.addr_low = 0;
+ ssp_cmd.addr_high = 0;
+ ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
+ ssp_cmd.esgl = 0;
+ }
+ }
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, outb++);
+
+ /* rotate the outb queue */
+ outb = outb%PM8001_MAX_SPCV_OUTB_NUM;
+
+ return ret;
+}
+
+static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_ccb_info *ccb)
+{
+ struct sas_task *task = ccb->task;
+ struct domain_device *dev = task->dev;
+ struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
+ u32 tag = ccb->ccb_tag;
+ int ret;
+ static u32 inb;
+ static u32 outb;
+ struct sata_start_req sata_cmd;
+ u32 hdr_tag, ncg_tag = 0;
+ u64 phys_addr;
+ u32 ATAP = 0x0;
+ u32 dir;
+ struct inbound_queue_table *circularQ;
+ unsigned long flags;
+ u32 opc = OPC_INB_SATA_HOST_OPSTART;
+ memset(&sata_cmd, 0, sizeof(sata_cmd));
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ if (task->data_dir == PCI_DMA_NONE) {
+ ATAP = 0x04; /* no data*/
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n"));
+ } else if (likely(!task->ata_task.device_control_reg_update)) {
+ if (task->ata_task.dma_xfer) {
+ ATAP = 0x06; /* DMA */
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n"));
+ } else {
+ ATAP = 0x05; /* PIO*/
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n"));
+ }
+ if (task->ata_task.use_ncq &&
+ dev->sata_dev.command_set != ATAPI_COMMAND_SET) {
+ ATAP = 0x07; /* FPDMA */
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
+ }
+ }
+ if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
+ task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
+ ncg_tag = hdr_tag;
+ }
+ dir = data_dir_flags[task->data_dir] << 8;
+ sata_cmd.tag = cpu_to_le32(tag);
+ sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+ sata_cmd.data_len = cpu_to_le32(task->total_xfer_len);
+
+ sata_cmd.sata_fis = task->ata_task.fis;
+ if (likely(!task->ata_task.device_control_reg_update))
+ sata_cmd.sata_fis.flags |= 0x80;/* C=1: update ATA cmd reg */
+ sata_cmd.sata_fis.flags &= 0xF0;/* PM_PORT field shall be 0 */
+
+ /* Check if encryption is set */
+ if (pm8001_ha->chip->encrypt &&
+ !(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) {
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n",
+ sata_cmd.sata_fis.command));
+ opc = OPC_INB_SATA_DIF_ENC_IO;
+
+ /* set encryption bit */
+ sata_cmd.ncqtag_atap_dir_m_dad =
+ cpu_to_le32(((ncg_tag & 0xff)<<16)|
+ ((ATAP & 0x3f) << 10) | 0x20 | dir);
+ /* dad (bit 0-1) is 0 */
+ /* fill in PRD (scatter/gather) table, if any */
+ if (task->num_scatter > 1) {
+ pm8001_chip_make_sg(task->scatter,
+ ccb->n_elem, ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle +
+ offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ sata_cmd.enc_addr_low = lower_32_bits(phys_addr);
+ sata_cmd.enc_addr_high = upper_32_bits(phys_addr);
+ sata_cmd.enc_esgl = cpu_to_le32(1 << 31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
+ sata_cmd.enc_addr_low = lower_32_bits(dma_addr);
+ sata_cmd.enc_addr_high = upper_32_bits(dma_addr);
+ sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.enc_esgl = 0;
+ } else if (task->num_scatter == 0) {
+ sata_cmd.enc_addr_low = 0;
+ sata_cmd.enc_addr_high = 0;
+ sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.enc_esgl = 0;
+ }
+ /* XTS mode. All other fields are 0 */
+ sata_cmd.key_index_mode = 0x6 << 4;
+ /* set tweak values. Should be the start lba */
+ sata_cmd.twk_val0 =
+ cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) |
+ (sata_cmd.sata_fis.lbah << 16) |
+ (sata_cmd.sata_fis.lbam << 8) |
+ (sata_cmd.sata_fis.lbal));
+ sata_cmd.twk_val1 =
+ cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) |
+ (sata_cmd.sata_fis.lbam_exp));
+ } else {
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+ "Sending Normal SATA command 0x%x inb %x\n",
+ sata_cmd.sata_fis.command, inb));
+ /* dad (bit 0-1) is 0 */
+ sata_cmd.ncqtag_atap_dir_m_dad =
+ cpu_to_le32(((ncg_tag & 0xff)<<16) |
+ ((ATAP & 0x3f) << 10) | dir);
+
+ /* fill in PRD (scatter/gather) table, if any */
+ if (task->num_scatter > 1) {
+ pm8001_chip_make_sg(task->scatter,
+ ccb->n_elem, ccb->buf_prd);
+ phys_addr = ccb->ccb_dma_handle +
+ offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ sata_cmd.addr_low = lower_32_bits(phys_addr);
+ sata_cmd.addr_high = upper_32_bits(phys_addr);
+ sata_cmd.esgl = cpu_to_le32(1 << 31);
+ } else if (task->num_scatter == 1) {
+ u64 dma_addr = sg_dma_address(task->scatter);
+ sata_cmd.addr_low = lower_32_bits(dma_addr);
+ sata_cmd.addr_high = upper_32_bits(dma_addr);
+ sata_cmd.len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.esgl = 0;
+ } else if (task->num_scatter == 0) {
+ sata_cmd.addr_low = 0;
+ sata_cmd.addr_high = 0;
+ sata_cmd.len = cpu_to_le32(task->total_xfer_len);
+ sata_cmd.esgl = 0;
+ }
+ /* scsi cdb */
+ sata_cmd.atapi_scsi_cdb[0] =
+ cpu_to_le32(((task->ata_task.atapi_packet[0]) |
+ (task->ata_task.atapi_packet[1] << 8) |
+ (task->ata_task.atapi_packet[2] << 16) |
+ (task->ata_task.atapi_packet[3] << 24)));
+ sata_cmd.atapi_scsi_cdb[1] =
+ cpu_to_le32(((task->ata_task.atapi_packet[4]) |
+ (task->ata_task.atapi_packet[5] << 8) |
+ (task->ata_task.atapi_packet[6] << 16) |
+ (task->ata_task.atapi_packet[7] << 24)));
+ sata_cmd.atapi_scsi_cdb[2] =
+ cpu_to_le32(((task->ata_task.atapi_packet[8]) |
+ (task->ata_task.atapi_packet[9] << 8) |
+ (task->ata_task.atapi_packet[10] << 16) |
+ (task->ata_task.atapi_packet[11] << 24)));
+ sata_cmd.atapi_scsi_cdb[3] =
+ cpu_to_le32(((task->ata_task.atapi_packet[12]) |
+ (task->ata_task.atapi_packet[13] << 8) |
+ (task->ata_task.atapi_packet[14] << 16) |
+ (task->ata_task.atapi_packet[15] << 24)));
+ }
+
+ /* Check for read log for failed drive and return */
+ if (sata_cmd.sata_fis.command == 0x2f) {
+ if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
+ (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
+ (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
+ struct task_status_struct *ts;
+
+ pm8001_ha_dev->id &= 0xDFFFFFFF;
+ ts = &task->task_status;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ ts->resp = SAS_TASK_COMPLETE;
+ ts->stat = SAM_STAT_GOOD;
+ task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+ task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
+ if (unlikely((task->task_state_flags &
+ SAS_TASK_STATE_ABORTED))) {
+ spin_unlock_irqrestore(&task->task_state_lock,
+ flags);
+ PM8001_FAIL_DBG(pm8001_ha,
+ pm8001_printk("task 0x%p resp 0x%x "
+ " stat 0x%x but aborted by upper layer "
+ "\n", task, ts->resp, ts->stat));
+ pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+ return 0;
+ } else if (task->uldd_task) {
+ spin_unlock_irqrestore(&task->task_state_lock,
+ flags);
+ pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+ mb();/* ditto */
+ spin_unlock_irq(&pm8001_ha->lock);
+ task->task_done(task);
+ spin_lock_irq(&pm8001_ha->lock);
+ return 0;
+ } else if (!task->uldd_task) {
+ spin_unlock_irqrestore(&task->task_state_lock,
+ flags);
+ pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+ mb();/*ditto*/
+ spin_unlock_irq(&pm8001_ha->lock);
+ task->task_done(task);
+ spin_lock_irq(&pm8001_ha->lock);
+ return 0;
+ }
+ }
+ }
+
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
+ &sata_cmd, outb++);
+
+ /* rotate the outb queue */
+ outb = outb%PM8001_MAX_SPCV_OUTB_NUM;
+ return ret;
+}
+
+/**
+ * pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND
+ * @pm8001_ha: our hba card information.
+ * @num: the inbound queue number
+ * @phy_id: the phy id which we wanted to start up.
+ */
+static int
+pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
+{
+ struct phy_start_req payload;
+ struct inbound_queue_table *circularQ;
+ int ret;
+ u32 tag = 0x01;
+ u32 opcode = OPC_INB_PHYSTART;
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ memset(&payload, 0, sizeof(payload));
+ payload.tag = cpu_to_le32(tag);
+
+ PM8001_INIT_DBG(pm8001_ha,
+ pm8001_printk("PHY START REQ for phy_id %d\n", phy_id));
+ /*
+ ** [0:7] PHY Identifier
+ ** [8:11] link rate 1.5G, 3G, 6G
+ ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode
+ ** [14] 0b disable spin up hold; 1b enable spin up hold
+ ** [15] ob no change in current PHY analig setup 1b enable using SPAST
+ */
+ payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
+ LINKMODE_AUTO | LINKRATE_15 |
+ LINKRATE_30 | LINKRATE_60 | phy_id);
+ /* SSC Disable and SAS Analog ST configuration */
+ /**
+ payload.ase_sh_lm_slr_phyid =
+ cpu_to_le32(SSC_DISABLE_30 | SAS_ASE | SPINHOLD_DISABLE |
+ LINKMODE_AUTO | LINKRATE_15 | LINKRATE_30 | LINKRATE_60 |
+ phy_id);
+ Have to add "SAS PHY Analog Setup SPASTI 1 Byte" Based on need
+ **/
+
+ payload.sas_identify.dev_type = SAS_END_DEVICE;
+ payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
+ memcpy(payload.sas_identify.sas_addr,
+ pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+ payload.sas_identify.phy_id = phy_id;
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+ return ret;
+}
+
+/**
+ * pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND
+ * @pm8001_ha: our hba card information.
+ * @num: the inbound queue number
+ * @phy_id: the phy id which we wanted to start up.
+ */
+static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
+ u8 phy_id)
+{
+ struct phy_stop_req payload;
+ struct inbound_queue_table *circularQ;
+ int ret;
+ u32 tag = 0x01;
+ u32 opcode = OPC_INB_PHYSTOP;
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ memset(&payload, 0, sizeof(payload));
+ payload.tag = cpu_to_le32(tag);
+ payload.phy_id = cpu_to_le32(phy_id);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+ return ret;
+}
+
+/**
+ * see comments on pm8001_mpi_reg_resp.
+ */
+static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *pm8001_dev, u32 flag)
+{
+ struct reg_dev_req payload;
+ u32 opc;
+ u32 stp_sspsmp_sata = 0x4;
+ struct inbound_queue_table *circularQ;
+ u32 linkrate, phy_id;
+ int rc, tag = 0xdeadbeef;
+ struct pm8001_ccb_info *ccb;
+ u8 retryFlag = 0x1;
+ u16 firstBurstSize = 0;
+ u16 ITNT = 2000;
+ struct domain_device *dev = pm8001_dev->sas_device;
+ struct domain_device *parent_dev = dev->parent;
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+ memset(&payload, 0, sizeof(payload));
+ rc = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (rc)
+ return rc;
+ ccb = &pm8001_ha->ccb_info[tag];
+ ccb->device = pm8001_dev;
+ ccb->ccb_tag = tag;
+ payload.tag = cpu_to_le32(tag);
+
+ if (flag == 1) {
+ stp_sspsmp_sata = 0x02; /*direct attached sata */
+ } else {
+ if (pm8001_dev->dev_type == SAS_SATA_DEV)
+ stp_sspsmp_sata = 0x00; /* stp*/
+ else if (pm8001_dev->dev_type == SAS_END_DEVICE ||
+ pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+ pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
+ stp_sspsmp_sata = 0x01; /*ssp or smp*/
+ }
+ if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
+ phy_id = parent_dev->ex_dev.ex_phy->phy_id;
+ else
+ phy_id = pm8001_dev->attached_phy;
+
+ opc = OPC_INB_REG_DEV;
+
+ linkrate = (pm8001_dev->sas_device->linkrate < dev->port->linkrate) ?
+ pm8001_dev->sas_device->linkrate : dev->port->linkrate;
+
+ payload.phyid_portid =
+ cpu_to_le32(((pm8001_dev->sas_device->port->id) & 0xFF) |
+ ((phy_id & 0xFF) << 8));
+
+ payload.dtype_dlr_mcn_ir_retry = cpu_to_le32((retryFlag & 0x01) |
+ ((linkrate & 0x0F) << 24) |
+ ((stp_sspsmp_sata & 0x03) << 28));
+ payload.firstburstsize_ITNexustimeout =
+ cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
+
+ memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
+ SAS_ADDR_SIZE);
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+
+ return rc;
+}
+
+/**
+ * pm80xx_chip_phy_ctl_req - support the local phy operation
+ * @pm8001_ha: our hba card information.
+ * @num: the inbound queue number
+ * @phy_id: the phy id which we wanted to operate
+ * @phy_op:
+ */
+static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
+ u32 phyId, u32 phy_op)
+{
+ struct local_phy_ctl_req payload;
+ struct inbound_queue_table *circularQ;
+ int ret;
+ u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
+ memset(&payload, 0, sizeof(payload));
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ payload.tag = cpu_to_le32(1);
+ payload.phyop_phyid =
+ cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ return ret;
+}
+
+static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 value;
+#ifdef PM8001_USE_MSIX
+ return 1;
+#endif
+ value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR);
+ if (value)
+ return 1;
+ return 0;
+
+}
+
+/**
+ * pm8001_chip_isr - PM8001 isr handler.
+ * @pm8001_ha: our hba card information.
+ * @irq: irq number.
+ * @stat: stat.
+ */
+static irqreturn_t
+pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+ pm80xx_chip_interrupt_disable(pm8001_ha, vec);
+ process_oq(pm8001_ha, vec);
+ pm80xx_chip_interrupt_enable(pm8001_ha, vec);
+ return IRQ_HANDLED;
+}
+
+const struct pm8001_dispatch pm8001_80xx_dispatch = {
+ .name = "pmc80xx",
+ .chip_init = pm80xx_chip_init,
+ .chip_soft_rst = pm80xx_chip_soft_rst,
+ .chip_rst = pm80xx_hw_chip_rst,
+ .chip_iounmap = pm8001_chip_iounmap,
+ .isr = pm80xx_chip_isr,
+ .is_our_interupt = pm80xx_chip_is_our_interupt,
+ .isr_process_oq = process_oq,
+ .interrupt_enable = pm80xx_chip_interrupt_enable,
+ .interrupt_disable = pm80xx_chip_interrupt_disable,
+ .make_prd = pm8001_chip_make_sg,
+ .smp_req = pm80xx_chip_smp_req,
+ .ssp_io_req = pm80xx_chip_ssp_io_req,
+ .sata_req = pm80xx_chip_sata_req,
+ .phy_start_req = pm80xx_chip_phy_start_req,
+ .phy_stop_req = pm80xx_chip_phy_stop_req,
+ .reg_dev_req = pm80xx_chip_reg_dev_req,
+ .dereg_dev_req = pm8001_chip_dereg_dev_req,
+ .phy_ctl_req = pm80xx_chip_phy_ctl_req,
+ .task_abort = pm8001_chip_abort_task,
+ .ssp_tm_req = pm8001_chip_ssp_tm_req,
+ .get_nvmd_req = pm8001_chip_get_nvmd_req,
+ .set_nvmd_req = pm8001_chip_set_nvmd_req,
+ .fw_flash_update_req = pm8001_chip_fw_flash_update_req,
+ .set_dev_state_req = pm8001_chip_set_dev_state_req,
+};
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
new file mode 100644
index 0000000..2b760ba
--- /dev/null
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -0,0 +1,1523 @@
+/*
+ * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver
+ *
+ * Copyright (c) 2008-2009 USI Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#ifndef _PMC8001_REG_H_
+#define _PMC8001_REG_H_
+
+#include <linux/types.h>
+#include <scsi/libsas.h>
+
+/* for Request Opcode of IOMB */
+#define OPC_INB_ECHO 1 /* 0x000 */
+#define OPC_INB_PHYSTART 4 /* 0x004 */
+#define OPC_INB_PHYSTOP 5 /* 0x005 */
+#define OPC_INB_SSPINIIOSTART 6 /* 0x006 */
+#define OPC_INB_SSPINITMSTART 7 /* 0x007 */
+/* 0x8 RESV IN SPCv */
+#define OPC_INB_RSVD 8 /* 0x008 */
+#define OPC_INB_DEV_HANDLE_ACCEPT 9 /* 0x009 */
+#define OPC_INB_SSPTGTIOSTART 10 /* 0x00A */
+#define OPC_INB_SSPTGTRSPSTART 11 /* 0x00B */
+/* 0xC, 0xD, 0xE removed in SPCv */
+#define OPC_INB_SSP_ABORT 15 /* 0x00F */
+#define OPC_INB_DEREG_DEV_HANDLE 16 /* 0x010 */
+#define OPC_INB_GET_DEV_HANDLE 17 /* 0x011 */
+#define OPC_INB_SMP_REQUEST 18 /* 0x012 */
+/* 0x13 SMP_RESPONSE is removed in SPCv */
+#define OPC_INB_SMP_ABORT 20 /* 0x014 */
+/* 0x16 RESV IN SPCv */
+#define OPC_INB_RSVD1 22 /* 0x016 */
+#define OPC_INB_SATA_HOST_OPSTART 23 /* 0x017 */
+#define OPC_INB_SATA_ABORT 24 /* 0x018 */
+#define OPC_INB_LOCAL_PHY_CONTROL 25 /* 0x019 */
+/* 0x1A RESV IN SPCv */
+#define OPC_INB_RSVD2 26 /* 0x01A */
+#define OPC_INB_FW_FLASH_UPDATE 32 /* 0x020 */
+#define OPC_INB_GPIO 34 /* 0x022 */
+#define OPC_INB_SAS_DIAG_MODE_START_END 35 /* 0x023 */
+#define OPC_INB_SAS_DIAG_EXECUTE 36 /* 0x024 */
+/* 0x25 RESV IN SPCv */
+#define OPC_INB_RSVD3 37 /* 0x025 */
+#define OPC_INB_GET_TIME_STAMP 38 /* 0x026 */
+#define OPC_INB_PORT_CONTROL 39 /* 0x027 */
+#define OPC_INB_GET_NVMD_DATA 40 /* 0x028 */
+#define OPC_INB_SET_NVMD_DATA 41 /* 0x029 */
+#define OPC_INB_SET_DEVICE_STATE 42 /* 0x02A */
+#define OPC_INB_GET_DEVICE_STATE 43 /* 0x02B */
+#define OPC_INB_SET_DEV_INFO 44 /* 0x02C */
+/* 0x2D RESV IN SPCv */
+#define OPC_INB_RSVD4 45 /* 0x02D */
+#define OPC_INB_SGPIO_REGISTER 46 /* 0x02E */
+#define OPC_INB_PCIE_DIAG_EXEC 47 /* 0x02F */
+#define OPC_INB_SET_CONTROLLER_CONFIG 48 /* 0x030 */
+#define OPC_INB_GET_CONTROLLER_CONFIG 49 /* 0x031 */
+#define OPC_INB_REG_DEV 50 /* 0x032 */
+#define OPC_INB_SAS_HW_EVENT_ACK 51 /* 0x033 */
+#define OPC_INB_GET_DEVICE_INFO 52 /* 0x034 */
+#define OPC_INB_GET_PHY_PROFILE 53 /* 0x035 */
+#define OPC_INB_FLASH_OP_EXT 54 /* 0x036 */
+#define OPC_INB_SET_PHY_PROFILE 55 /* 0x037 */
+#define OPC_INB_KEK_MANAGEMENT 256 /* 0x100 */
+#define OPC_INB_DEK_MANAGEMENT 257 /* 0x101 */
+#define OPC_INB_SSP_INI_DIF_ENC_IO 258 /* 0x102 */
+#define OPC_INB_SATA_DIF_ENC_IO 259 /* 0x103 */
+
+/* for Response Opcode of IOMB */
+#define OPC_OUB_ECHO 1 /* 0x001 */
+#define OPC_OUB_RSVD 4 /* 0x004 */
+#define OPC_OUB_SSP_COMP 5 /* 0x005 */
+#define OPC_OUB_SMP_COMP 6 /* 0x006 */
+#define OPC_OUB_LOCAL_PHY_CNTRL 7 /* 0x007 */
+#define OPC_OUB_RSVD1 10 /* 0x00A */
+#define OPC_OUB_DEREG_DEV 11 /* 0x00B */
+#define OPC_OUB_GET_DEV_HANDLE 12 /* 0x00C */
+#define OPC_OUB_SATA_COMP 13 /* 0x00D */
+#define OPC_OUB_SATA_EVENT 14 /* 0x00E */
+#define OPC_OUB_SSP_EVENT 15 /* 0x00F */
+#define OPC_OUB_RSVD2 16 /* 0x010 */
+/* 0x11 - SMP_RECEIVED Notification removed in SPCv*/
+#define OPC_OUB_SSP_RECV_EVENT 18 /* 0x012 */
+#define OPC_OUB_RSVD3 19 /* 0x013 */
+#define OPC_OUB_FW_FLASH_UPDATE 20 /* 0x014 */
+#define OPC_OUB_GPIO_RESPONSE 22 /* 0x016 */
+#define OPC_OUB_GPIO_EVENT 23 /* 0x017 */
+#define OPC_OUB_GENERAL_EVENT 24 /* 0x018 */
+#define OPC_OUB_SSP_ABORT_RSP 26 /* 0x01A */
+#define OPC_OUB_SATA_ABORT_RSP 27 /* 0x01B */
+#define OPC_OUB_SAS_DIAG_MODE_START_END 28 /* 0x01C */
+#define OPC_OUB_SAS_DIAG_EXECUTE 29 /* 0x01D */
+#define OPC_OUB_GET_TIME_STAMP 30 /* 0x01E */
+#define OPC_OUB_RSVD4 31 /* 0x01F */
+#define OPC_OUB_PORT_CONTROL 32 /* 0x020 */
+#define OPC_OUB_SKIP_ENTRY 33 /* 0x021 */
+#define OPC_OUB_SMP_ABORT_RSP 34 /* 0x022 */
+#define OPC_OUB_GET_NVMD_DATA 35 /* 0x023 */
+#define OPC_OUB_SET_NVMD_DATA 36 /* 0x024 */
+#define OPC_OUB_DEVICE_HANDLE_REMOVAL 37 /* 0x025 */
+#define OPC_OUB_SET_DEVICE_STATE 38 /* 0x026 */
+#define OPC_OUB_GET_DEVICE_STATE 39 /* 0x027 */
+#define OPC_OUB_SET_DEV_INFO 40 /* 0x028 */
+#define OPC_OUB_RSVD5 41 /* 0x029 */
+#define OPC_OUB_HW_EVENT 1792 /* 0x700 */
+#define OPC_OUB_DEV_HANDLE_ARRIV 1824 /* 0x720 */
+#define OPC_OUB_THERM_HW_EVENT 1840 /* 0x730 */
+#define OPC_OUB_SGPIO_RESP 2094 /* 0x82E */
+#define OPC_OUB_PCIE_DIAG_EXECUTE 2095 /* 0x82F */
+#define OPC_OUB_DEV_REGIST 2098 /* 0x832 */
+#define OPC_OUB_SAS_HW_EVENT_ACK 2099 /* 0x833 */
+#define OPC_OUB_GET_DEVICE_INFO 2100 /* 0x834 */
+/* spcv specific commands */
+#define OPC_OUB_PHY_START_RESP 2052 /* 0x804 */
+#define OPC_OUB_PHY_STOP_RESP 2053 /* 0x805 */
+#define OPC_OUB_SET_CONTROLLER_CONFIG 2096 /* 0x830 */
+#define OPC_OUB_GET_CONTROLLER_CONFIG 2097 /* 0x831 */
+#define OPC_OUB_GET_PHY_PROFILE 2101 /* 0x835 */
+#define OPC_OUB_FLASH_OP_EXT 2102 /* 0x836 */
+#define OPC_OUB_SET_PHY_PROFILE 2103 /* 0x837 */
+#define OPC_OUB_KEK_MANAGEMENT_RESP 2304 /* 0x900 */
+#define OPC_OUB_DEK_MANAGEMENT_RESP 2305 /* 0x901 */
+#define OPC_OUB_SSP_COALESCED_COMP_RESP 2306 /* 0x902 */
+
+/* for phy start*/
+#define SSC_DISABLE_15 (0x01 << 16)
+#define SSC_DISABLE_30 (0x02 << 16)
+#define SSC_DISABLE_60 (0x04 << 16)
+#define SAS_ASE (0x01 << 15)
+#define SPINHOLD_DISABLE (0x00 << 14)
+#define SPINHOLD_ENABLE (0x01 << 14)
+#define LINKMODE_SAS (0x01 << 12)
+#define LINKMODE_DSATA (0x02 << 12)
+#define LINKMODE_AUTO (0x03 << 12)
+#define LINKRATE_15 (0x01 << 8)
+#define LINKRATE_30 (0x02 << 8)
+#define LINKRATE_60 (0x06 << 8)
+
+/* Thermal related */
+#define THERMAL_ENABLE 0x1
+#define THERMAL_LOG_ENABLE 0x1
+#define THERMAL_OP_CODE 0x6
+#define LTEMPHIL 70
+#define RTEMPHIL 100
+
+/* Encryption info */
+#define SCRATCH_PAD3_ENC_DISABLED 0x00000000
+#define SCRATCH_PAD3_ENC_DIS_ERR 0x00000001
+#define SCRATCH_PAD3_ENC_ENA_ERR 0x00000002
+#define SCRATCH_PAD3_ENC_READY 0x00000003
+#define SCRATCH_PAD3_ENC_MASK SCRATCH_PAD3_ENC_READY
+
+#define SCRATCH_PAD3_XTS_ENABLED (1 << 14)
+#define SCRATCH_PAD3_SMA_ENABLED (1 << 4)
+#define SCRATCH_PAD3_SMB_ENABLED (1 << 5)
+#define SCRATCH_PAD3_SMF_ENABLED 0
+#define SCRATCH_PAD3_SM_MASK 0x000000F0
+#define SCRATCH_PAD3_ERR_CODE 0x00FF0000
+
+#define SEC_MODE_SMF 0x0
+#define SEC_MODE_SMA 0x100
+#define SEC_MODE_SMB 0x200
+#define CIPHER_MODE_ECB 0x00000001
+#define CIPHER_MODE_XTS 0x00000002
+#define KEK_MGMT_SUBOP_KEYCARDUPDATE 0x4
+
+/* SAS protocol timer configuration page */
+#define SAS_PROTOCOL_TIMER_CONFIG_PAGE 0x04
+#define STP_MCT_TMO 32
+#define SSP_MCT_TMO 32
+#define SAS_MAX_OPEN_TIME 5
+#define SMP_MAX_CONN_TIMER 0xFF
+#define STP_FRM_TIMER 0
+#define STP_IDLE_TIME 5 /* 5 us; controller default */
+#define SAS_MFD 0
+#define SAS_OPNRJT_RTRY_INTVL 2
+#define SAS_DOPNRJT_RTRY_TMO 128
+#define SAS_COPNRJT_RTRY_TMO 128
+
+/*
+ Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
+ Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
+ is DOPNRJT_RTRY_TMO
+*/
+#define SAS_DOPNRJT_RTRY_THR 23438
+#define SAS_COPNRJT_RTRY_THR 23438
+#define SAS_MAX_AIP 0x200000
+#define IT_NEXUS_TIMEOUT 0x7D0
+#define PORT_RECOVERY_TIMEOUT ((IT_NEXUS_TIMEOUT/100) + 30)
+
+struct mpi_msg_hdr {
+ __le32 header; /* Bits [11:0] - Message operation code */
+ /* Bits [15:12] - Message Category */
+ /* Bits [21:16] - Outboundqueue ID for the
+ operation completion message */
+ /* Bits [23:22] - Reserved */
+ /* Bits [28:24] - Buffer Count, indicates how
+ many buffer are allocated for the massage */
+ /* Bits [30:29] - Reserved */
+ /* Bits [31] - Message Valid bit */
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY Start Command
+ * use to describe enable the phy (128 bytes)
+ */
+struct phy_start_req {
+ __le32 tag;
+ __le32 ase_sh_lm_slr_phyid;
+ struct sas_identify_frame sas_identify; /* 28 Bytes */
+ __le32 spasti;
+ u32 reserved[21];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY Start Command
+ * use to disable the phy (128 bytes)
+ */
+struct phy_stop_req {
+ __le32 tag;
+ __le32 phy_id;
+ u32 reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/* set device bits fis - device to host */
+struct set_dev_bits_fis {
+ u8 fis_type; /* 0xA1*/
+ u8 n_i_pmport;
+ /* b7 : n Bit. Notification bit. If set device needs attention. */
+ /* b6 : i Bit. Interrupt Bit */
+ /* b5-b4: reserved2 */
+ /* b3-b0: PM Port */
+ u8 status;
+ u8 error;
+ u32 _r_a;
+} __attribute__ ((packed));
+/* PIO setup FIS - device to host */
+struct pio_setup_fis {
+ u8 fis_type; /* 0x5f */
+ u8 i_d_pmPort;
+ /* b7 : reserved */
+ /* b6 : i bit. Interrupt bit */
+ /* b5 : d bit. data transfer direction. set to 1 for device to host
+ xfer */
+ /* b4 : reserved */
+ /* b3-b0: PM Port */
+ u8 status;
+ u8 error;
+ u8 lbal;
+ u8 lbam;
+ u8 lbah;
+ u8 device;
+ u8 lbal_exp;
+ u8 lbam_exp;
+ u8 lbah_exp;
+ u8 _r_a;
+ u8 sector_count;
+ u8 sector_count_exp;
+ u8 _r_b;
+ u8 e_status;
+ u8 _r_c[2];
+ u8 transfer_count;
+} __attribute__ ((packed));
+
+/*
+ * brief the data structure of SATA Completion Response
+ * use to describe the sata task response (64 bytes)
+ */
+struct sata_completion_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 param;
+ u32 sata_resp[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SAS HW Event Notification
+ * use to alert the host about the hardware event(64 bytes)
+ */
+/* updated outbound struct for spcv */
+
+struct hw_event_resp {
+ __le32 lr_status_evt_portid;
+ __le32 evt_param;
+ __le32 phyid_npip_portstate;
+ struct sas_identify_frame sas_identify;
+ struct dev_to_host_fis sata_fis;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure for thermal event notification
+ */
+
+struct thermal_hw_event {
+ __le32 thermal_event;
+ __le32 rht_lht;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of REGISTER DEVICE Command
+ * use to describe MPI REGISTER DEVICE Command (64 bytes)
+ */
+
+struct reg_dev_req {
+ __le32 tag;
+ __le32 phyid_portid;
+ __le32 dtype_dlr_mcn_ir_retry;
+ __le32 firstburstsize_ITNexustimeout;
+ u8 sas_addr[SAS_ADDR_SIZE];
+ __le32 upper_device_id;
+ u32 reserved[24];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of DEREGISTER DEVICE Command
+ * use to request spc to remove all internal resources associated
+ * with the device id (64 bytes)
+ */
+
+struct dereg_dev_req {
+ __le32 tag;
+ __le32 device_id;
+ u32 reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of DEVICE_REGISTRATION Response
+ * use to notify the completion of the device registration (64 bytes)
+ */
+struct dev_reg_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 device_id;
+ u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of Local PHY Control Command
+ * use to issue PHY CONTROL to local phy (64 bytes)
+ */
+struct local_phy_ctl_req {
+ __le32 tag;
+ __le32 phyop_phyid;
+ u32 reserved1[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Local Phy Control Response
+ * use to describe MPI Local Phy Control Response (64 bytes)
+ */
+ struct local_phy_ctl_resp {
+ __le32 tag;
+ __le32 phyop_phyid;
+ __le32 status;
+ u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+#define OP_BITS 0x0000FF00
+#define ID_BITS 0x000000FF
+
+/*
+ * brief the data structure of PORT Control Command
+ * use to control port properties (64 bytes)
+ */
+
+struct port_ctl_req {
+ __le32 tag;
+ __le32 portop_portid;
+ __le32 param0;
+ __le32 param1;
+ u32 reserved1[27];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of HW Event Ack Command
+ * use to acknowledge receive HW event (64 bytes)
+ */
+struct hw_event_ack_req {
+ __le32 tag;
+ __le32 phyid_sea_portid;
+ __le32 param0;
+ __le32 param1;
+ u32 reserved1[27];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY_START Response Command
+ * indicates the completion of PHY_START command (64 bytes)
+ */
+struct phy_start_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 phyid;
+ u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY_STOP Response Command
+ * indicates the completion of PHY_STOP command (64 bytes)
+ */
+struct phy_stop_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 phyid;
+ u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SSP Completion Response
+ * use to indicate a SSP Completion (n bytes)
+ */
+struct ssp_completion_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 param;
+ __le32 ssptag_rescv_rescpad;
+ struct ssp_response_iu ssp_resp_iu;
+ __le32 residual_count;
+} __attribute__((packed, aligned(4)));
+
+#define SSP_RESCV_BIT 0x00010000
+
+/*
+ * brief the data structure of SATA EVNET response
+ * use to indicate a SATA Completion (64 bytes)
+ */
+struct sata_event_resp {
+ __le32 tag;
+ __le32 event;
+ __le32 port_id;
+ __le32 device_id;
+ u32 reserved;
+ __le32 event_param0;
+ __le32 event_param1;
+ __le32 sata_addr_h32;
+ __le32 sata_addr_l32;
+ __le32 e_udt1_udt0_crc;
+ __le32 e_udt5_udt4_udt3_udt2;
+ __le32 a_udt1_udt0_crc;
+ __le32 a_udt5_udt4_udt3_udt2;
+ __le32 hwdevid_diferr;
+ __le32 err_framelen_byteoffset;
+ __le32 err_dataframe;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SSP EVNET esponse
+ * use to indicate a SSP Completion (64 bytes)
+ */
+struct ssp_event_resp {
+ __le32 tag;
+ __le32 event;
+ __le32 port_id;
+ __le32 device_id;
+ __le32 ssp_tag;
+ __le32 event_param0;
+ __le32 event_param1;
+ __le32 sas_addr_h32;
+ __le32 sas_addr_l32;
+ __le32 e_udt1_udt0_crc;
+ __le32 e_udt5_udt4_udt3_udt2;
+ __le32 a_udt1_udt0_crc;
+ __le32 a_udt5_udt4_udt3_udt2;
+ __le32 hwdevid_diferr;
+ __le32 err_framelen_byteoffset;
+ __le32 err_dataframe;
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of General Event Notification Response
+ * use to describe MPI General Event Notification Response (64 bytes)
+ */
+struct general_event_resp {
+ __le32 status;
+ __le32 inb_IOMB_payload[14];
+} __attribute__((packed, aligned(4)));
+
+#define GENERAL_EVENT_PAYLOAD 14
+#define OPCODE_BITS 0x00000fff
+
+/*
+ * brief the data structure of SMP Request Command
+ * use to describe MPI SMP REQUEST Command (64 bytes)
+ */
+struct smp_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 len_ip_ir;
+ /* Bits [0] - Indirect response */
+ /* Bits [1] - Indirect Payload */
+ /* Bits [15:2] - Reserved */
+ /* Bits [23:16] - direct payload Len */
+ /* Bits [31:24] - Reserved */
+ u8 smp_req16[16];
+ union {
+ u8 smp_req[32];
+ struct {
+ __le64 long_req_addr;/* sg dma address, LE */
+ __le32 long_req_size;/* LE */
+ u32 _r_a;
+ __le64 long_resp_addr;/* sg dma address, LE */
+ __le32 long_resp_size;/* LE */
+ u32 _r_b;
+ } long_smp_req;/* sequencer extension */
+ };
+ __le32 rsvd[16];
+} __attribute__((packed, aligned(4)));
+/*
+ * brief the data structure of SMP Completion Response
+ * use to describe MPI SMP Completion Response (64 bytes)
+ */
+struct smp_completion_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 param;
+ u8 _r_a[252];
+} __attribute__((packed, aligned(4)));
+
+/*
+ *brief the data structure of SSP SMP SATA Abort Command
+ * use to describe MPI SSP SMP & SATA Abort Command (64 bytes)
+ */
+struct task_abort_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 tag_to_abort;
+ __le32 abort_all;
+ u32 reserved[27];
+} __attribute__((packed, aligned(4)));
+
+/* These flags used for SSP SMP & SATA Abort */
+#define ABORT_MASK 0x3
+#define ABORT_SINGLE 0x0
+#define ABORT_ALL 0x1
+
+/**
+ * brief the data structure of SSP SATA SMP Abort Response
+ * use to describe SSP SMP & SATA Abort Response ( 64 bytes)
+ */
+struct task_abort_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 scp;
+ u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Start/End Command
+ * use to describe MPI SAS Diagnostic Start/End Command (64 bytes)
+ */
+struct sas_diag_start_end_req {
+ __le32 tag;
+ __le32 operation_phyid;
+ u32 reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Execute Command
+ * use to describe MPI SAS Diagnostic Execute Command (64 bytes)
+ */
+struct sas_diag_execute_req {
+ __le32 tag;
+ __le32 cmdtype_cmddesc_phyid;
+ __le32 pat1_pat2;
+ __le32 threshold;
+ __le32 codepat_errmsk;
+ __le32 pmon;
+ __le32 pERF1CTL;
+ u32 reserved[24];
+} __attribute__((packed, aligned(4)));
+
+#define SAS_DIAG_PARAM_BYTES 24
+
+/*
+ * brief the data structure of Set Device State Command
+ * use to describe MPI Set Device State Command (64 bytes)
+ */
+struct set_dev_state_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 nds;
+ u32 reserved[28];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SATA Start Command
+ * use to describe MPI SATA IO Start Command (64 bytes)
+ * Note: This structure is common for normal / encryption I/O
+ */
+
+struct sata_start_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 data_len;
+ __le32 ncqtag_atap_dir_m_dad;
+ struct host_to_dev_fis sata_fis;
+ u32 reserved1;
+ u32 reserved2; /* dword 11. rsvd for normal I/O. */
+ /* EPLE Descl for enc I/O */
+ u32 addr_low; /* dword 12. rsvd for enc I/O */
+ u32 addr_high; /* dword 13. reserved for enc I/O */
+ __le32 len; /* dword 14: length for normal I/O. */
+ /* EPLE Desch for enc I/O */
+ __le32 esgl; /* dword 15. rsvd for enc I/O */
+ __le32 atapi_scsi_cdb[4]; /* dword 16-19. rsvd for enc I/O */
+ /* The below fields are reserved for normal I/O */
+ __le32 key_index_mode; /* dword 20 */
+ __le32 sector_cnt_enss;/* dword 21 */
+ __le32 keytagl; /* dword 22 */
+ __le32 keytagh; /* dword 23 */
+ __le32 twk_val0; /* dword 24 */
+ __le32 twk_val1; /* dword 25 */
+ __le32 twk_val2; /* dword 26 */
+ __le32 twk_val3; /* dword 27 */
+ __le32 enc_addr_low; /* dword 28. Encryption SGL address high */
+ __le32 enc_addr_high; /* dword 29. Encryption SGL address low */
+ __le32 enc_len; /* dword 30. Encryption length */
+ __le32 enc_esgl; /* dword 31. Encryption esgl bit */
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SSP INI TM Start Command
+ * use to describe MPI SSP INI TM Start Command (64 bytes)
+ */
+struct ssp_ini_tm_start_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 relate_tag;
+ __le32 tmf;
+ u8 lun[8];
+ __le32 ds_ads_m;
+ u32 reserved[24];
+} __attribute__((packed, aligned(4)));
+
+struct ssp_info_unit {
+ u8 lun[8];/* SCSI Logical Unit Number */
+ u8 reserved1;/* reserved */
+ u8 efb_prio_attr;
+ /* B7 : enabledFirstBurst */
+ /* B6-3 : taskPriority */
+ /* B2-0 : taskAttribute */
+ u8 reserved2; /* reserved */
+ u8 additional_cdb_len;
+ /* B7-2 : additional_cdb_len */
+ /* B1-0 : reserved */
+ u8 cdb[16];/* The SCSI CDB up to 16 bytes length */
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SSP INI IO Start Command
+ * use to describe MPI SSP INI IO Start Command (64 bytes)
+ * Note: This structure is common for normal / encryption I/O
+ */
+struct ssp_ini_io_start_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 data_len;
+ __le32 dad_dir_m_tlr;
+ struct ssp_info_unit ssp_iu;
+ __le32 addr_low; /* dword 12: sgl low for normal I/O. */
+ /* epl_descl for encryption I/O */
+ __le32 addr_high; /* dword 13: sgl hi for normal I/O */
+ /* dpl_descl for encryption I/O */
+ __le32 len; /* dword 14: len for normal I/O. */
+ /* edpl_desch for encryption I/O */
+ __le32 esgl; /* dword 15: ESGL bit for normal I/O. */
+ /* user defined tag mask for enc I/O */
+ /* The below fields are reserved for normal I/O */
+ u8 udt[12]; /* dword 16-18 */
+ __le32 sectcnt_ios; /* dword 19 */
+ __le32 key_cmode; /* dword 20 */
+ __le32 ks_enss; /* dword 21 */
+ __le32 keytagl; /* dword 22 */
+ __le32 keytagh; /* dword 23 */
+ __le32 twk_val0; /* dword 24 */
+ __le32 twk_val1; /* dword 25 */
+ __le32 twk_val2; /* dword 26 */
+ __le32 twk_val3; /* dword 27 */
+ __le32 enc_addr_low; /* dword 28: Encryption sgl addr low */
+ __le32 enc_addr_high; /* dword 29: Encryption sgl addr hi */
+ __le32 enc_len; /* dword 30: Encryption length */
+ __le32 enc_esgl; /* dword 31: ESGL bit for encryption */
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for SSP_INI_DIF_ENC_IO COMMAND
+ * use to initiate SSP I/O operation with optional DIF/ENC
+ */
+struct ssp_dif_enc_io_req {
+ __le32 tag;
+ __le32 device_id;
+ __le32 data_len;
+ __le32 dirMTlr;
+ __le32 sspiu0;
+ __le32 sspiu1;
+ __le32 sspiu2;
+ __le32 sspiu3;
+ __le32 sspiu4;
+ __le32 sspiu5;
+ __le32 sspiu6;
+ __le32 epl_des;
+ __le32 dpl_desl_ndplr;
+ __le32 dpl_desh;
+ __le32 uum_uuv_bss_difbits;
+ u8 udt[12];
+ __le32 sectcnt_ios;
+ __le32 key_cmode;
+ __le32 ks_enss;
+ __le32 keytagl;
+ __le32 keytagh;
+ __le32 twk_val0;
+ __le32 twk_val1;
+ __le32 twk_val2;
+ __le32 twk_val3;
+ __le32 addr_low;
+ __le32 addr_high;
+ __le32 len;
+ __le32 esgl;
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Firmware download
+ * use to describe MPI FW DOWNLOAD Command (64 bytes)
+ */
+struct fw_flash_Update_req {
+ __le32 tag;
+ __le32 cur_image_offset;
+ __le32 cur_image_len;
+ __le32 total_image_len;
+ u32 reserved0[7];
+ __le32 sgl_addr_lo;
+ __le32 sgl_addr_hi;
+ __le32 len;
+ __le32 ext_reserved;
+ u32 reserved1[16];
+} __attribute__((packed, aligned(4)));
+
+#define FWFLASH_IOMB_RESERVED_LEN 0x07
+/**
+ * brief the data structure of FW_FLASH_UPDATE Response
+ * use to describe MPI FW_FLASH_UPDATE Response (64 bytes)
+ *
+ */
+ struct fw_flash_Update_resp {
+ __le32 tag;
+ __le32 status;
+ u32 reserved[13];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Get NVM Data Command
+ * use to get data from NVM in HBA(64 bytes)
+ */
+struct get_nvm_data_req {
+ __le32 tag;
+ __le32 len_ir_vpdd;
+ __le32 vpd_offset;
+ u32 reserved[8];
+ __le32 resp_addr_lo;
+ __le32 resp_addr_hi;
+ __le32 resp_len;
+ u32 reserved1[17];
+} __attribute__((packed, aligned(4)));
+
+struct set_nvm_data_req {
+ __le32 tag;
+ __le32 len_ir_vpdd;
+ __le32 vpd_offset;
+ u32 reserved[8];
+ __le32 resp_addr_lo;
+ __le32 resp_addr_hi;
+ __le32 resp_len;
+ u32 reserved1[17];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for SET CONTROLLER CONFIG COMMAND
+ * use to modify controller configuration
+ */
+struct set_ctrl_cfg_req {
+ __le32 tag;
+ __le32 cfg_pg[14];
+ u32 reserved[16];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for GET CONTROLLER CONFIG COMMAND
+ * use to get controller configuration page
+ */
+struct get_ctrl_cfg_req {
+ __le32 tag;
+ __le32 pgcd;
+ __le32 int_vec;
+ u32 reserved[28];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for KEK_MANAGEMENT COMMAND
+ * use for KEK management
+ */
+struct kek_mgmt_req {
+ __le32 tag;
+ __le32 new_curidx_ksop;
+ u32 reserved;
+ __le32 kblob[12];
+ u32 reserved1[16];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for DEK_MANAGEMENT COMMAND
+ * use for DEK management
+ */
+struct dek_mgmt_req {
+ __le32 tag;
+ __le32 kidx_dsop;
+ __le32 dekidx;
+ __le32 addr_l;
+ __le32 addr_h;
+ __le32 nent;
+ __le32 dbf_tblsize;
+ u32 reserved[24];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for SET PHY PROFILE COMMAND
+ * use to retrive phy specific information
+ */
+struct set_phy_profile_req {
+ __le32 tag;
+ __le32 ppc_phyid;
+ u32 reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for GET PHY PROFILE COMMAND
+ * use to retrive phy specific information
+ */
+struct get_phy_profile_req {
+ __le32 tag;
+ __le32 ppc_phyid;
+ __le32 profile[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for EXT FLASH PARTITION
+ * use to manage ext flash partition
+ */
+struct ext_flash_partition_req {
+ __le32 tag;
+ __le32 cmd;
+ __le32 offset;
+ __le32 len;
+ u32 reserved[7];
+ __le32 addr_low;
+ __le32 addr_high;
+ __le32 len1;
+ __le32 ext;
+ u32 reserved1[16];
+} __attribute__((packed, aligned(4)));
+
+#define TWI_DEVICE 0x0
+#define C_SEEPROM 0x1
+#define VPD_FLASH 0x4
+#define AAP1_RDUMP 0x5
+#define IOP_RDUMP 0x6
+#define EXPAN_ROM 0x7
+
+#define IPMode 0x80000000
+#define NVMD_TYPE 0x0000000F
+#define NVMD_STAT 0x0000FFFF
+#define NVMD_LEN 0xFF000000
+/**
+ * brief the data structure of Get NVMD Data Response
+ * use to describe MPI Get NVMD Data Response (64 bytes)
+ */
+struct get_nvm_data_resp {
+ __le32 tag;
+ __le32 ir_tda_bn_dps_das_nvm;
+ __le32 dlen_status;
+ __le32 nvm_data[12];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Start/End Response
+ * use to describe MPI SAS Diagnostic Start/End Response (64 bytes)
+ *
+ */
+struct sas_diag_start_end_resp {
+ __le32 tag;
+ __le32 status;
+ u32 reserved[13];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Execute Response
+ * use to describe MPI SAS Diagnostic Execute Response (64 bytes)
+ *
+ */
+struct sas_diag_execute_resp {
+ __le32 tag;
+ __le32 cmdtype_cmddesc_phyid;
+ __le32 Status;
+ __le32 ReportData;
+ u32 reserved[11];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Set Device State Response
+ * use to describe MPI Set Device State Response (64 bytes)
+ *
+ */
+struct set_dev_state_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 device_id;
+ __le32 pds_nds;
+ u32 reserved[11];
+} __attribute__((packed, aligned(4)));
+
+/* new outbound structure for spcv - begins */
+/**
+ * brief the data structure for SET CONTROLLER CONFIG COMMAND
+ * use to modify controller configuration
+ */
+struct set_ctrl_cfg_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 err_qlfr_pgcd;
+ u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+struct get_ctrl_cfg_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 err_qlfr;
+ __le32 confg_page[12];
+} __attribute__((packed, aligned(4)));
+
+struct kek_mgmt_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 kidx_new_curr_ksop;
+ __le32 err_qlfr;
+ u32 reserved[11];
+} __attribute__((packed, aligned(4)));
+
+struct dek_mgmt_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 kekidx_tbls_dsop;
+ __le32 dekidx;
+ __le32 err_qlfr;
+ u32 reserved[10];
+} __attribute__((packed, aligned(4)));
+
+struct get_phy_profile_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 ppc_phyid;
+ __le32 ppc_specific_rsp[12];
+} __attribute__((packed, aligned(4)));
+
+struct flash_op_ext_resp {
+ __le32 tag;
+ __le32 cmd;
+ __le32 status;
+ __le32 epart_size;
+ __le32 epart_sect_size;
+ u32 reserved[10];
+} __attribute__((packed, aligned(4)));
+
+struct set_phy_profile_resp {
+ __le32 tag;
+ __le32 status;
+ __le32 ppc_phyid;
+ __le32 ppc_specific_rsp[12];
+} __attribute__((packed, aligned(4)));
+
+struct ssp_coalesced_comp_resp {
+ __le32 coal_cnt;
+ __le32 tag0;
+ __le32 ssp_tag0;
+ __le32 tag1;
+ __le32 ssp_tag1;
+ __le32 add_tag_ssp_tag[10];
+} __attribute__((packed, aligned(4)));
+
+/* new outbound structure for spcv - ends */
+
+/* brief data structure for SAS protocol timer configuration page.
+ *
+ */
+struct SASProtocolTimerConfig {
+ __le32 pageCode; /* 0 */
+ __le32 MST_MSI; /* 1 */
+ __le32 STP_SSP_MCT_TMO; /* 2 */
+ __le32 STP_FRM_TMO; /* 3 */
+ __le32 STP_IDLE_TMO; /* 4 */
+ __le32 OPNRJT_RTRY_INTVL; /* 5 */
+ __le32 Data_Cmd_OPNRJT_RTRY_TMO; /* 6 */
+ __le32 Data_Cmd_OPNRJT_RTRY_THR; /* 7 */
+ __le32 MAX_AIP; /* 8 */
+} __attribute__((packed, aligned(4)));
+
+typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
+
+#define NDS_BITS 0x0F
+#define PDS_BITS 0xF0
+
+/*
+ * HW Events type
+ */
+
+#define HW_EVENT_RESET_START 0x01
+#define HW_EVENT_CHIP_RESET_COMPLETE 0x02
+#define HW_EVENT_PHY_STOP_STATUS 0x03
+#define HW_EVENT_SAS_PHY_UP 0x04
+#define HW_EVENT_SATA_PHY_UP 0x05
+#define HW_EVENT_SATA_SPINUP_HOLD 0x06
+#define HW_EVENT_PHY_DOWN 0x07
+#define HW_EVENT_PORT_INVALID 0x08
+#define HW_EVENT_BROADCAST_CHANGE 0x09
+#define HW_EVENT_PHY_ERROR 0x0A
+#define HW_EVENT_BROADCAST_SES 0x0B
+#define HW_EVENT_INBOUND_CRC_ERROR 0x0C
+#define HW_EVENT_HARD_RESET_RECEIVED 0x0D
+#define HW_EVENT_MALFUNCTION 0x0E
+#define HW_EVENT_ID_FRAME_TIMEOUT 0x0F
+#define HW_EVENT_BROADCAST_EXP 0x10
+#define HW_EVENT_PHY_START_STATUS 0x11
+#define HW_EVENT_LINK_ERR_INVALID_DWORD 0x12
+#define HW_EVENT_LINK_ERR_DISPARITY_ERROR 0x13
+#define HW_EVENT_LINK_ERR_CODE_VIOLATION 0x14
+#define HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH 0x15
+#define HW_EVENT_LINK_ERR_PHY_RESET_FAILED 0x16
+#define HW_EVENT_PORT_RECOVERY_TIMER_TMO 0x17
+#define HW_EVENT_PORT_RECOVER 0x18
+#define HW_EVENT_PORT_RESET_TIMER_TMO 0x19
+#define HW_EVENT_PORT_RESET_COMPLETE 0x20
+#define EVENT_BROADCAST_ASYNCH_EVENT 0x21
+
+/* port state */
+#define PORT_NOT_ESTABLISHED 0x00
+#define PORT_VALID 0x01
+#define PORT_LOSTCOMM 0x02
+#define PORT_IN_RESET 0x04
+#define PORT_3RD_PARTY_RESET 0x07
+#define PORT_INVALID 0x08
+
+/*
+ * SSP/SMP/SATA IO Completion Status values
+ */
+
+#define IO_SUCCESS 0x00
+#define IO_ABORTED 0x01
+#define IO_OVERFLOW 0x02
+#define IO_UNDERFLOW 0x03
+#define IO_FAILED 0x04
+#define IO_ABORT_RESET 0x05
+#define IO_NOT_VALID 0x06
+#define IO_NO_DEVICE 0x07
+#define IO_ILLEGAL_PARAMETER 0x08
+#define IO_LINK_FAILURE 0x09
+#define IO_PROG_ERROR 0x0A
+
+#define IO_EDC_IN_ERROR 0x0B
+#define IO_EDC_OUT_ERROR 0x0C
+#define IO_ERROR_HW_TIMEOUT 0x0D
+#define IO_XFER_ERROR_BREAK 0x0E
+#define IO_XFER_ERROR_PHY_NOT_READY 0x0F
+#define IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED 0x10
+#define IO_OPEN_CNX_ERROR_ZONE_VIOLATION 0x11
+#define IO_OPEN_CNX_ERROR_BREAK 0x12
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS 0x13
+#define IO_OPEN_CNX_ERROR_BAD_DESTINATION 0x14
+#define IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED 0x15
+#define IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY 0x16
+#define IO_OPEN_CNX_ERROR_WRONG_DESTINATION 0x17
+/* This error code 0x18 is not used on SPCv */
+#define IO_OPEN_CNX_ERROR_UNKNOWN_ERROR 0x18
+#define IO_XFER_ERROR_NAK_RECEIVED 0x19
+#define IO_XFER_ERROR_ACK_NAK_TIMEOUT 0x1A
+#define IO_XFER_ERROR_PEER_ABORTED 0x1B
+#define IO_XFER_ERROR_RX_FRAME 0x1C
+#define IO_XFER_ERROR_DMA 0x1D
+#define IO_XFER_ERROR_CREDIT_TIMEOUT 0x1E
+#define IO_XFER_ERROR_SATA_LINK_TIMEOUT 0x1F
+#define IO_XFER_ERROR_SATA 0x20
+
+/* This error code 0x22 is not used on SPCv */
+#define IO_XFER_ERROR_ABORTED_DUE_TO_SRST 0x22
+#define IO_XFER_ERROR_REJECTED_NCQ_MODE 0x21
+#define IO_XFER_ERROR_ABORTED_NCQ_MODE 0x23
+#define IO_XFER_OPEN_RETRY_TIMEOUT 0x24
+/* This error code 0x25 is not used on SPCv */
+#define IO_XFER_SMP_RESP_CONNECTION_ERROR 0x25
+#define IO_XFER_ERROR_UNEXPECTED_PHASE 0x26
+#define IO_XFER_ERROR_XFER_RDY_OVERRUN 0x27
+#define IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED 0x28
+#define IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT 0x30
+
+/* The following error code 0x31 and 0x32 are not using (obsolete) */
+#define IO_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NAK 0x31
+#define IO_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK 0x32
+
+#define IO_XFER_ERROR_OFFSET_MISMATCH 0x34
+#define IO_XFER_ERROR_XFER_ZERO_DATA_LEN 0x35
+#define IO_XFER_CMD_FRAME_ISSUED 0x36
+#define IO_ERROR_INTERNAL_SMP_RESOURCE 0x37
+#define IO_PORT_IN_RESET 0x38
+#define IO_DS_NON_OPERATIONAL 0x39
+#define IO_DS_IN_RECOVERY 0x3A
+#define IO_TM_TAG_NOT_FOUND 0x3B
+#define IO_XFER_PIO_SETUP_ERROR 0x3C
+#define IO_SSP_EXT_IU_ZERO_LEN_ERROR 0x3D
+#define IO_DS_IN_ERROR 0x3E
+#define IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY 0x3F
+#define IO_ABORT_IN_PROGRESS 0x40
+#define IO_ABORT_DELAYED 0x41
+#define IO_INVALID_LENGTH 0x42
+
+/********** additional response event values *****************/
+
+#define IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY_ALT 0x43
+#define IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED 0x44
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO 0x45
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST 0x46
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE 0x47
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED 0x48
+#define IO_DS_INVALID 0x49
+/* WARNING: the value is not contiguous from here */
+#define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52
+#define IO_XFER_DMA_ACTIVATE_TIMEOUT 0x53
+#define IO_XFER_ERROR_INTERNAL_CRC_ERROR 0x54
+#define MPI_IO_RQE_BUSY_FULL 0x55
+#define IO_XFER_ERR_EOB_DATA_OVERRUN 0x56
+#define IO_XFR_ERROR_INVALID_SSP_RSP_FRAME 0x57
+#define IO_OPEN_CNX_ERROR_OPEN_PREEMPTED 0x58
+
+#define MPI_ERR_IO_RESOURCE_UNAVAILABLE 0x1004
+#define MPI_ERR_ATAPI_DEVICE_BUSY 0x1024
+
+#define IO_XFR_ERROR_DEK_KEY_CACHE_MISS 0x2040
+/*
+ * An encryption IO request failed due to DEK Key Tag mismatch.
+ * The key tag supplied in the encryption IOMB does not match with
+ * the Key Tag in the referenced DEK Entry.
+ */
+#define IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH 0x2041
+#define IO_XFR_ERROR_CIPHER_MODE_INVALID 0x2042
+/*
+ * An encryption I/O request failed because the initial value (IV)
+ * in the unwrapped DEK blob didn't match the IV used to unwrap it.
+ */
+#define IO_XFR_ERROR_DEK_IV_MISMATCH 0x2043
+/* An encryption I/O request failed due to an internal RAM ECC or
+ * interface error while unwrapping the DEK. */
+#define IO_XFR_ERROR_DEK_RAM_INTERFACE_ERROR 0x2044
+/* An encryption I/O request failed due to an internal RAM ECC or
+ * interface error while unwrapping the DEK. */
+#define IO_XFR_ERROR_INTERNAL_RAM 0x2045
+/*
+ * An encryption I/O request failed
+ * because the DEK index specified in the I/O was outside the bounds of
+ * the total number of entries in the host DEK table.
+ */
+#define IO_XFR_ERROR_DEK_INDEX_OUT_OF_BOUNDS0x2046
+
+/* define DIF IO response error status code */
+#define IO_XFR_ERROR_DIF_MISMATCH 0x3000
+#define IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH 0x3001
+#define IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH 0x3002
+#define IO_XFR_ERROR_DIF_CRC_MISMATCH 0x3003
+
+/* define operator management response status and error qualifier code */
+#define OPR_MGMT_OP_NOT_SUPPORTED 0x2060
+#define OPR_MGMT_MPI_ENC_ERR_OPR_PARAM_ILLEGAL 0x2061
+#define OPR_MGMT_MPI_ENC_ERR_OPR_ID_NOT_FOUND 0x2062
+#define OPR_MGMT_MPI_ENC_ERR_OPR_ROLE_NOT_MATCH 0x2063
+#define OPR_MGMT_MPI_ENC_ERR_OPR_MAX_NUM_EXCEEDED 0x2064
+#define OPR_MGMT_MPI_ENC_ERR_KEK_UNWRAP_FAIL 0x2022
+#define OPR_MGMT_MPI_ENC_ERR_NVRAM_OPERATION_FAILURE 0x2023
+/***************** additional response event values ***************/
+
+/* WARNING: This error code must always be the last number.
+ * If you add error code, modify this code also
+ * It is used as an index
+ */
+#define IO_ERROR_UNKNOWN_GENERIC 0x2023
+
+/* MSGU CONFIGURATION TABLE*/
+
+#define SPCv_MSGU_CFG_TABLE_UPDATE 0x01
+#define SPCv_MSGU_CFG_TABLE_RESET 0x02
+#define SPCv_MSGU_CFG_TABLE_FREEZE 0x04
+#define SPCv_MSGU_CFG_TABLE_UNFREEZE 0x08
+#define MSGU_IBDB_SET 0x00
+#define MSGU_HOST_INT_STATUS 0x08
+#define MSGU_HOST_INT_MASK 0x0C
+#define MSGU_IOPIB_INT_STATUS 0x18
+#define MSGU_IOPIB_INT_MASK 0x1C
+#define MSGU_IBDB_CLEAR 0x20
+
+#define MSGU_MSGU_CONTROL 0x24
+#define MSGU_ODR 0x20
+#define MSGU_ODCR 0x28
+
+#define MSGU_ODMR 0x30
+#define MSGU_ODMR_U 0x34
+#define MSGU_ODMR_CLR 0x38
+#define MSGU_ODMR_CLR_U 0x3C
+#define MSGU_OD_RSVD 0x40
+
+#define MSGU_SCRATCH_PAD_0 0x44
+#define MSGU_SCRATCH_PAD_1 0x48
+#define MSGU_SCRATCH_PAD_2 0x4C
+#define MSGU_SCRATCH_PAD_3 0x50
+#define MSGU_HOST_SCRATCH_PAD_0 0x54
+#define MSGU_HOST_SCRATCH_PAD_1 0x58
+#define MSGU_HOST_SCRATCH_PAD_2 0x5C
+#define MSGU_HOST_SCRATCH_PAD_3 0x60
+#define MSGU_HOST_SCRATCH_PAD_4 0x64
+#define MSGU_HOST_SCRATCH_PAD_5 0x68
+#define MSGU_HOST_SCRATCH_PAD_6 0x6C
+#define MSGU_HOST_SCRATCH_PAD_7 0x70
+
+/* bit definition for ODMR register */
+#define ODMR_MASK_ALL 0xFFFFFFFF/* mask all
+ interrupt vector */
+#define ODMR_CLEAR_ALL 0 /* clear all
+ interrupt vector */
+/* bit definition for ODCR register */
+#define ODCR_CLEAR_ALL 0xFFFFFFFF /* mask all
+ interrupt vector*/
+/* MSIX Interupts */
+#define MSIX_TABLE_OFFSET 0x2000
+#define MSIX_TABLE_ELEMENT_SIZE 0x10
+#define MSIX_INTERRUPT_CONTROL_OFFSET 0xC
+#define MSIX_TABLE_BASE (MSIX_TABLE_OFFSET + \
+ MSIX_INTERRUPT_CONTROL_OFFSET)
+#define MSIX_INTERRUPT_DISABLE 0x1
+#define MSIX_INTERRUPT_ENABLE 0x0
+
+/* state definition for Scratch Pad1 register */
+#define SCRATCH_PAD_RAAE_READY 0x3
+#define SCRATCH_PAD_ILA_READY 0xC
+#define SCRATCH_PAD_BOOT_LOAD_SUCCESS 0x0
+#define SCRATCH_PAD_IOP0_READY 0xC00
+#define SCRATCH_PAD_IOP1_READY 0x3000
+
+/* boot loader state */
+#define SCRATCH_PAD1_BOOTSTATE_MASK 0x70 /* Bit 4-6 */
+#define SCRATCH_PAD1_BOOTSTATE_SUCESS 0x0 /* Load successful */
+#define SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM 0x10 /* HDA SEEPROM */
+#define SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP 0x20 /* HDA BootStrap Pins */
+#define SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET 0x30 /* HDA Soft Reset */
+#define SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR 0x40 /* HDA critical error */
+#define SCRATCH_PAD1_BOOTSTATE_R1 0x50 /* Reserved */
+#define SCRATCH_PAD1_BOOTSTATE_R2 0x60 /* Reserved */
+#define SCRATCH_PAD1_BOOTSTATE_FATAL 0x70 /* Fatal Error */
+
+ /* state definition for Scratch Pad2 register */
+#define SCRATCH_PAD2_POR 0x00 /* power on state */
+#define SCRATCH_PAD2_SFR 0x01 /* soft reset state */
+#define SCRATCH_PAD2_ERR 0x02 /* error state */
+#define SCRATCH_PAD2_RDY 0x03 /* ready state */
+#define SCRATCH_PAD2_FWRDY_RST 0x04 /* FW rdy for soft reset flag */
+#define SCRATCH_PAD2_IOPRDY_RST 0x08 /* IOP ready for soft reset */
+#define SCRATCH_PAD2_STATE_MASK 0xFFFFFFF4 /* ScratchPad 2
+ Mask, bit1-0 State */
+#define SCRATCH_PAD2_RESERVED 0x000003FC/* Scratch Pad1
+ Reserved bit 2 to 9 */
+
+#define SCRATCH_PAD_ERROR_MASK 0xFFFFFC00 /* Error mask bits */
+#define SCRATCH_PAD_STATE_MASK 0x00000003 /* State Mask bits */
+
+/* main configuration offset - byte offset */
+#define MAIN_SIGNATURE_OFFSET 0x00 /* DWORD 0x00 */
+#define MAIN_INTERFACE_REVISION 0x04 /* DWORD 0x01 */
+#define MAIN_FW_REVISION 0x08 /* DWORD 0x02 */
+#define MAIN_MAX_OUTSTANDING_IO_OFFSET 0x0C /* DWORD 0x03 */
+#define MAIN_MAX_SGL_OFFSET 0x10 /* DWORD 0x04 */
+#define MAIN_CNTRL_CAP_OFFSET 0x14 /* DWORD 0x05 */
+#define MAIN_GST_OFFSET 0x18 /* DWORD 0x06 */
+#define MAIN_IBQ_OFFSET 0x1C /* DWORD 0x07 */
+#define MAIN_OBQ_OFFSET 0x20 /* DWORD 0x08 */
+#define MAIN_IQNPPD_HPPD_OFFSET 0x24 /* DWORD 0x09 */
+
+/* 0x28 - 0x4C - RSVD */
+#define MAIN_EVENT_CRC_CHECK 0x48 /* DWORD 0x12 */
+#define MAIN_EVENT_LOG_ADDR_HI 0x50 /* DWORD 0x14 */
+#define MAIN_EVENT_LOG_ADDR_LO 0x54 /* DWORD 0x15 */
+#define MAIN_EVENT_LOG_BUFF_SIZE 0x58 /* DWORD 0x16 */
+#define MAIN_EVENT_LOG_OPTION 0x5C /* DWORD 0x17 */
+#define MAIN_PCS_EVENT_LOG_ADDR_HI 0x60 /* DWORD 0x18 */
+#define MAIN_PCS_EVENT_LOG_ADDR_LO 0x64 /* DWORD 0x19 */
+#define MAIN_PCS_EVENT_LOG_BUFF_SIZE 0x68 /* DWORD 0x1A */
+#define MAIN_PCS_EVENT_LOG_OPTION 0x6C /* DWORD 0x1B */
+#define MAIN_FATAL_ERROR_INTERRUPT 0x70 /* DWORD 0x1C */
+#define MAIN_FATAL_ERROR_RDUMP0_OFFSET 0x74 /* DWORD 0x1D */
+#define MAIN_FATAL_ERROR_RDUMP0_LENGTH 0x78 /* DWORD 0x1E */
+#define MAIN_FATAL_ERROR_RDUMP1_OFFSET 0x7C /* DWORD 0x1F */
+#define MAIN_FATAL_ERROR_RDUMP1_LENGTH 0x80 /* DWORD 0x20 */
+#define MAIN_GPIO_LED_FLAGS_OFFSET 0x84 /* DWORD 0x21 */
+#define MAIN_ANALOG_SETUP_OFFSET 0x88 /* DWORD 0x22 */
+
+#define MAIN_INT_VECTOR_TABLE_OFFSET 0x8C /* DWORD 0x23 */
+#define MAIN_SAS_PHY_ATTR_TABLE_OFFSET 0x90 /* DWORD 0x24 */
+#define MAIN_PORT_RECOVERY_TIMER 0x94 /* DWORD 0x25 */
+#define MAIN_INT_REASSERTION_DELAY 0x98 /* DWORD 0x26 */
+
+/* Gereral Status Table offset - byte offset */
+#define GST_GSTLEN_MPIS_OFFSET 0x00
+#define GST_IQ_FREEZE_STATE0_OFFSET 0x04
+#define GST_IQ_FREEZE_STATE1_OFFSET 0x08
+#define GST_MSGUTCNT_OFFSET 0x0C
+#define GST_IOPTCNT_OFFSET 0x10
+/* 0x14 - 0x34 - RSVD */
+#define GST_GPIO_INPUT_VAL 0x38
+/* 0x3c - 0x40 - RSVD */
+#define GST_RERRINFO_OFFSET0 0x44
+#define GST_RERRINFO_OFFSET1 0x48
+#define GST_RERRINFO_OFFSET2 0x4c
+#define GST_RERRINFO_OFFSET3 0x50
+#define GST_RERRINFO_OFFSET4 0x54
+#define GST_RERRINFO_OFFSET5 0x58
+#define GST_RERRINFO_OFFSET6 0x5c
+#define GST_RERRINFO_OFFSET7 0x60
+
+/* General Status Table - MPI state */
+#define GST_MPI_STATE_UNINIT 0x00
+#define GST_MPI_STATE_INIT 0x01
+#define GST_MPI_STATE_TERMINATION 0x02
+#define GST_MPI_STATE_ERROR 0x03
+#define GST_MPI_STATE_MASK 0x07
+
+/* Per SAS PHY Attributes */
+
+#define PSPA_PHYSTATE0_OFFSET 0x00 /* Dword V */
+#define PSPA_OB_HW_EVENT_PID0_OFFSET 0x04 /* DWORD V+1 */
+#define PSPA_PHYSTATE1_OFFSET 0x08 /* Dword V+2 */
+#define PSPA_OB_HW_EVENT_PID1_OFFSET 0x0C /* DWORD V+3 */
+#define PSPA_PHYSTATE2_OFFSET 0x10 /* Dword V+4 */
+#define PSPA_OB_HW_EVENT_PID2_OFFSET 0x14 /* DWORD V+5 */
+#define PSPA_PHYSTATE3_OFFSET 0x18 /* Dword V+6 */
+#define PSPA_OB_HW_EVENT_PID3_OFFSET 0x1C /* DWORD V+7 */
+#define PSPA_PHYSTATE4_OFFSET 0x20 /* Dword V+8 */
+#define PSPA_OB_HW_EVENT_PID4_OFFSET 0x24 /* DWORD V+9 */
+#define PSPA_PHYSTATE5_OFFSET 0x28 /* Dword V+10 */
+#define PSPA_OB_HW_EVENT_PID5_OFFSET 0x2C /* DWORD V+11 */
+#define PSPA_PHYSTATE6_OFFSET 0x30 /* Dword V+12 */
+#define PSPA_OB_HW_EVENT_PID6_OFFSET 0x34 /* DWORD V+13 */
+#define PSPA_PHYSTATE7_OFFSET 0x38 /* Dword V+14 */
+#define PSPA_OB_HW_EVENT_PID7_OFFSET 0x3C /* DWORD V+15 */
+#define PSPA_PHYSTATE8_OFFSET 0x40 /* DWORD V+16 */
+#define PSPA_OB_HW_EVENT_PID8_OFFSET 0x44 /* DWORD V+17 */
+#define PSPA_PHYSTATE9_OFFSET 0x48 /* DWORD V+18 */
+#define PSPA_OB_HW_EVENT_PID9_OFFSET 0x4C /* DWORD V+19 */
+#define PSPA_PHYSTATE10_OFFSET 0x50 /* DWORD V+20 */
+#define PSPA_OB_HW_EVENT_PID10_OFFSET 0x54 /* DWORD V+21 */
+#define PSPA_PHYSTATE11_OFFSET 0x58 /* DWORD V+22 */
+#define PSPA_OB_HW_EVENT_PID11_OFFSET 0x5C /* DWORD V+23 */
+#define PSPA_PHYSTATE12_OFFSET 0x60 /* DWORD V+24 */
+#define PSPA_OB_HW_EVENT_PID12_OFFSET 0x64 /* DWORD V+25 */
+#define PSPA_PHYSTATE13_OFFSET 0x68 /* DWORD V+26 */
+#define PSPA_OB_HW_EVENT_PID13_OFFSET 0x6c /* DWORD V+27 */
+#define PSPA_PHYSTATE14_OFFSET 0x70 /* DWORD V+28 */
+#define PSPA_OB_HW_EVENT_PID14_OFFSET 0x74 /* DWORD V+29 */
+#define PSPA_PHYSTATE15_OFFSET 0x78 /* DWORD V+30 */
+#define PSPA_OB_HW_EVENT_PID15_OFFSET 0x7c /* DWORD V+31 */
+/* end PSPA */
+
+/* inbound queue configuration offset - byte offset */
+#define IB_PROPERITY_OFFSET 0x00
+#define IB_BASE_ADDR_HI_OFFSET 0x04
+#define IB_BASE_ADDR_LO_OFFSET 0x08
+#define IB_CI_BASE_ADDR_HI_OFFSET 0x0C
+#define IB_CI_BASE_ADDR_LO_OFFSET 0x10
+#define IB_PIPCI_BAR 0x14
+#define IB_PIPCI_BAR_OFFSET 0x18
+#define IB_RESERVED_OFFSET 0x1C
+
+/* outbound queue configuration offset - byte offset */
+#define OB_PROPERITY_OFFSET 0x00
+#define OB_BASE_ADDR_HI_OFFSET 0x04
+#define OB_BASE_ADDR_LO_OFFSET 0x08
+#define OB_PI_BASE_ADDR_HI_OFFSET 0x0C
+#define OB_PI_BASE_ADDR_LO_OFFSET 0x10
+#define OB_CIPCI_BAR 0x14
+#define OB_CIPCI_BAR_OFFSET 0x18
+#define OB_INTERRUPT_COALES_OFFSET 0x1C
+#define OB_DYNAMIC_COALES_OFFSET 0x20
+#define OB_PROPERTY_INT_ENABLE 0x40000000
+
+#define MBIC_NMI_ENABLE_VPE0_IOP 0x000418
+#define MBIC_NMI_ENABLE_VPE0_AAP1 0x000418
+/* PCIE registers - BAR2(0x18), BAR1(win) 0x010000 */
+#define PCIE_EVENT_INTERRUPT_ENABLE 0x003040
+#define PCIE_EVENT_INTERRUPT 0x003044
+#define PCIE_ERROR_INTERRUPT_ENABLE 0x003048
+#define PCIE_ERROR_INTERRUPT 0x00304C
+
+/* SPCV soft reset */
+#define SPC_REG_SOFT_RESET 0x00001000
+#define SPCv_NORMAL_RESET_VALUE 0x1
+
+#define SPCv_SOFT_RESET_READ_MASK 0xC0
+#define SPCv_SOFT_RESET_NO_RESET 0x0
+#define SPCv_SOFT_RESET_NORMAL_RESET_OCCURED 0x40
+#define SPCv_SOFT_RESET_HDA_MODE_OCCURED 0x80
+#define SPCv_SOFT_RESET_CHIP_RESET_OCCURED 0xC0
+
+/* signature definition for host scratch pad0 register */
+#define SPC_SOFT_RESET_SIGNATURE 0x252acbcd
+/* Signature for Soft Reset */
+
+/* SPC Reset register - BAR4(0x20), BAR2(win) (need dynamic mapping) */
+#define SPC_REG_RESET 0x000000/* reset register */
+
+/* bit definition for SPC_RESET register */
+#define SPC_REG_RESET_OSSP 0x00000001
+#define SPC_REG_RESET_RAAE 0x00000002
+#define SPC_REG_RESET_PCS_SPBC 0x00000004
+#define SPC_REG_RESET_PCS_IOP_SS 0x00000008
+#define SPC_REG_RESET_PCS_AAP1_SS 0x00000010
+#define SPC_REG_RESET_PCS_AAP2_SS 0x00000020
+#define SPC_REG_RESET_PCS_LM 0x00000040
+#define SPC_REG_RESET_PCS 0x00000080
+#define SPC_REG_RESET_GSM 0x00000100
+#define SPC_REG_RESET_DDR2 0x00010000
+#define SPC_REG_RESET_BDMA_CORE 0x00020000
+#define SPC_REG_RESET_BDMA_SXCBI 0x00040000
+#define SPC_REG_RESET_PCIE_AL_SXCBI 0x00080000
+#define SPC_REG_RESET_PCIE_PWR 0x00100000
+#define SPC_REG_RESET_PCIE_SFT 0x00200000
+#define SPC_REG_RESET_PCS_SXCBI 0x00400000
+#define SPC_REG_RESET_LMS_SXCBI 0x00800000
+#define SPC_REG_RESET_PMIC_SXCBI 0x01000000
+#define SPC_REG_RESET_PMIC_CORE 0x02000000
+#define SPC_REG_RESET_PCIE_PC_SXCBI 0x04000000
+#define SPC_REG_RESET_DEVICE 0x80000000
+
+/* registers for BAR Shifting - BAR2(0x18), BAR1(win) */
+#define SPCV_IBW_AXI_TRANSLATION_LOW 0x001010
+
+#define MBIC_AAP1_ADDR_BASE 0x060000
+#define MBIC_IOP_ADDR_BASE 0x070000
+#define GSM_ADDR_BASE 0x0700000
+/* Dynamic map through Bar4 - 0x00700000 */
+#define GSM_CONFIG_RESET 0x00000000
+#define RAM_ECC_DB_ERR 0x00000018
+#define GSM_READ_ADDR_PARITY_INDIC 0x00000058
+#define GSM_WRITE_ADDR_PARITY_INDIC 0x00000060
+#define GSM_WRITE_DATA_PARITY_INDIC 0x00000068
+#define GSM_READ_ADDR_PARITY_CHECK 0x00000038
+#define GSM_WRITE_ADDR_PARITY_CHECK 0x00000040
+#define GSM_WRITE_DATA_PARITY_CHECK 0x00000048
+
+#define RB6_ACCESS_REG 0x6A0000
+#define HDAC_EXEC_CMD 0x0002
+#define HDA_C_PA 0xcb
+#define HDA_SEQ_ID_BITS 0x00ff0000
+#define HDA_GSM_OFFSET_BITS 0x00FFFFFF
+#define HDA_GSM_CMD_OFFSET_BITS 0x42C0
+#define HDA_GSM_RSP_OFFSET_BITS 0x42E0
+
+#define MBIC_AAP1_ADDR_BASE 0x060000
+#define MBIC_IOP_ADDR_BASE 0x070000
+#define GSM_ADDR_BASE 0x0700000
+#define SPC_TOP_LEVEL_ADDR_BASE 0x000000
+#define GSM_CONFIG_RESET_VALUE 0x00003b00
+#define GPIO_ADDR_BASE 0x00090000
+#define GPIO_GPIO_0_0UTPUT_CTL_OFFSET 0x0000010c
+
+/* RB6 offset */
+#define SPC_RB6_OFFSET 0x80C0
+/* Magic number of soft reset for RB6 */
+#define RB6_MAGIC_NUMBER_RST 0x1234
+
+/* Device Register status */
+#define DEVREG_SUCCESS 0x00
+#define DEVREG_FAILURE_OUT_OF_RESOURCE 0x01
+#define DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED 0x02
+#define DEVREG_FAILURE_INVALID_PHY_ID 0x03
+#define DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED 0x04
+#define DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE 0x05
+#define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06
+#define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07
+
+#endif
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index af763ea..1eb7b028 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -125,7 +125,7 @@ static struct pmcraid_chip_details pmcraid_chip_cfg[] = {
/*
* PCI device ids supported by pmcraid driver
*/
-static struct pci_device_id pmcraid_pci_table[] __devinitdata = {
+static struct pci_device_id pmcraid_pci_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_PMC, PCI_DEVICE_ID_PMC_MAXRAID),
0, 0, (kernel_ulong_t)&pmcraid_chip_cfg[0]
},
@@ -3599,19 +3599,6 @@ static int pmcraid_chr_open(struct inode *inode, struct file *filep)
}
/**
- * pmcraid_release - char node "release" entry point
- */
-static int pmcraid_chr_release(struct inode *inode, struct file *filep)
-{
- struct pmcraid_instance *pinstance = filep->private_data;
-
- filep->private_data = NULL;
- fasync_helper(-1, filep, 0, &pinstance->aen_queue);
-
- return 0;
-}
-
-/**
* pmcraid_fasync - Async notifier registration from applications
*
* This function adds the calling process to a driver global queue. When an
@@ -4167,7 +4154,6 @@ static long pmcraid_chr_ioctl(
static const struct file_operations pmcraid_fops = {
.owner = THIS_MODULE,
.open = pmcraid_chr_open,
- .release = pmcraid_chr_release,
.fasync = pmcraid_chr_fasync,
.unlocked_ioctl = pmcraid_chr_ioctl,
#ifdef CONFIG_COMPAT
@@ -4818,8 +4804,7 @@ pmcraid_release_control_blocks(
* Return Value
* 0 in case of success; -ENOMEM in case of failure
*/
-static int __devinit
-pmcraid_allocate_cmd_blocks(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_cmd_blocks(struct pmcraid_instance *pinstance)
{
int i;
@@ -4855,8 +4840,7 @@ pmcraid_allocate_cmd_blocks(struct pmcraid_instance *pinstance)
* Return Value
* 0 in case it can allocate all control blocks, otherwise -ENOMEM
*/
-static int __devinit
-pmcraid_allocate_control_blocks(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_control_blocks(struct pmcraid_instance *pinstance)
{
int i;
@@ -4922,8 +4906,7 @@ pmcraid_release_host_rrqs(struct pmcraid_instance *pinstance, int maxindex)
* Return value
* 0 hrrq buffers are allocated, -ENOMEM otherwise.
*/
-static int __devinit
-pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance)
{
int i, buffer_size;
@@ -5062,8 +5045,7 @@ static void pmcraid_release_config_buffers(struct pmcraid_instance *pinstance)
* Return Value
* 0 for successful allocation, -ENOMEM for any failure
*/
-static int __devinit
-pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance)
{
int i;
@@ -5181,7 +5163,7 @@ static void pmcraid_release_buffers(struct pmcraid_instance *pinstance)
* Return Value
* 0 in case all of the blocks are allocated, -ENOMEM otherwise.
*/
-static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance)
+static int pmcraid_init_buffers(struct pmcraid_instance *pinstance)
{
int i;
@@ -5281,11 +5263,8 @@ static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance)
* Return Value
* 0 on success, non-zero in case of any failure
*/
-static int __devinit pmcraid_init_instance(
- struct pci_dev *pdev,
- struct Scsi_Host *host,
- void __iomem *mapped_pci_addr
-)
+static int pmcraid_init_instance(struct pci_dev *pdev, struct Scsi_Host *host,
+ void __iomem *mapped_pci_addr)
{
struct pmcraid_instance *pinstance =
(struct pmcraid_instance *)host->hostdata;
@@ -5442,7 +5421,7 @@ static void pmcraid_release_chrdev(struct pmcraid_instance *pinstance)
* Return value
* none
*/
-static void __devexit pmcraid_remove(struct pci_dev *pdev)
+static void pmcraid_remove(struct pci_dev *pdev)
{
struct pmcraid_instance *pinstance = pci_get_drvdata(pdev);
@@ -5883,10 +5862,8 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd)
* returns 0 if the device is claimed and successfully configured.
* returns non-zero error code in case of any failure
*/
-static int __devinit pmcraid_probe(
- struct pci_dev *pdev,
- const struct pci_device_id *dev_id
-)
+static int pmcraid_probe(struct pci_dev *pdev,
+ const struct pci_device_id *dev_id)
{
struct pmcraid_instance *pinstance;
struct Scsi_Host *host;
@@ -6115,7 +6092,7 @@ static int __init pmcraid_init(void)
if (IS_ERR(pmcraid_class)) {
error = PTR_ERR(pmcraid_class);
- pmcraid_err("failed to register with with sysfs, error = %x\n",
+ pmcraid_err("failed to register with sysfs, error = %x\n",
error);
goto out_unreg_chrdev;
}
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index d164c96..1db8b26 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -118,8 +118,9 @@ static inline void ppa_pb_release(ppa_struct *dev)
* Also gives a method to use a script to obtain optimum timings (TODO)
*/
-static inline int ppa_proc_write(ppa_struct *dev, char *buffer, int length)
+static inline int ppa_write_info(struct Scsi_Host *host, char *buffer, int length)
{
+ ppa_struct *dev = ppa_dev(host);
unsigned long x;
if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
@@ -137,35 +138,17 @@ static inline int ppa_proc_write(ppa_struct *dev, char *buffer, int length)
return -EINVAL;
}
-static int ppa_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
+static int ppa_show_info(struct seq_file *m, struct Scsi_Host *host)
{
- int len = 0;
ppa_struct *dev = ppa_dev(host);
- if (inout)
- return ppa_proc_write(dev, buffer, length);
-
- len += sprintf(buffer + len, "Version : %s\n", PPA_VERSION);
- len +=
- sprintf(buffer + len, "Parport : %s\n",
- dev->dev->port->name);
- len +=
- sprintf(buffer + len, "Mode : %s\n",
- PPA_MODE_STRING[dev->mode]);
+ seq_printf(m, "Version : %s\n", PPA_VERSION);
+ seq_printf(m, "Parport : %s\n", dev->dev->port->name);
+ seq_printf(m, "Mode : %s\n", PPA_MODE_STRING[dev->mode]);
#if PPA_DEBUG > 0
- len +=
- sprintf(buffer + len, "recon_tmo : %lu\n", dev->recon_tmo);
+ seq_printf(m, "recon_tmo : %lu\n", dev->recon_tmo);
#endif
-
- /* Request for beyond end of buffer */
- if (offset > length)
- return 0;
-
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- return len;
+ return 0;
}
static int device_check(ppa_struct *dev);
@@ -981,7 +964,8 @@ static int ppa_adjust_queue(struct scsi_device *device)
static struct scsi_host_template ppa_template = {
.module = THIS_MODULE,
.proc_name = "ppa",
- .proc_info = ppa_proc_info,
+ .show_info = ppa_show_info,
+ .write_info = ppa_write_info,
.name = "Iomega VPI0 (ppa) interface",
.queuecommand = ppa_queuecommand,
.eh_abort_handler = ppa_abort,
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 959f100..e6e2a30 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -359,7 +359,7 @@ static struct scsi_host_template ps3rom_host_template = {
};
-static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
+static int ps3rom_probe(struct ps3_system_bus_device *_dev)
{
struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
int error;
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 538230b..5a522c5 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1438,7 +1438,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
* Returns:
* 0 = success
*/
-static int __devinit
+static int
qla1280_initialize_adapter(struct scsi_qla_host *ha)
{
struct device_reg __iomem *reg;
@@ -4230,7 +4230,7 @@ static struct scsi_host_template qla1280_driver_template = {
};
-static int __devinit
+static int
qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
int devnum = id->driver_data;
@@ -4399,7 +4399,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
-static void __devexit
+static void
qla1280_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *host = pci_get_drvdata(pdev);
@@ -4433,7 +4433,7 @@ static struct pci_driver qla1280_pci_driver = {
.name = "qla1280",
.id_table = qla1280_pci_tbl,
.probe = qla1280_probe_one,
- .remove = __devexit_p(qla1280_remove_one),
+ .remove = qla1280_remove_one,
};
static int __init
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 317a7fd..23d6072 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -24,7 +24,9 @@ config SCSI_QLA_FC
Firmware images can be retrieved from:
- ftp://ftp.qlogic.com/outgoing/linux/firmware/
+ http://ldriver.qlogic.com/firmware/
+
+ They are also included in the linux-firmware tree as well.
config TCM_QLA2XXX
tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs"
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index dce7d78..c37b244 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,6 +1,6 @@
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \
- qla_nx.o qla_target.o
+ qla_nx.o qla_mr.o qla_target.o
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 83d7984..d7a99ae 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -888,7 +888,10 @@ qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
struct qla_hw_data *ha = vha->hw;
uint32_t sn;
- if (IS_FWI2_CAPABLE(ha)) {
+ if (IS_QLAFX00(vha->hw)) {
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ vha->hw->mr.serial_num);
+ } else if (IS_FWI2_CAPABLE(ha)) {
qla2xxx_get_vpd_field(vha, "SN", buf, PAGE_SIZE);
return snprintf(buf, PAGE_SIZE, "%s\n", buf);
}
@@ -912,6 +915,11 @@ qla2x00_isp_id_show(struct device *dev, struct device_attribute *attr,
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
+
+ if (IS_QLAFX00(vha->hw))
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ vha->hw->mr.hw_version);
+
return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
ha->product_id[0], ha->product_id[1], ha->product_id[2],
ha->product_id[3]);
@@ -922,6 +930,11 @@ qla2x00_model_name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
+ if (IS_QLAFX00(vha->hw))
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ vha->hw->mr.product_name);
+
return snprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_number);
}
@@ -1272,22 +1285,29 @@ qla2x00_thermal_temp_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
- int rval = QLA_FUNCTION_FAILED;
- uint16_t temp, frac;
+ uint16_t temp = 0;
- if (!vha->hw->flags.thermal_supported)
- return snprintf(buf, PAGE_SIZE, "\n");
+ if (!vha->hw->thermal_support) {
+ ql_log(ql_log_warn, vha, 0x70db,
+ "Thermal not supported by this card.\n");
+ goto done;
+ }
- temp = frac = 0;
- if (qla2x00_reset_active(vha))
- ql_log(ql_log_warn, vha, 0x707b,
- "ISP reset active.\n");
- else if (!vha->hw->flags.eeh_busy)
- rval = qla2x00_get_thermal_temp(vha, &temp, &frac);
- if (rval != QLA_SUCCESS)
- return snprintf(buf, PAGE_SIZE, "\n");
+ if (qla2x00_reset_active(vha)) {
+ ql_log(ql_log_warn, vha, 0x70dc, "ISP reset active.\n");
+ goto done;
+ }
+
+ if (vha->hw->flags.eeh_busy) {
+ ql_log(ql_log_warn, vha, 0x70dd, "PCI EEH busy.\n");
+ goto done;
+ }
- return snprintf(buf, PAGE_SIZE, "%d.%02d\n", temp, frac);
+ if (qla2x00_get_thermal_temp(vha, &temp) == QLA_SUCCESS)
+ return snprintf(buf, PAGE_SIZE, "%d\n", temp);
+
+done:
+ return snprintf(buf, PAGE_SIZE, "\n");
}
static ssize_t
@@ -1297,6 +1317,12 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int rval = QLA_FUNCTION_FAILED;
uint16_t state[5];
+ uint32_t pstate;
+
+ if (IS_QLAFX00(vha->hw)) {
+ pstate = qlafx00_fw_state_show(dev, attr, buf);
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", pstate);
+ }
if (qla2x00_reset_active(vha))
ql_log(ql_log_warn, vha, 0x707c,
@@ -1447,6 +1473,11 @@ qla2x00_get_host_speed(struct Scsi_Host *shost)
(shost_priv(shost)))->hw;
u32 speed = FC_PORTSPEED_UNKNOWN;
+ if (IS_QLAFX00(ha)) {
+ qlafx00_get_host_speed(shost);
+ return;
+ }
+
switch (ha->link_data_rate) {
case PORT_SPEED_1GB:
speed = FC_PORTSPEED_1GBIT;
@@ -1630,6 +1661,9 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
{
scsi_qla_host_t *vha = shost_priv(shost);
+ if (IS_QLAFX00(vha->hw))
+ return 0;
+
qla2x00_loop_reset(vha);
return 0;
}
@@ -1648,12 +1682,18 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
pfc_host_stat = &vha->fc_host_stat;
memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
+ if (IS_QLAFX00(vha->hw))
+ goto done;
+
if (test_bit(UNLOADING, &vha->dpc_flags))
goto done;
if (unlikely(pci_channel_offline(ha->pdev)))
goto done;
+ if (qla2x00_reset_active(vha))
+ goto done;
+
stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
if (stats == NULL) {
ql_log(ql_log_warn, vha, 0x707d,
@@ -1666,7 +1706,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
if (IS_FWI2_CAPABLE(ha)) {
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
} else if (atomic_read(&base_vha->loop_state) == LOOP_READY &&
- !qla2x00_reset_active(vha) && !ha->dpc_active) {
+ !ha->dpc_active) {
/* Must be in a 'READY' state for statistics retrieval. */
rval = qla2x00_get_link_status(base_vha, base_vha->loop_id,
stats, stats_dma);
@@ -1931,11 +1971,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
"Timer for the VP[%d] has stopped\n", vha->vp_idx);
}
- /* No pending activities shall be there on the vha now */
- if (ql2xextended_error_logging & ql_dbg_user)
- msleep(random32()%10); /* Just to see if something falls on
- * the net we have placed below */
-
BUG_ON(atomic_read(&vha->vref_count));
qla2x00_free_fcports(vha);
@@ -2085,6 +2120,9 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
FC_PORTSPEED_1GBIT;
else if (IS_QLA23XX(ha))
speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+ else if (IS_QLAFX00(ha))
+ speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
+ FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
else
speed = FC_PORTSPEED_1GBIT;
fc_host_supported_speeds(vha->host) = speed;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 9f34ded..417eaad 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -27,20 +27,37 @@ void
qla2x00_bsg_sp_free(void *data, void *ptr)
{
srb_t *sp = (srb_t *)ptr;
- struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
+ struct scsi_qla_host *vha = sp->fcport->vha;
struct fc_bsg_job *bsg_job = sp->u.bsg_job;
struct qla_hw_data *ha = vha->hw;
+ struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
- dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
- bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+ if (sp->type == SRB_FXIOCB_BCMD) {
+ piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
+ &bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
- dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
- bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
+ dma_unmap_sg(&ha->pdev->dev,
+ bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+
+ if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
+ dma_unmap_sg(&ha->pdev->dev,
+ bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ } else {
+ dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+
+ dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ }
if (sp->type == SRB_CT_CMD ||
+ sp->type == SRB_FXIOCB_BCMD ||
sp->type == SRB_ELS_CMD_HST)
kfree(sp->fcport);
- mempool_free(sp, vha->hw->srb_mempool);
+ qla2x00_rel_sp(vha, sp);
}
int
@@ -252,6 +269,12 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
type = "FC_BSG_HST_ELS_NOLOGIN";
}
+ if (!vha->flags.online) {
+ ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
+ rval = -EIO;
+ goto done;
+ }
+
/* pass through is supported only for ISP 4Gb or higher */
if (!IS_FWI2_CAPABLE(ha)) {
ql_dbg(ql_dbg_user, vha, 0x7001,
@@ -309,12 +332,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
NPH_FABRIC_CONTROLLER : NPH_F_PORT;
}
- if (!vha->flags.online) {
- ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
- rval = -EIO;
- goto done;
- }
-
req_sg_cnt =
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -368,7 +385,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x700e,
"qla2x00_start_sp failed = %d\n", rval);
- mempool_free(sp, ha->srb_mempool);
+ qla2x00_rel_sp(vha, sp);
rval = -EIO;
goto done_unmap_sg;
}
@@ -382,7 +399,7 @@ done_unmap_sg:
goto done_free_fcport;
done_free_fcport:
- if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
+ if (bsg_job->request->msgcode == FC_BSG_RPT_ELS)
kfree(fcport);
done:
return rval;
@@ -515,7 +532,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7017,
"qla2x00_start_sp failed=%d.\n", rval);
- mempool_free(sp, ha->srb_mempool);
+ qla2x00_rel_sp(vha, sp);
rval = -EIO;
goto done_free_fcport;
}
@@ -531,6 +548,75 @@ done_unmap_sg:
done:
return rval;
}
+
+/* Disable loopback mode */
+static inline int
+qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
+ int wait, int wait2)
+{
+ int ret = 0;
+ int rval = 0;
+ uint16_t new_config[4];
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
+ goto done_reset_internal;
+
+ memset(new_config, 0 , sizeof(new_config));
+ if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
+ ENABLE_INTERNAL_LOOPBACK ||
+ (config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
+ ENABLE_EXTERNAL_LOOPBACK) {
+ new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
+ ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
+ (new_config[0] & INTERNAL_LOOPBACK_MASK));
+ memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
+
+ ha->notify_dcbx_comp = wait;
+ ha->notify_lb_portup_comp = wait2;
+
+ ret = qla81xx_set_port_config(vha, new_config);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x7025,
+ "Set port config failed.\n");
+ ha->notify_dcbx_comp = 0;
+ ha->notify_lb_portup_comp = 0;
+ rval = -EINVAL;
+ goto done_reset_internal;
+ }
+
+ /* Wait for DCBX complete event */
+ if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
+ (DCBX_COMP_TIMEOUT * HZ))) {
+ ql_dbg(ql_dbg_user, vha, 0x7026,
+ "DCBX completion not received.\n");
+ ha->notify_dcbx_comp = 0;
+ ha->notify_lb_portup_comp = 0;
+ rval = -EINVAL;
+ goto done_reset_internal;
+ } else
+ ql_dbg(ql_dbg_user, vha, 0x7027,
+ "DCBX completion received.\n");
+
+ if (wait2 &&
+ !wait_for_completion_timeout(&ha->lb_portup_comp,
+ (LB_PORTUP_COMP_TIMEOUT * HZ))) {
+ ql_dbg(ql_dbg_user, vha, 0x70c5,
+ "Port up completion not received.\n");
+ ha->notify_lb_portup_comp = 0;
+ rval = -EINVAL;
+ goto done_reset_internal;
+ } else
+ ql_dbg(ql_dbg_user, vha, 0x70c6,
+ "Port up completion received.\n");
+
+ ha->notify_dcbx_comp = 0;
+ ha->notify_lb_portup_comp = 0;
+ }
+done_reset_internal:
+ return rval;
+}
+
/*
* Set the port configuration to enable the internal or external loopback
* depending on the loopback mode.
@@ -566,9 +652,19 @@ qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
}
/* Wait for DCBX complete event */
- if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
+ if (!wait_for_completion_timeout(&ha->dcbx_comp,
+ (DCBX_COMP_TIMEOUT * HZ))) {
ql_dbg(ql_dbg_user, vha, 0x7022,
- "State change notification not received.\n");
+ "DCBX completion not received.\n");
+ ret = qla81xx_reset_loopback_mode(vha, new_config, 0, 0);
+ /*
+ * If the reset of the loopback mode doesn't work take a FCoE
+ * dump and reset the chip.
+ */
+ if (ret) {
+ ha->isp_ops->fw_dump(vha, 0);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ }
rval = -EINVAL;
} else {
if (ha->flags.idc_compl_status) {
@@ -578,7 +674,7 @@ qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
ha->flags.idc_compl_status = 0;
} else
ql_dbg(ql_dbg_user, vha, 0x7023,
- "State change received.\n");
+ "DCBX completion received.\n");
}
ha->notify_dcbx_comp = 0;
@@ -587,57 +683,6 @@ done_set_internal:
return rval;
}
-/* Disable loopback mode */
-static inline int
-qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
- int wait)
-{
- int ret = 0;
- int rval = 0;
- uint16_t new_config[4];
- struct qla_hw_data *ha = vha->hw;
-
- if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
- goto done_reset_internal;
-
- memset(new_config, 0 , sizeof(new_config));
- if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
- ENABLE_INTERNAL_LOOPBACK ||
- (config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
- ENABLE_EXTERNAL_LOOPBACK) {
- new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
- ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
- (new_config[0] & INTERNAL_LOOPBACK_MASK));
- memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
-
- ha->notify_dcbx_comp = wait;
- ret = qla81xx_set_port_config(vha, new_config);
- if (ret != QLA_SUCCESS) {
- ql_log(ql_log_warn, vha, 0x7025,
- "Set port config failed.\n");
- ha->notify_dcbx_comp = 0;
- rval = -EINVAL;
- goto done_reset_internal;
- }
-
- /* Wait for DCBX complete event */
- if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
- (20 * HZ))) {
- ql_dbg(ql_dbg_user, vha, 0x7026,
- "State change notification not received.\n");
- ha->notify_dcbx_comp = 0;
- rval = -EINVAL;
- goto done_reset_internal;
- } else
- ql_dbg(ql_dbg_user, vha, 0x7027,
- "State change received.\n");
-
- ha->notify_dcbx_comp = 0;
- }
-done_reset_internal:
- return rval;
-}
-
static int
qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
{
@@ -723,6 +768,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
elreq.transfer_size = req_data_len;
elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+ elreq.iteration_count =
+ bsg_job->request->rqst_data.h_vendor.vendor_cmd[2];
if (atomic_read(&vha->loop_state) == LOOP_READY &&
(ha->current_topology == ISP_CFG_F ||
@@ -739,6 +786,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
if (IS_QLA81XX(ha) || IS_QLA8031(ha)) {
memset(config, 0, sizeof(config));
memset(new_config, 0, sizeof(new_config));
+
if (qla81xx_get_port_config(vha, config)) {
ql_log(ql_log_warn, vha, 0x701f,
"Get port config failed.\n");
@@ -746,6 +794,14 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
goto done_free_dma_rsp;
}
+ if ((config[0] & INTERNAL_LOOPBACK_MASK) != 0) {
+ ql_dbg(ql_dbg_user, vha, 0x70c4,
+ "Loopback operation already in "
+ "progress.\n");
+ rval = -EAGAIN;
+ goto done_free_dma_rsp;
+ }
+
ql_dbg(ql_dbg_user, vha, 0x70c0,
"elreq.options=%04x\n", elreq.options);
@@ -755,7 +811,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
config, new_config, elreq.options);
else
rval = qla81xx_reset_loopback_mode(vha,
- config, 1);
+ config, 1, 0);
else
rval = qla81xx_set_loopback_mode(vha, config,
new_config, elreq.options);
@@ -772,14 +828,6 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
command_sent = INT_DEF_LB_LOOPBACK_CMD;
rval = qla2x00_loopback_test(vha, &elreq, response);
- if (new_config[0]) {
- /* Revert back to original port config
- * Also clear internal loopback
- */
- qla81xx_reset_loopback_mode(vha,
- new_config, 0);
- }
-
if (response[0] == MBS_COMMAND_ERROR &&
response[1] == MBS_LB_RESET) {
ql_log(ql_log_warn, vha, 0x7029,
@@ -788,15 +836,39 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
/* Also reset the MPI */
- if (qla81xx_restart_mpi_firmware(vha) !=
- QLA_SUCCESS) {
- ql_log(ql_log_warn, vha, 0x702a,
- "MPI reset failed.\n");
+ if (IS_QLA81XX(ha)) {
+ if (qla81xx_restart_mpi_firmware(vha) !=
+ QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x702a,
+ "MPI reset failed.\n");
+ }
}
rval = -EIO;
goto done_free_dma_rsp;
}
+
+ if (new_config[0]) {
+ int ret;
+
+ /* Revert back to original port config
+ * Also clear internal loopback
+ */
+ ret = qla81xx_reset_loopback_mode(vha,
+ new_config, 0, 1);
+ if (ret) {
+ /*
+ * If the reset of the loopback mode
+ * doesn't work take FCoE dump and then
+ * reset the chip.
+ */
+ ha->isp_ops->fw_dump(vha, 0);
+ set_bit(ISP_ABORT_NEEDED,
+ &vha->dpc_flags);
+ }
+
+ }
+
} else {
type = "FC_BSG_HST_VENDOR_LOOPBACK";
ql_dbg(ql_dbg_user, vha, 0x702b,
@@ -1012,14 +1084,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
return -EINVAL;
}
- ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request +
- sizeof(struct fc_bsg_request));
- if (!ql84_mgmt) {
- ql_log(ql_log_warn, vha, 0x703b,
- "MGMT header not provided, exiting.\n");
- return -EINVAL;
- }
-
mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (!mn) {
ql_log(ql_log_warn, vha, 0x703c,
@@ -1030,7 +1094,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
memset(mn, 0, sizeof(struct access_chip_84xx));
mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
mn->entry_count = 1;
-
+ ql84_mgmt = (void *)bsg_job->request + sizeof(struct fc_bsg_request);
switch (ql84_mgmt->mgmt.cmd) {
case QLA84_MGMT_READ_MEM:
case QLA84_MGMT_GET_INFO:
@@ -1210,14 +1274,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
return -EINVAL;
}
- port_param = (struct qla_port_param *)((char *)bsg_job->request +
- sizeof(struct fc_bsg_request));
- if (!port_param) {
- ql_log(ql_log_warn, vha, 0x7047,
- "port_param header not provided.\n");
- return -EINVAL;
- }
-
+ port_param = (void *)bsg_job->request + sizeof(struct fc_bsg_request);
if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
ql_log(ql_log_warn, vha, 0x7048,
"Invalid destination type.\n");
@@ -1830,6 +1887,128 @@ done:
}
static int
+qlafx00_mgmt_cmd(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = (DRIVER_ERROR << 16);
+ struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
+ srb_t *sp;
+ int req_sg_cnt = 0, rsp_sg_cnt = 0;
+ struct fc_port *fcport;
+ char *type = "FC_BSG_HST_FX_MGMT";
+
+ /* Copy the IOCB specific information */
+ piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
+ &bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+
+ /* Dump the vendor information */
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf,
+ (uint8_t *)piocb_rqst, sizeof(struct qla_mt_iocb_rqst_fx00));
+
+ if (!vha->flags.online) {
+ ql_log(ql_log_warn, vha, 0x70d0,
+ "Host is not online.\n");
+ rval = -EIO;
+ goto done;
+ }
+
+ if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) {
+ req_sg_cnt = dma_map_sg(&ha->pdev->dev,
+ bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+ if (!req_sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x70c7,
+ "dma_map_sg return %d for request\n", req_sg_cnt);
+ rval = -ENOMEM;
+ goto done;
+ }
+ }
+
+ if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) {
+ rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
+ bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ if (!rsp_sg_cnt) {
+ ql_log(ql_log_warn, vha, 0x70c8,
+ "dma_map_sg return %d for reply\n", rsp_sg_cnt);
+ rval = -ENOMEM;
+ goto done_unmap_req_sg;
+ }
+ }
+
+ ql_dbg(ql_dbg_user, vha, 0x70c9,
+ "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
+ "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
+ req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
+
+ /* Allocate a dummy fcport structure, since functions preparing the
+ * IOCB and mailbox command retrieves port specific information
+ * from fcport structure. For Host based ELS commands there will be
+ * no fcport structure allocated
+ */
+ fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
+ if (!fcport) {
+ ql_log(ql_log_warn, vha, 0x70ca,
+ "Failed to allocate fcport.\n");
+ rval = -ENOMEM;
+ goto done_unmap_rsp_sg;
+ }
+
+ /* Alloc SRB structure */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+ ql_log(ql_log_warn, vha, 0x70cb,
+ "qla2x00_get_sp failed.\n");
+ rval = -ENOMEM;
+ goto done_free_fcport;
+ }
+
+ /* Initialize all required fields of fcport */
+ fcport->vha = vha;
+ fcport->loop_id = piocb_rqst->dataword;
+
+ sp->type = SRB_FXIOCB_BCMD;
+ sp->name = "bsg_fx_mgmt";
+ sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
+ sp->u.bsg_job = bsg_job;
+ sp->free = qla2x00_bsg_sp_free;
+ sp->done = qla2x00_bsg_job_done;
+
+ ql_dbg(ql_dbg_user, vha, 0x70cc,
+ "bsg rqst type: %s fx_mgmt_type: %x id=%x\n",
+ type, piocb_rqst->func_type, fcport->loop_id);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x70cd,
+ "qla2x00_start_sp failed=%d.\n", rval);
+ mempool_free(sp, ha->srb_mempool);
+ rval = -EIO;
+ goto done_free_fcport;
+ }
+ return rval;
+
+done_free_fcport:
+ kfree(fcport);
+
+done_unmap_rsp_sg:
+ if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
+ dma_unmap_sg(&ha->pdev->dev,
+ bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+done_unmap_req_sg:
+ if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
+ dma_unmap_sg(&ha->pdev->dev,
+ bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+
+done:
+ return rval;
+}
+
+static int
qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
{
switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
@@ -1875,6 +2054,8 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
case QL_VND_DIAG_IO_CMD:
return qla24xx_process_bidir_cmd(bsg_job);
+ case QL_VND_FX00_MGMT_CMD:
+ return qlafx00_mgmt_cmd(bsg_job);
default:
return -ENOSYS;
}
@@ -1950,12 +2131,14 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
if (!req)
continue;
- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
if (((sp->type == SRB_CT_CMD) ||
- (sp->type == SRB_ELS_CMD_HST))
+ (sp->type == SRB_ELS_CMD_HST) ||
+ (sp->type == SRB_FXIOCB_BCMD))
&& (sp->u.bsg_job == bsg_job)) {
+ req->outstanding_cmds[cnt] = NULL;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
ql_log(ql_log_warn, vha, 0x7089,
@@ -1983,8 +2166,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
done:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (bsg_job->request->msgcode == FC_BSG_HST_CT)
- kfree(sp->fcport);
- mempool_free(sp, ha->srb_mempool);
+ sp->free(vha, sp);
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 37b8b7b..04f7703 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -22,6 +22,7 @@
#define QL_VND_DIAG_IO_CMD 0x0A
#define QL_VND_WRITE_I2C 0x10
#define QL_VND_READ_I2C 0x11
+#define QL_VND_FX00_MGMT_CMD 0x12
/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK 0
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 53f9e49..df132fe 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -11,35 +11,42 @@
* ----------------------------------------------------------------------
* | Level | Last Value Used | Holes |
* ----------------------------------------------------------------------
- * | Module Init and Probe | 0x0125 | 0x4b,0xba,0xfa |
- * | Mailbox commands | 0x114f | 0x111a-0x111b |
- * | | | 0x112c-0x112e |
- * | | | 0x113a |
- * | Device Discovery | 0x2087 | 0x2020-0x2022, |
+ * | Module Init and Probe | 0x014f | 0x4b,0xba,0xfa |
+ * | Mailbox commands | 0x117a | 0x111a-0x111b |
+ * | | | 0x1155-0x1158 |
+ * | Device Discovery | 0x2095 | 0x2020-0x2022, |
+ * | | | 0x2011-0x2012, |
* | | | 0x2016 |
- * | Queue Command and IO tracing | 0x3030 | 0x3006-0x300b |
+ * | Queue Command and IO tracing | 0x3058 | 0x3006-0x300b |
* | | | 0x3027-0x3028 |
- * | | | 0x302d-0x302e |
- * | DPC Thread | 0x401d | 0x4002,0x4013 |
- * | Async Events | 0x5071 | 0x502b-0x502f |
+ * | | | 0x303d-0x3041 |
+ * | | | 0x302d,0x3033 |
+ * | | | 0x3036,0x3038 |
+ * | | | 0x303a |
+ * | DPC Thread | 0x4022 | 0x4002,0x4013 |
+ * | Async Events | 0x5081 | 0x502b-0x502f |
* | | | 0x5047,0x5052 |
+ * | | | 0x5040,0x5075 |
* | Timer Routines | 0x6011 | |
- * | User Space Interactions | 0x70c3 | 0x7018,0x702e, |
+ * | User Space Interactions | 0x70dd | 0x7018,0x702e, |
+ * | | | 0x7020,0x7024, |
* | | | 0x7039,0x7045, |
* | | | 0x7073-0x7075, |
- * | | | 0x708c, |
+ * | | | 0x707b,0x708c, |
* | | | 0x70a5,0x70a6, |
* | | | 0x70a8,0x70ab, |
- * | | | 0x70ad-0x70ae |
+ * | | | 0x70ad-0x70ae, |
+ * | | | 0x70d1-0x70da, |
+ * | | | 0x7047,0x703b |
* | Task Management | 0x803c | 0x8025-0x8026 |
* | | | 0x800b,0x8039 |
* | AER/EEH | 0x9011 | |
* | Virtual Port | 0xa007 | |
- * | ISP82XX Specific | 0xb084 | 0xb002,0xb024 |
+ * | ISP82XX Specific | 0xb086 | 0xb002,0xb024 |
* | MultiQ | 0xc00c | |
* | Misc | 0xd010 | |
- * | Target Mode | 0xe06f | |
- * | Target Mode Management | 0xf071 | |
+ * | Target Mode | 0xe070 | |
+ * | Target Mode Management | 0xf072 | |
* | Target Mode Task Management | 0x1000b | |
* ----------------------------------------------------------------------
*/
@@ -400,7 +407,7 @@ qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr,
void *ring;
} aq, *aqp;
- if (!ha->tgt.atio_q_length)
+ if (!ha->tgt.atio_ring)
return ptr;
num_queues = 1;
@@ -1463,7 +1470,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
nxt = qla2xxx_copy_queues(ha, nxt);
- nxt = qla24xx_copy_eft(ha, nxt);
+ qla24xx_copy_eft(ha, nxt);
/* Chain entries -- started with MQ. */
nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
@@ -1782,7 +1789,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
nxt = qla2xxx_copy_queues(ha, nxt);
- nxt = qla24xx_copy_eft(ha, nxt);
+ qla24xx_copy_eft(ha, nxt);
/* Chain entries -- started with MQ. */
nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
@@ -2284,7 +2291,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
copy_queue:
nxt = qla2xxx_copy_queues(ha, nxt);
- nxt = qla24xx_copy_eft(ha, nxt);
+ qla24xx_copy_eft(ha, nxt);
/* Chain entries -- started with MQ. */
nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 8f911c0..35e20b4 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6e7727f4..95ca32a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -37,6 +37,7 @@
#include "qla_nx.h"
#define QLA2XXX_DRIVER_NAME "qla2xxx"
#define QLA2XXX_APIDEV "ql2xapidev"
+#define QLA2XXX_MANUFACTURER "QLogic Corporation"
/*
* We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
@@ -244,7 +245,6 @@
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
#include "qla_fw.h"
-
/*
* Timeout timer counts in seconds
*/
@@ -253,8 +253,8 @@
#define LOOP_DOWN_TIME 255 /* 240 */
#define LOOP_DOWN_RESET (LOOP_DOWN_TIME - 30)
-/* Maximum outstanding commands in ISP queues (1-65535) */
-#define MAX_OUTSTANDING_COMMANDS 1024
+#define DEFAULT_OUTSTANDING_COMMANDS 1024
+#define MIN_OUTSTANDING_COMMANDS 128
/* ISP request and response entry counts (37-65535) */
#define REQUEST_ENTRY_CNT_2100 128 /* Number of request entries. */
@@ -264,6 +264,7 @@
#define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/
#define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */
+#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
struct req_que;
@@ -283,6 +284,7 @@ struct sd_dif_tuple {
struct srb_cmd {
struct scsi_cmnd *cmd; /* Linux SCSI command pkt */
uint32_t request_sense_length;
+ uint32_t fw_sense_length;
uint8_t *request_sense_ptr;
void *ctx;
};
@@ -320,7 +322,39 @@ struct srb_iocb {
uint32_t flags;
uint32_t lun;
uint32_t data;
+ struct completion comp;
+ __le16 comp_status;
} tmf;
+ struct {
+#define SRB_FXDISC_REQ_DMA_VALID BIT_0
+#define SRB_FXDISC_RESP_DMA_VALID BIT_1
+#define SRB_FXDISC_REQ_DWRD_VALID BIT_2
+#define SRB_FXDISC_RSP_DWRD_VALID BIT_3
+#define FXDISC_TIMEOUT 20
+ uint8_t flags;
+ uint32_t req_len;
+ uint32_t rsp_len;
+ void *req_addr;
+ void *rsp_addr;
+ dma_addr_t req_dma_handle;
+ dma_addr_t rsp_dma_handle;
+ __le32 adapter_id;
+ __le32 adapter_id_hi;
+ __le16 req_func_type;
+ __le32 req_data;
+ __le32 req_data_extra;
+ __le32 result;
+ __le32 seq_number;
+ __le16 fw_flags;
+ struct completion fxiocb_comp;
+ __le32 reserved_0;
+ uint8_t reserved_1;
+ } fxiocb;
+ struct {
+ uint32_t cmd_hndl;
+ __le16 comp_status;
+ struct completion comp;
+ } abt;
} u;
struct timer_list timer;
@@ -337,6 +371,10 @@ struct srb_iocb {
#define SRB_TM_CMD 7
#define SRB_SCSI_CMD 8
#define SRB_BIDI_CMD 9
+#define SRB_FXIOCB_DCMD 10
+#define SRB_FXIOCB_BCMD 11
+#define SRB_ABT_CMD 12
+
typedef struct srb {
atomic_t ref_count;
@@ -367,6 +405,10 @@ typedef struct srb {
(sp->u.scmd.request_sense_ptr)
#define SET_CMD_SENSE_PTR(sp, ptr) \
(sp->u.scmd.request_sense_ptr = ptr)
+#define GET_FW_SENSE_LEN(sp) \
+ (sp->u.scmd.fw_sense_length)
+#define SET_FW_SENSE_LEN(sp, len) \
+ (sp->u.scmd.fw_sense_length = len)
struct msg_echo_lb {
dma_addr_t send_dma;
@@ -375,6 +417,7 @@ struct msg_echo_lb {
uint16_t rsp_sg_cnt;
uint16_t options;
uint32_t transfer_size;
+ uint32_t iteration_count;
};
/*
@@ -537,13 +580,78 @@ struct device_reg_25xxmq {
uint32_t req_q_out;
uint32_t rsp_q_in;
uint32_t rsp_q_out;
+ uint32_t atio_q_in;
+ uint32_t atio_q_out;
+};
+
+
+struct device_reg_fx00 {
+ uint32_t mailbox0; /* 00 */
+ uint32_t mailbox1; /* 04 */
+ uint32_t mailbox2; /* 08 */
+ uint32_t mailbox3; /* 0C */
+ uint32_t mailbox4; /* 10 */
+ uint32_t mailbox5; /* 14 */
+ uint32_t mailbox6; /* 18 */
+ uint32_t mailbox7; /* 1C */
+ uint32_t mailbox8; /* 20 */
+ uint32_t mailbox9; /* 24 */
+ uint32_t mailbox10; /* 28 */
+ uint32_t mailbox11;
+ uint32_t mailbox12;
+ uint32_t mailbox13;
+ uint32_t mailbox14;
+ uint32_t mailbox15;
+ uint32_t mailbox16;
+ uint32_t mailbox17;
+ uint32_t mailbox18;
+ uint32_t mailbox19;
+ uint32_t mailbox20;
+ uint32_t mailbox21;
+ uint32_t mailbox22;
+ uint32_t mailbox23;
+ uint32_t mailbox24;
+ uint32_t mailbox25;
+ uint32_t mailbox26;
+ uint32_t mailbox27;
+ uint32_t mailbox28;
+ uint32_t mailbox29;
+ uint32_t mailbox30;
+ uint32_t mailbox31;
+ uint32_t aenmailbox0;
+ uint32_t aenmailbox1;
+ uint32_t aenmailbox2;
+ uint32_t aenmailbox3;
+ uint32_t aenmailbox4;
+ uint32_t aenmailbox5;
+ uint32_t aenmailbox6;
+ uint32_t aenmailbox7;
+ /* Request Queue. */
+ uint32_t req_q_in; /* A0 - Request Queue In-Pointer */
+ uint32_t req_q_out; /* A4 - Request Queue Out-Pointer */
+ /* Response Queue. */
+ uint32_t rsp_q_in; /* A8 - Response Queue In-Pointer */
+ uint32_t rsp_q_out; /* AC - Response Queue Out-Pointer */
+ /* Init values shadowed on FW Up Event */
+ uint32_t initval0; /* B0 */
+ uint32_t initval1; /* B4 */
+ uint32_t initval2; /* B8 */
+ uint32_t initval3; /* BC */
+ uint32_t initval4; /* C0 */
+ uint32_t initval5; /* C4 */
+ uint32_t initval6; /* C8 */
+ uint32_t initval7; /* CC */
+ uint32_t fwheartbeat; /* D0 */
};
+
+
typedef union {
struct device_reg_2xxx isp;
struct device_reg_24xx isp24;
struct device_reg_25xxmq isp25mq;
struct device_reg_82xx isp82;
+ struct device_reg_fx00 ispfx00;
} device_reg_t;
#define ISP_REQ_Q_IN(ha, reg) \
@@ -563,6 +671,9 @@ typedef union {
&(reg)->u.isp2100.mailbox5 : \
&(reg)->u.isp2300.rsp_q_out)
+#define ISP_ATIO_Q_IN(vha) (vha->hw->tgt.atio_q_in)
+#define ISP_ATIO_Q_OUT(vha) (vha->hw->tgt.atio_q_out)
+
#define MAILBOX_REG(ha, reg, num) \
(IS_QLA2100(ha) || IS_QLA2200(ha) ? \
(num < 8 ? \
@@ -596,6 +707,20 @@ typedef struct {
#define IOCTL_CMD BIT_2
} mbx_cmd_t;
+struct mbx_cmd_32 {
+ uint32_t out_mb; /* outbound from driver */
+ uint32_t in_mb; /* Incoming from RISC */
+ uint32_t mb[MAILBOX_REGISTER_COUNT];
+ long buf_size;
+ void *bufp;
+ uint32_t tov;
+ uint8_t flags;
+#define MBX_DMA_IN BIT_0
+#define MBX_DMA_OUT BIT_1
+#define IOCTL_CMD BIT_2
+};
+
+
#define MBX_TOV_SECONDS 30
/*
@@ -671,6 +796,15 @@ typedef struct {
#define MBA_BYPASS_NOTIFICATION 0x8043 /* Auto bypass notification. */
#define MBA_DISCARD_RND_FRAME 0x8048 /* discard RND frame due to error. */
#define MBA_REJECTED_FCP_CMD 0x8049 /* rejected FCP_CMD. */
+#define MBA_FW_NOT_STARTED 0x8050 /* Firmware not started */
+#define MBA_FW_STARTING 0x8051 /* Firmware starting */
+#define MBA_FW_RESTART_CMPLT 0x8060 /* Firmware restart complete */
+#define MBA_INIT_REQUIRED 0x8061 /* Initialization required */
+#define MBA_SHUTDOWN_REQUESTED 0x8062 /* Shutdown Requested */
+#define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */
+#define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change
+ Notification */
+#define MBA_FW_POLL_STATE 0x8600 /* Firmware in poll diagnostic state */
/* 83XX FCoE specific */
#define MBA_IDC_AEN 0x8200 /* FCoE: NIC Core state change AEN */
@@ -762,8 +896,8 @@ typedef struct {
#define MBC_PORT_LOGOUT 0x56 /* Port Logout request */
#define MBC_SEND_RNID_ELS 0x57 /* Send RNID ELS request */
#define MBC_SET_RNID_PARAMS 0x59 /* Set RNID parameters */
-#define MBC_GET_RNID_PARAMS 0x5a /* Data Rate */
-#define MBC_DATA_RATE 0x5d /* Get RNID parameters */
+#define MBC_GET_RNID_PARAMS 0x5a /* Get RNID parameters */
+#define MBC_DATA_RATE 0x5d /* Data Rate */
#define MBC_INITIALIZE_FIRMWARE 0x60 /* Initialize firmware */
#define MBC_INITIATE_LIP 0x62 /* Initiate Loop */
/* Initialization Procedure */
@@ -792,6 +926,12 @@ typedef struct {
#define MBC_LUN_RESET 0x7E /* Send LUN reset */
/*
+ * all the Mt. Rainier mailbox command codes that clash with FC/FCoE ones
+ * should be defined with MBC_MR_*
+ */
+#define MBC_MR_DRV_SHUTDOWN 0x6A
+
+/*
* ISP24xx mailbox commands
*/
#define MBC_SERDES_PARAMS 0x10 /* Serdes Tx Parameters. */
@@ -809,6 +949,7 @@ typedef struct {
#define MBC_HOST_MEMORY_COPY 0x53 /* Host Memory Copy. */
#define MBC_SEND_RNFT_ELS 0x5e /* Send RNFT ELS request */
#define MBC_GET_LINK_PRIV_STATS 0x6d /* Get link & private data. */
+#define MBC_LINK_INITIALIZATION 0x72 /* Do link initialization. */
#define MBC_SET_VENDOR_ID 0x76 /* Set Vendor ID. */
#define MBC_PORT_RESET 0x120 /* Port Reset */
#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */
@@ -856,6 +997,8 @@ typedef struct {
#define MBX_1 BIT_1
#define MBX_0 BIT_0
+#define RNID_TYPE_ASIC_TEMP 0xC
+
/*
* Firmware state codes from get firmware state mailbox command
*/
@@ -1049,6 +1192,30 @@ typedef struct {
uint8_t reserved_3[26];
} init_cb_t;
+
+struct init_cb_fx {
+ uint16_t version;
+ uint16_t reserved_1[13];
+ __le16 request_q_outpointer;
+ __le16 response_q_inpointer;
+ uint16_t reserved_2[2];
+ __le16 response_q_length;
+ __le16 request_q_length;
+ uint16_t reserved_3[2];
+ __le32 request_q_address[2];
+ __le32 response_q_address[2];
+ uint16_t reserved_4[4];
+ uint8_t response_q_msivec;
+ uint8_t reserved_5[19];
+ uint16_t interrupt_delay_timer;
+ uint16_t reserved_6;
+ uint32_t fwoptions1;
+ uint32_t fwoptions2;
+ uint32_t fwoptions3;
+ uint8_t reserved_7[24];
+};
+
+
/*
* Get Link Status mailbox command return buffer.
*/
@@ -1822,6 +1989,9 @@ typedef struct fc_port {
uint16_t loop_id;
uint16_t old_loop_id;
+ uint16_t tgt_id;
+ uint16_t old_tgt_id;
+
uint8_t fcp_prio;
uint8_t fabric_port_name[WWN_SIZE];
@@ -1839,10 +2009,14 @@ typedef struct fc_port {
uint8_t fc4_type;
uint8_t scan_state;
+
+ unsigned long last_queue_full;
+ unsigned long last_ramp_up;
+
+ uint16_t port_id;
} fc_port_t;
-#define QLA_FCPORT_SCAN_NONE 0
-#define QLA_FCPORT_SCAN_FOUND 1
+#include "qla_mr.h"
/*
* Fibre channel port/lun states.
@@ -2385,6 +2559,7 @@ struct isp_operations {
int (*start_scsi) (srb_t *);
int (*abort_isp) (struct scsi_qla_host *);
int (*iospace_config)(struct qla_hw_data*);
+ int (*initialize_adapter)(struct scsi_qla_host *);
};
/* MSI-X Support *************************************************************/
@@ -2423,6 +2598,7 @@ enum qla_work_type {
QLA_EVT_ASYNC_ADISC,
QLA_EVT_ASYNC_ADISC_DONE,
QLA_EVT_UEVENT,
+ QLA_EVT_AENFX,
};
@@ -2450,7 +2626,15 @@ struct qla_work_evt {
u32 code;
#define QLA_UEVENT_CODE_FW_DUMP 0
} uevent;
- } u;
+ struct {
+ uint32_t evtcode;
+ uint32_t mbx[8];
+ uint32_t count;
+ } aenfx;
+ struct {
+ srb_t *sp;
+ } iosb;
+ } u;
};
struct qla_chip_state_84xx {
@@ -2514,6 +2698,11 @@ struct rsp_que {
struct req_que *req;
srb_t *status_srb; /* status continuation entry */
struct work_struct q_work;
+
+ dma_addr_t dma_fx00;
+ response_t *ring_fx00;
+ uint16_t length_fx00;
+ uint8_t rsp_pkt[REQUEST_ENTRY_SIZE];
};
/* Request queue data structure */
@@ -2533,9 +2722,16 @@ struct req_que {
uint16_t qos;
uint16_t vp_idx;
struct rsp_que *rsp;
- srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS];
+ srb_t **outstanding_cmds;
uint32_t current_outstanding_cmd;
+ uint16_t num_outstanding_cmds;
+#define MAX_Q_DEPTH 32
int max_q_depth;
+
+ dma_addr_t dma_fx00;
+ request_t *ring_fx00;
+ uint16_t length_fx00;
+ uint8_t req_pkt[REQUEST_ENTRY_SIZE];
};
/* Place holder for FW buffer parameters */
@@ -2557,11 +2753,13 @@ struct qlt_hw_data {
struct atio *atio_ring_ptr; /* Current address. */
uint16_t atio_ring_index; /* Current index. */
uint16_t atio_q_length;
+ uint32_t __iomem *atio_q_in;
+ uint32_t __iomem *atio_q_out;
void *target_lport_ptr;
struct qla_tgt_func_tmpl *tgt_ops;
struct qla_tgt *qla_tgt;
- struct qla_tgt_cmd *cmds[MAX_OUTSTANDING_COMMANDS];
+ struct qla_tgt_cmd *cmds[DEFAULT_OUTSTANDING_COMMANDS];
uint16_t current_handle;
struct qla_tgt_vp_map *tgt_vp_map;
@@ -2618,13 +2816,15 @@ struct qla_hw_data {
uint32_t nic_core_hung:1;
uint32_t quiesce_owner:1;
- uint32_t thermal_supported:1;
uint32_t nic_core_reset_hdlr_active:1;
uint32_t nic_core_reset_owner:1;
uint32_t isp82xx_no_md_cap:1;
uint32_t host_shutting_down:1;
uint32_t idc_compl_status:1;
- /* 32 bits */
+
+ uint32_t mr_reset_hdlr_active:1;
+ uint32_t mr_intr_valid:1;
+ /* 34 bits */
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -2641,7 +2841,21 @@ struct qla_hw_data {
resource_size_t pio_address;
#define MIN_IOBASE_LEN 0x100
-/* Multi queue data structs */
+ dma_addr_t bar0_hdl;
+
+ void __iomem *cregbase;
+ dma_addr_t bar2_hdl;
+#define BAR0_LEN_FX00 (1024 * 1024)
+#define BAR2_LEN_FX00 (128 * 1024)
+
+ uint32_t rqstq_intr_code;
+ uint32_t mbx_intr_code;
+ uint32_t req_que_len;
+ uint32_t rsp_que_len;
+ uint32_t req_que_off;
+ uint32_t rsp_que_off;
+
+ /* Multi queue data structs */
device_reg_t __iomem *mqiobase;
device_reg_t __iomem *msixbase;
uint16_t msix_count;
@@ -2720,7 +2934,8 @@ struct qla_hw_data {
#define DT_ISP8021 BIT_14
#define DT_ISP2031 BIT_15
#define DT_ISP8031 BIT_16
-#define DT_ISP_LAST (DT_ISP8031 << 1)
+#define DT_ISPFX00 BIT_17
+#define DT_ISP_LAST (DT_ISPFX00 << 1)
#define DT_T10_PI BIT_25
#define DT_IIDMA BIT_26
@@ -2748,6 +2963,7 @@ struct qla_hw_data {
#define IS_QLA82XX(ha) (DT_MASK(ha) & DT_ISP8021)
#define IS_QLA2031(ha) (DT_MASK(ha) & DT_ISP2031)
#define IS_QLA8031(ha) (DT_MASK(ha) & DT_ISP8031)
+#define IS_QLAFX00(ha) (DT_MASK(ha) & DT_ISPFX00)
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
@@ -2788,6 +3004,8 @@ struct qla_hw_data {
#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha))
#define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
(((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
+#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha))
+#define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length)
/* HBA serial number */
uint8_t serial0;
@@ -2810,6 +3028,7 @@ struct qla_hw_data {
uint16_t r_a_tov;
int port_down_retry_count;
uint8_t mbx_count;
+ uint8_t aen_mbx_count;
uint32_t login_retry_count;
/* SNS command interfaces. */
@@ -2857,9 +3076,13 @@ struct qla_hw_data {
void *swl;
/* These are used by mailbox operations. */
- volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
+ uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
+ uint32_t mailbox_out32[MAILBOX_REGISTER_COUNT];
+ uint32_t aenmb[AEN_MAILBOX_REGISTER_COUNT_FX00];
mbx_cmd_t *mcp;
+ struct mbx_cmd_32 *mcp32;
+
unsigned long mbx_cmd_flags;
#define MBX_INTERRUPT 1
#define MBX_INTR_WAIT 2
@@ -2870,7 +3093,13 @@ struct qla_hw_data {
struct completion mbx_cmd_comp; /* Serialize mbx access */
struct completion mbx_intr_comp; /* Used for completion notification */
struct completion dcbx_comp; /* For set port config notification */
+ struct completion lb_portup_comp; /* Used to wait for link up during
+ * loopback */
+#define DCBX_COMP_TIMEOUT 20
+#define LB_PORTUP_COMP_TIMEOUT 10
+
int notify_dcbx_comp;
+ int notify_lb_portup_comp;
struct mutex selflogin_lock;
/* Basic firmware related information. */
@@ -2887,6 +3116,7 @@ struct qla_hw_data {
#define RISC_START_ADDRESS_2300 0x800
#define RISC_START_ADDRESS_2400 0x100000
uint16_t fw_xcb_count;
+ uint16_t fw_iocb_count;
uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */
uint8_t fw_seriallink_options[4];
@@ -2996,6 +3226,7 @@ struct qla_hw_data {
int cur_vport_count;
struct qla_chip_state_84xx *cs84xx;
+ struct qla_statistics qla_stats;
struct isp_operations *isp_ops;
struct workqueue_struct *wq;
struct qlfc_fw fw_buf;
@@ -3056,7 +3287,18 @@ struct qla_hw_data {
struct work_struct idc_state_handler;
struct work_struct nic_core_unrecoverable;
+#define HOST_QUEUE_RAMPDOWN_INTERVAL (60 * HZ)
+#define HOST_QUEUE_RAMPUP_INTERVAL (30 * HZ)
+ unsigned long host_last_rampdown_time;
+ unsigned long host_last_rampup_time;
+ int cfg_lun_q_depth;
+
+ struct mr_data_fx00 mr;
+
struct qlt_hw_data tgt;
+ uint16_t thermal_support;
+#define THERMAL_SUPPORT_I2C BIT_0
+#define THERMAL_SUPPORT_ISP BIT_1
};
/*
@@ -3082,6 +3324,8 @@ typedef struct scsi_qla_host {
uint32_t process_response_queue :1;
uint32_t difdix_supported:1;
uint32_t delete_progress:1;
+
+ uint32_t fw_tgt_reported:1;
} flags;
atomic_t loop_state;
@@ -3115,6 +3359,11 @@ typedef struct scsi_qla_host {
#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
#define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */
#define SCR_PENDING 21 /* SCR in target mode */
+#define HOST_RAMP_DOWN_QUEUE_DEPTH 22
+#define HOST_RAMP_UP_QUEUE_DEPTH 23
+#define PORT_UPDATE_NEEDED 24
+#define FX00_RESET_RECOVERY 25
+#define FX00_TARGET_SCAN 26
uint32_t device_flags;
#define SWITCH_FOUND BIT_0
@@ -3205,6 +3454,10 @@ struct qla_tgt_vp_map {
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
atomic_read(&ha->loop_state) == LOOP_DOWN)
+#define STATE_TRANSITION(ha) \
+ (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \
+ test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
+
#define QLA_VHA_MARK_BUSY(__vha, __bail) do { \
atomic_inc(&__vha->vref_count); \
mb(); \
@@ -3248,8 +3501,6 @@ struct qla_tgt_vp_map {
#define NVRAM_DELAY() udelay(10)
-#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1)
-
/*
* Flash support definitions
*/
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 706c4f7..792a292 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index be6d61a..1ac2b0e 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -300,7 +300,8 @@ struct init_cb_24xx {
uint32_t prio_request_q_address[2];
uint16_t msix;
- uint8_t reserved_2[6];
+ uint16_t msix_atio;
+ uint8_t reserved_2[4];
uint16_t atio_q_inpointer;
uint16_t atio_q_length;
@@ -1387,9 +1388,7 @@ struct qla_flt_header {
#define FLT_REG_FCP_PRIO_0 0x87
#define FLT_REG_FCP_PRIO_1 0x88
#define FLT_REG_FCOE_FW 0xA4
-#define FLT_REG_FCOE_VPD_0 0xA9
#define FLT_REG_FCOE_NVRAM_0 0xAA
-#define FLT_REG_FCOE_VPD_1 0xAB
#define FLT_REG_FCOE_NVRAM_1 0xAC
struct qla_flt_region {
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2411d1a..2d98232 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -55,7 +55,7 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
-extern int qla2x00_get_thermal_temp(scsi_qla_host_t *, uint16_t *, uint16_t *);
+extern int qla2x00_get_thermal_temp(scsi_qla_host_t *, uint16_t *);
extern void qla84xx_put_chip(struct scsi_qla_host *);
@@ -84,6 +84,10 @@ extern int qla83xx_nic_core_reset(scsi_qla_host_t *);
extern void qla83xx_reset_ownership(scsi_qla_host_t *);
extern int qla2xxx_mctp_dump(scsi_qla_host_t *);
+extern int
+qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
+extern int qla2x00_init_rings(scsi_qla_host_t *);
+
/*
* Global Data in qla_os.c source file.
*/
@@ -94,6 +98,7 @@ extern int qlport_down_retry;
extern int ql2xplogiabsentdevice;
extern int ql2xloginretrycount;
extern int ql2xfdmienable;
+extern int ql2xmaxqdepth;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
extern int ql2xiidmaenable;
@@ -130,7 +135,6 @@ extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *,
fc_port_t *, uint16_t *);
-extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
@@ -154,6 +158,7 @@ extern int qla83xx_set_drv_presence(scsi_qla_host_t *vha);
extern int __qla83xx_set_drv_presence(scsi_qla_host_t *vha);
extern int qla83xx_clear_drv_presence(scsi_qla_host_t *vha);
extern int __qla83xx_clear_drv_presence(scsi_qla_host_t *vha);
+extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
/*
* Global Functions in qla_mid.c source file.
@@ -207,8 +212,6 @@ extern int qla24xx_start_scsi(srb_t *sp);
int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
uint16_t, uint16_t, uint8_t);
extern int qla2x00_start_sp(srb_t *);
-extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t);
-extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
extern int qla24xx_dif_start_scsi(srb_t *);
extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
@@ -278,6 +281,9 @@ extern int
qla2x00_get_port_name(scsi_qla_host_t *, uint16_t, uint8_t *, uint8_t);
extern int
+qla24xx_link_initialize(scsi_qla_host_t *);
+
+extern int
qla2x00_lip_reset(scsi_qla_host_t *);
extern int
@@ -417,6 +423,12 @@ extern void qla2x00_free_irqs(scsi_qla_host_t *);
extern int qla2x00_get_data_rate(scsi_qla_host_t *);
extern const char *qla2x00_get_link_speed_str(struct qla_hw_data *, uint16_t);
+extern srb_t *
+qla2x00_get_sp_from_handle(scsi_qla_host_t *, const char *, struct req_que *,
+ void *);
+extern void
+qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *,
+ uint32_t);
/*
* Global Function Prototypes in qla_sup.c source file.
@@ -436,6 +448,7 @@ extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
+extern int qla2x00_is_a_vp_did(scsi_qla_host_t *, uint32_t);
extern int qla2x00_beacon_on(struct scsi_qla_host *);
extern int qla2x00_beacon_off(struct scsi_qla_host *);
@@ -553,6 +566,42 @@ extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
+/* qlafx00 related functions */
+extern int qlafx00_pci_config(struct scsi_qla_host *);
+extern int qlafx00_initialize_adapter(struct scsi_qla_host *);
+extern void qlafx00_soft_reset(scsi_qla_host_t *);
+extern int qlafx00_chip_diag(scsi_qla_host_t *);
+extern void qlafx00_config_rings(struct scsi_qla_host *);
+extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *);
+extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *);
+extern irqreturn_t qlafx00_intr_handler(int, void *);
+extern void qlafx00_enable_intrs(struct qla_hw_data *);
+extern void qlafx00_disable_intrs(struct qla_hw_data *);
+extern int qlafx00_abort_command(srb_t *);
+extern int qlafx00_abort_target(fc_port_t *, unsigned int, int);
+extern int qlafx00_lun_reset(fc_port_t *, unsigned int, int);
+extern int qlafx00_start_scsi(srb_t *);
+extern int qlafx00_abort_isp(scsi_qla_host_t *);
+extern int qlafx00_iospace_config(struct qla_hw_data *);
+extern int qlafx00_init_firmware(scsi_qla_host_t *, uint16_t);
+extern int qlafx00_fw_ready(scsi_qla_host_t *);
+extern int qlafx00_configure_devices(scsi_qla_host_t *);
+extern int qlafx00_reset_initialize(scsi_qla_host_t *);
+extern int qlafx00_fx_disc(scsi_qla_host_t *, fc_port_t *, uint16_t);
+extern int qlafx00_process_aen(struct scsi_qla_host *, struct qla_work_evt *);
+extern int qlafx00_post_aenfx_work(struct scsi_qla_host *, uint32_t,
+ uint32_t *, int);
+extern uint32_t qlafx00_fw_state_show(struct device *,
+ struct device_attribute *, char *);
+extern void qlafx00_get_host_speed(struct Scsi_Host *);
+extern void qlafx00_init_response_q_entries(struct rsp_que *);
+
+extern void qlafx00_tm_iocb(srb_t *, struct tsk_mgmt_entry_fx00 *);
+extern void qlafx00_abort_iocb(srb_t *, struct abort_iocb_entry_fx00 *);
+extern void qlafx00_fxdisc_iocb(srb_t *, struct fxdisc_entry_fx00 *);
+extern void qlafx00_timer_routine(scsi_qla_host_t *);
+extern int qlafx00_rescan_isp(scsi_qla_host_t *);
+
/* qla82xx related functions */
/* PCI related functions */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 01efc0e..0926451 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -99,17 +99,17 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
* Returns a pointer to the intitialized @ct_req.
*/
static inline struct ct_sns_req *
-qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size)
+qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
{
- memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+ memset(p, 0, sizeof(struct ct_sns_pkt));
- ct_req->header.revision = 0x01;
- ct_req->header.gs_type = 0xFC;
- ct_req->header.gs_subtype = 0x02;
- ct_req->command = cpu_to_be16(cmd);
- ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+ p->p.req.header.revision = 0x01;
+ p->p.req.header.gs_type = 0xFC;
+ p->p.req.header.gs_subtype = 0x02;
+ p->p.req.command = cpu_to_be16(cmd);
+ p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
- return (ct_req);
+ return &p->p.req;
}
static int
@@ -188,7 +188,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
GA_NXT_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
GA_NXT_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -284,8 +284,7 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
gid_pt_rsp_size);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
- gid_pt_rsp_size);
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_type */
@@ -359,7 +358,7 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
GPN_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
GPN_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -421,7 +420,7 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
GNN_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
GNN_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -495,7 +494,7 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
RFT_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
RFT_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -551,7 +550,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
RFF_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
RFF_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -606,8 +605,7 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
RNN_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
- RNN_ID_RSP_SIZE);
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_id, node_name */
@@ -639,9 +637,14 @@ void
qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn)
{
struct qla_hw_data *ha = vha->hw;
- sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s",ha->model_number,
- ha->fw_major_version, ha->fw_minor_version,
- ha->fw_subminor_version, qla2x00_version_str);
+
+ if (IS_QLAFX00(ha))
+ sprintf(snn, "%s FW:v%s DVR:v%s", ha->model_number,
+ ha->mr.fw_version, qla2x00_version_str);
+ else
+ sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
+ ha->fw_major_version, ha->fw_minor_version,
+ ha->fw_subminor_version, qla2x00_version_str);
}
/**
@@ -671,7 +674,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
RSNN_NN_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -923,7 +926,7 @@ qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
sns_cmd->p.gpn_data[9] != 0x02) {
ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
"GPN_ID failed, rejected request, gpn_rsp:\n");
- ql_dump_buffer(ql_dbg_disc, vha, 0x207f,
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
sns_cmd->p.gpn_data, 16);
rval = QLA_FUNCTION_FAILED;
} else {
@@ -1257,18 +1260,18 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
* Returns a pointer to the intitialized @ct_req.
*/
static inline struct ct_sns_req *
-qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
+qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,
uint16_t rsp_size)
{
- memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+ memset(p, 0, sizeof(struct ct_sns_pkt));
- ct_req->header.revision = 0x01;
- ct_req->header.gs_type = 0xFA;
- ct_req->header.gs_subtype = 0x10;
- ct_req->command = cpu_to_be16(cmd);
- ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+ p->p.req.header.revision = 0x01;
+ p->p.req.header.gs_type = 0xFA;
+ p->p.req.header.gs_subtype = 0x10;
+ p->p.req.command = cpu_to_be16(cmd);
+ p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
- return ct_req;
+ return &p->p.req;
}
/**
@@ -1296,8 +1299,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
- RHBA_RSP_SIZE);
+ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare FDMI command arguments -- attribute block, attributes. */
@@ -1328,8 +1330,8 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
/* Manufacturer. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
- strcpy(eiter->a.manufacturer, "QLogic Corporation");
- alen = strlen(eiter->a.manufacturer);
+ alen = strlen(QLA2XXX_MANUFACTURER);
+ strncpy(eiter->a.manufacturer, QLA2XXX_MANUFACTURER, alen + 1);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
@@ -1365,8 +1367,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
/* Model description. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
- if (ha->model_desc)
- strncpy(eiter->a.model_desc, ha->model_desc, 80);
+ strncpy(eiter->a.model_desc, ha->model_desc, 80);
alen = strlen(eiter->a.model_desc);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
eiter->len = cpu_to_be16(4 + alen);
@@ -1486,8 +1487,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
DHBA_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
- DHBA_RSP_SIZE);
+ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare FDMI command arguments -- portname. */
@@ -1543,8 +1543,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
- RPA_RSP_SIZE);
+ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare FDMI command arguments -- attribute block, attributes. */
@@ -1649,8 +1648,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
/* OS device name. */
eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
- strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME);
- alen = strlen(eiter->a.os_dev_name);
+ alen = strlen(QLA2XXX_DRIVER_NAME);
+ strncpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME, alen + 1);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
@@ -1718,7 +1717,8 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha)
int rval;
struct qla_hw_data *ha = vha->hw;
- if (IS_QLA2100(ha) || IS_QLA2200(ha))
+ if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
+ IS_QLAFX00(ha))
return QLA_FUNCTION_FAILED;
rval = qla2x00_mgmt_svr_login(vha);
@@ -1770,7 +1770,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
GFPN_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
GFPN_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
@@ -1837,18 +1837,18 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
static inline struct ct_sns_req *
-qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd,
+qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
uint16_t rsp_size)
{
- memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+ memset(p, 0, sizeof(struct ct_sns_pkt));
- ct_req->header.revision = 0x01;
- ct_req->header.gs_type = 0xFA;
- ct_req->header.gs_subtype = 0x01;
- ct_req->command = cpu_to_be16(cmd);
- ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+ p->p.req.header.revision = 0x01;
+ p->p.req.header.gs_type = 0xFA;
+ p->p.req.header.gs_subtype = 0x01;
+ p->p.req.command = cpu_to_be16(cmd);
+ p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
- return ct_req;
+ return &p->p.req;
}
/**
@@ -1884,8 +1884,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
GPSC_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req,
- GPSC_CMD, GPSC_RSP_SIZE);
+ ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
+ GPSC_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_name */
@@ -1995,7 +1995,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
GFF_ID_RSP_SIZE);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFF_ID_CMD,
+ ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
GFF_ID_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 563eee3..f2216ed 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -25,7 +25,6 @@
*/
static int qla2x00_isp_firmware(scsi_qla_host_t *);
static int qla2x00_setup_chip(scsi_qla_host_t *);
-static int qla2x00_init_rings(scsi_qla_host_t *);
static int qla2x00_fw_ready(scsi_qla_host_t *);
static int qla2x00_configure_hba(scsi_qla_host_t *);
static int qla2x00_configure_loop(scsi_qla_host_t *);
@@ -70,9 +69,7 @@ qla2x00_sp_free(void *data, void *ptr)
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
del_timer(&iocb->timer);
- mempool_free(sp, vha->hw->srb_mempool);
-
- QLA_VHA_MARK_NOT_BUSY(vha);
+ qla2x00_rel_sp(vha, sp);
}
/* Asynchronous Login/Logout Routines -------------------------------------- */
@@ -85,7 +82,9 @@ qla2x00_get_async_timeout(struct scsi_qla_host *vha)
/* Firmware should use switch negotiated r_a_tov for timeout. */
tmo = ha->r_a_tov / 10 * 2;
- if (!IS_FWI2_CAPABLE(ha)) {
+ if (IS_QLAFX00(ha)) {
+ tmo = FX00_DEF_RATOV * 2;
+ } else if (!IS_FWI2_CAPABLE(ha)) {
/*
* Except for earlier ISPs where the timeout is seeded from the
* initialization control block.
@@ -525,7 +524,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
vha->flags.reset_active = 0;
ha->flags.pci_channel_io_perm_failure = 0;
ha->flags.eeh_busy = 0;
- ha->flags.thermal_supported = 1;
+ ha->thermal_support = THERMAL_SUPPORT_I2C|THERMAL_SUPPORT_ISP;
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
atomic_set(&vha->loop_state, LOOP_DOWN);
vha->device_flags = DFLG_NO_CABLE;
@@ -1399,7 +1398,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
mq_size += ha->max_rsp_queues *
(rsp->length * sizeof(response_t));
}
- if (ha->tgt.atio_q_length)
+ if (ha->tgt.atio_ring)
mq_size += ha->tgt.atio_q_length * sizeof(request_t);
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha))
@@ -1559,6 +1558,47 @@ done:
return rval;
}
+int
+qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
+{
+ /* Don't try to reallocate the array */
+ if (req->outstanding_cmds)
+ return QLA_SUCCESS;
+
+ if (!IS_FWI2_CAPABLE(ha) || (ha->mqiobase &&
+ (ql2xmultique_tag || ql2xmaxqueues > 1)))
+ req->num_outstanding_cmds = DEFAULT_OUTSTANDING_COMMANDS;
+ else {
+ if (ha->fw_xcb_count <= ha->fw_iocb_count)
+ req->num_outstanding_cmds = ha->fw_xcb_count;
+ else
+ req->num_outstanding_cmds = ha->fw_iocb_count;
+ }
+
+ req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
+ req->num_outstanding_cmds, GFP_KERNEL);
+
+ if (!req->outstanding_cmds) {
+ /*
+ * Try to allocate a minimal size just so we can get through
+ * initialization.
+ */
+ req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS;
+ req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
+ req->num_outstanding_cmds, GFP_KERNEL);
+
+ if (!req->outstanding_cmds) {
+ ql_log(ql_log_fatal, NULL, 0x0126,
+ "Failed to allocate memory for "
+ "outstanding_cmds for req_que %p.\n", req);
+ req->num_outstanding_cmds = 0;
+ return QLA_FUNCTION_FAILED;
+ }
+ }
+
+ return QLA_SUCCESS;
+}
+
/**
* qla2x00_setup_chip() - Load and start RISC firmware.
* @ha: HA context
@@ -1628,9 +1668,18 @@ enable_82xx_npiv:
MIN_MULTI_ID_FABRIC - 1;
}
qla2x00_get_resource_cnts(vha, NULL,
- &ha->fw_xcb_count, NULL, NULL,
+ &ha->fw_xcb_count, NULL, &ha->fw_iocb_count,
&ha->max_npiv_vports, NULL);
+ /*
+ * Allocate the array of outstanding commands
+ * now that we know the firmware resources.
+ */
+ rval = qla2x00_alloc_outstanding_cmds(ha,
+ vha->req);
+ if (rval != QLA_SUCCESS)
+ goto failed;
+
if (!fw_major_version && ql2xallocfwdump
&& !IS_QLA82XX(ha))
qla2x00_alloc_fw_dump(vha);
@@ -1914,7 +1963,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
}
- qlt_24xx_config_rings(vha, reg);
+ qlt_24xx_config_rings(vha);
/* PCI posting */
RD_REG_DWORD(&ioreg->hccr);
@@ -1929,7 +1978,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
*
* Returns 0 on success.
*/
-static int
+int
qla2x00_init_rings(scsi_qla_host_t *vha)
{
int rval;
@@ -1948,7 +1997,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
req = ha->req_q_map[que];
if (!req)
continue;
- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++)
req->outstanding_cmds[cnt] = NULL;
req->current_outstanding_cmd = 1;
@@ -1964,7 +2013,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
if (!rsp)
continue;
/* Initialize response queue entries */
- qla2x00_init_response_q_entries(rsp);
+ if (IS_QLAFX00(ha))
+ qlafx00_init_response_q_entries(rsp);
+ else
+ qla2x00_init_response_q_entries(rsp);
}
ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
@@ -1976,11 +2028,16 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
+
+ if (IS_QLAFX00(ha)) {
+ rval = qlafx00_init_firmware(vha, ha->init_cb_size);
+ goto next_check;
+ }
+
/* Update any ISP specific firmware options before initialization. */
ha->isp_ops->update_fw_options(vha);
- ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
-
if (ha->flags.npiv_supported) {
if (ha->operating_mode == LOOP && !IS_CNA_CAPABLE(ha))
ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
@@ -1994,6 +2051,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
}
rval = qla2x00_init_firmware(vha, ha->init_cb_size);
+next_check:
if (rval) {
ql_log(ql_log_fatal, vha, 0x00d2,
"Init Firmware **** FAILED ****.\n");
@@ -2021,6 +2079,9 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
uint16_t state[5];
struct qla_hw_data *ha = vha->hw;
+ if (IS_QLAFX00(vha->hw))
+ return qlafx00_fw_ready(vha);
+
rval = QLA_SUCCESS;
/* 20 seconds for loop down. */
@@ -2157,6 +2218,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
char connect_type[22];
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
+ scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
/* Get host addresses. */
rval = qla2x00_get_adapter_id(vha,
@@ -2170,6 +2232,13 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
} else {
ql_log(ql_log_warn, vha, 0x2009,
"Unable to get host loop ID.\n");
+ if (IS_FWI2_CAPABLE(ha) && (vha == base_vha) &&
+ (rval == QLA_COMMAND_ERROR && loop_id == 0x1b)) {
+ ql_log(ql_log_warn, vha, 0x1151,
+ "Doing link init.\n");
+ if (qla24xx_link_initialize(vha) == QLA_SUCCESS)
+ return rval;
+ }
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
}
return (rval);
@@ -2240,14 +2309,6 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
"Topology - %s, Host Loop address 0x%x.\n",
connect_type, vha->loop_id);
- if (rval) {
- ql_log(ql_log_warn, vha, 0x2011,
- "%s FAILED\n", __func__);
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x2012,
- "%s success\n", __func__);
- }
-
return(rval);
}
@@ -2690,7 +2751,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->loop_id = FC_NO_LOOP_ID;
qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
fcport->supported_classes = FC_COS_UNSPECIFIED;
- fcport->scan_state = QLA_FCPORT_SCAN_NONE;
return fcport;
}
@@ -3079,6 +3139,12 @@ void
qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
{
fcport->vha = vha;
+
+ if (IS_QLAFX00(vha->hw)) {
+ qla2x00_set_fcport_state(fcport, FCS_ONLINE);
+ qla2x00_reg_remote_port(vha, fcport);
+ return;
+ }
fcport->login_retry = 0;
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
@@ -3103,7 +3169,7 @@ static int
qla2x00_configure_fabric(scsi_qla_host_t *vha)
{
int rval;
- fc_port_t *fcport;
+ fc_port_t *fcport, *fcptemp;
uint16_t next_loopid;
uint16_t mb[MAILBOX_REGISTER_COUNT];
uint16_t loop_id;
@@ -3141,7 +3207,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
0xfc, mb, BIT_1|BIT_0);
if (rval != QLA_SUCCESS) {
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- break;
+ return rval;
}
if (mb[0] != MBS_COMMAND_COMPLETE) {
ql_dbg(ql_dbg_disc, vha, 0x2042,
@@ -3173,16 +3239,21 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
}
}
+#define QLA_FCPORT_SCAN 1
+#define QLA_FCPORT_FOUND 2
+
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ fcport->scan_state = QLA_FCPORT_SCAN;
+ }
+
rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
if (rval != QLA_SUCCESS)
break;
- /* Add new ports to existing port list */
- list_splice_tail_init(&new_fcports, &vha->vp_fcports);
-
- /* Starting free loop ID. */
- next_loopid = ha->min_external_loopid;
-
+ /*
+ * Logout all previous fabric devices marked lost, except
+ * FCP2 devices.
+ */
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break;
@@ -3190,8 +3261,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
continue;
- /* Logout lost/gone fabric devices (non-FCP2) */
- if (fcport->scan_state != QLA_FCPORT_SCAN_FOUND &&
+ if (fcport->scan_state == QLA_FCPORT_SCAN &&
atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport,
ql2xplogiabsentdevice, 0);
@@ -3204,30 +3274,74 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
fcport->d_id.b.domain,
fcport->d_id.b.area,
fcport->d_id.b.al_pa);
+ fcport->loop_id = FC_NO_LOOP_ID;
}
- continue;
}
- fcport->scan_state = QLA_FCPORT_SCAN_NONE;
-
- /* Login fabric devices that need a login */
- if ((fcport->flags & FCF_LOGIN_NEEDED) != 0 &&
- atomic_read(&vha->loop_down_timer) == 0) {
- if (fcport->loop_id == FC_NO_LOOP_ID) {
- fcport->loop_id = next_loopid;
- rval = qla2x00_find_new_loop_id(
- base_vha, fcport);
- if (rval != QLA_SUCCESS) {
- /* Ran out of IDs to use */
- continue;
- }
+ }
+
+ /* Starting free loop ID. */
+ next_loopid = ha->min_external_loopid;
+
+ /*
+ * Scan through our port list and login entries that need to be
+ * logged in.
+ */
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (atomic_read(&vha->loop_down_timer) ||
+ test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ break;
+
+ if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
+ (fcport->flags & FCF_LOGIN_NEEDED) == 0)
+ continue;
+
+ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ fcport->loop_id = next_loopid;
+ rval = qla2x00_find_new_loop_id(
+ base_vha, fcport);
+ if (rval != QLA_SUCCESS) {
+ /* Ran out of IDs to use */
+ break;
}
}
+ /* Login and update database */
+ qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
+ }
+
+ /* Exit if out of loop IDs. */
+ if (rval != QLA_SUCCESS) {
+ break;
+ }
+
+ /*
+ * Login and add the new devices to our port list.
+ */
+ list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
+ if (atomic_read(&vha->loop_down_timer) ||
+ test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ break;
+
+ /* Find a new loop ID to use. */
+ fcport->loop_id = next_loopid;
+ rval = qla2x00_find_new_loop_id(base_vha, fcport);
+ if (rval != QLA_SUCCESS) {
+ /* Ran out of IDs to use */
+ break;
+ }
/* Login and update database */
qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
+
+ list_move_tail(&fcport->list, &vha->vp_fcports);
}
} while (0);
+ /* Free all new device structures not processed. */
+ list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
+ list_del(&fcport->list);
+ kfree(fcport);
+ }
+
if (rval) {
ql_dbg(ql_dbg_disc, vha, 0x2068,
"Configure fabric error exit rval=%d.\n", rval);
@@ -3263,8 +3377,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
int first_dev, last_dev;
port_id_t wrap = {}, nxt_d_id;
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
- struct scsi_qla_host *tvp;
+ struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
rval = QLA_SUCCESS;
@@ -3377,22 +3490,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
continue;
/* Bypass virtual ports of the same host. */
- found = 0;
- if (ha->num_vhosts) {
- unsigned long flags;
-
- spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
- if (new_fcport->d_id.b24 == vp->d_id.b24) {
- found = 1;
- break;
- }
- }
- spin_unlock_irqrestore(&ha->vport_slock, flags);
-
- if (found)
- continue;
- }
+ if (qla2x00_is_a_vp_did(vha, new_fcport->d_id.b24))
+ continue;
/* Bypass if same domain and area of adapter. */
if (((new_fcport->d_id.b24 & 0xffff00) ==
@@ -3417,7 +3516,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
WWN_SIZE))
continue;
- fcport->scan_state = QLA_FCPORT_SCAN_FOUND;
+ fcport->scan_state = QLA_FCPORT_FOUND;
found++;
@@ -3806,15 +3905,24 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
/* Wait at most MAX_TARGET RSCNs for a stable link. */
wait_time = 256;
do {
- /* Issue a marker after FW becomes ready. */
- qla2x00_marker(vha, req, rsp, 0, 0,
- MK_SYNC_ALL);
- vha->marker_needed = 0;
+ if (!IS_QLAFX00(vha->hw)) {
+ /*
+ * Issue a marker after FW becomes
+ * ready.
+ */
+ qla2x00_marker(vha, req, rsp, 0, 0,
+ MK_SYNC_ALL);
+ vha->marker_needed = 0;
+ }
/* Remap devices on Loop. */
clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- qla2x00_configure_loop(vha);
+ if (IS_QLAFX00(vha->hw))
+ qlafx00_configure_devices(vha);
+ else
+ qla2x00_configure_loop(vha);
+
wait_time--;
} while (!atomic_read(&vha->loop_down_timer) &&
!(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
@@ -3880,9 +3988,7 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
if (fcport->drport &&
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
-
qla2x00_rport_del(fcport);
-
spin_lock_irqsave(&ha->vport_slock, flags);
}
}
@@ -5004,7 +5110,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
return rval;
}
-#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
+#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/"
int
qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
@@ -5529,6 +5635,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
if (IS_T10_PI_CAPABLE(ha))
nv->frame_payload_size &= ~7;
+ qlt_81xx_config_nvram_stage1(vha, nv);
+
/* Reset Initialization control block */
memset(icb, 0, ha->init_cb_size);
@@ -5569,6 +5677,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
"QLE8XXX");
+ qlt_81xx_config_nvram_stage2(vha, icb);
+
/* Use alternate WWN? */
if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index c0462c0..28c38b4 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -1,10 +1,32 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
+/**
+ * qla24xx_calc_iocbs() - Determine number of Command Type 3 and
+ * Continuation Type 1 IOCBs to allocate.
+ *
+ * @dsds: number of data segment decriptors needed
+ *
+ * Returns the number of IOCB entries needed to store @dsds.
+ */
+static inline uint16_t
+qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)
+{
+ uint16_t iocbs;
+
+ iocbs = 1;
+ if (dsds > 1) {
+ iocbs += (dsds - 1) / 5;
+ if ((dsds - 1) % 5)
+ iocbs++;
+ }
+ return iocbs;
+}
+
/*
* qla2x00_debounce_register
* Debounce register.
@@ -58,6 +80,17 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
}
static inline void
+host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize)
+{
+ uint32_t *isrc = (uint32_t *) src;
+ __le32 *odest = (__le32 *) dst;
+ uint32_t iter = bsize >> 2;
+
+ for (; iter ; iter--)
+ *odest++ = cpu_to_le32(*isrc++);
+}
+
+static inline void
qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
{
int i;
@@ -198,6 +231,13 @@ done:
}
static inline void
+qla2x00_rel_sp(scsi_qla_host_t *vha, srb_t *sp)
+{
+ mempool_free(sp, vha->hw->srb_mempool);
+ QLA_VHA_MARK_NOT_BUSY(vha);
+}
+
+static inline void
qla2x00_init_timer(srb_t *sp, unsigned long tmo)
{
init_timer(&sp->u.iocb_cmd.timer);
@@ -206,10 +246,46 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
add_timer(&sp->u.iocb_cmd.timer);
sp->free = qla2x00_sp_free;
+ if ((IS_QLAFX00(sp->fcport->vha->hw)) &&
+ (sp->type == SRB_FXIOCB_DCMD))
+ init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
}
static inline int
qla2x00_gid_list_size(struct qla_hw_data *ha)
{
- return sizeof(struct gid_list_info) * ha->max_fibre_devices;
+ if (IS_QLAFX00(ha))
+ return sizeof(uint32_t) * 32;
+ else
+ return sizeof(struct gid_list_info) * ha->max_fibre_devices;
+}
+
+static inline void
+qla2x00_do_host_ramp_up(scsi_qla_host_t *vha)
+{
+ if (vha->hw->cfg_lun_q_depth >= ql2xmaxqdepth)
+ return;
+
+ /* Wait at least HOST_QUEUE_RAMPDOWN_INTERVAL before ramping up */
+ if (time_before(jiffies, (vha->hw->host_last_rampdown_time +
+ HOST_QUEUE_RAMPDOWN_INTERVAL)))
+ return;
+
+ /* Wait at least HOST_QUEUE_RAMPUP_INTERVAL between each ramp up */
+ if (time_before(jiffies, (vha->hw->host_last_rampup_time +
+ HOST_QUEUE_RAMPUP_INTERVAL)))
+ return;
+
+ set_bit(HOST_RAMP_UP_QUEUE_DEPTH, &vha->dpc_flags);
+}
+
+static inline void
+qla2x00_handle_mbx_completion(struct qla_hw_data *ha, int status)
+{
+ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+ set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+ clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+ complete(&ha->mbx_intr_comp);
+ }
}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index a481684..42ef481 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -135,7 +135,8 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req)
cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
/* Load packet defaults. */
- *((uint32_t *)(&cont_pkt->entry_type)) =
+ *((uint32_t *)(&cont_pkt->entry_type)) = IS_QLAFX00(vha->hw) ?
+ __constant_cpu_to_le32(CONTINUE_A64_TYPE_FX00) :
__constant_cpu_to_le32(CONTINUE_A64_TYPE);
return (cont_pkt);
@@ -349,14 +350,14 @@ qla2x00_start_scsi(srb_t *sp)
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
handle++;
- if (handle == MAX_OUTSTANDING_COMMANDS)
+ if (handle == req->num_outstanding_cmds)
handle = 1;
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS)
+ if (index == req->num_outstanding_cmds)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -486,6 +487,10 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
if (ha->mqenable || IS_QLA83XX(ha)) {
WRT_REG_DWORD(req->req_q_in, req->ring_index);
RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
+ } else if (IS_QLAFX00(ha)) {
+ WRT_REG_DWORD(&reg->ispfx00.req_q_in, req->ring_index);
+ RD_REG_DWORD_RELAXED(&reg->ispfx00.req_q_in);
+ QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code);
} else if (IS_FWI2_CAPABLE(ha)) {
WRT_REG_DWORD(&reg->isp24.req_q_in, req->ring_index);
RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
@@ -514,11 +519,12 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
uint16_t lun, uint8_t type)
{
mrk_entry_t *mrk;
- struct mrk_entry_24xx *mrk24;
+ struct mrk_entry_24xx *mrk24 = NULL;
+ struct mrk_entry_fx00 *mrkfx = NULL;
+
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- mrk24 = NULL;
req = ha->req_q_map[0];
mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, NULL);
if (mrk == NULL) {
@@ -531,7 +537,15 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
mrk->entry_type = MARKER_TYPE;
mrk->modifier = type;
if (type != MK_SYNC_ALL) {
- if (IS_FWI2_CAPABLE(ha)) {
+ if (IS_QLAFX00(ha)) {
+ mrkfx = (struct mrk_entry_fx00 *) mrk;
+ mrkfx->handle = MAKE_HANDLE(req->id, mrkfx->handle);
+ mrkfx->handle_hi = 0;
+ mrkfx->tgt_id = cpu_to_le16(loop_id);
+ mrkfx->lun[1] = LSB(lun);
+ mrkfx->lun[2] = MSB(lun);
+ host_to_fcp_swap(mrkfx->lun, sizeof(mrkfx->lun));
+ } else if (IS_FWI2_CAPABLE(ha)) {
mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id);
mrk24->lun[1] = LSB(lun);
@@ -589,28 +603,6 @@ int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked)
return QLA_SUCCESS;
}
-/**
- * qla24xx_calc_iocbs() - Determine number of Command Type 3 and
- * Continuation Type 1 IOCBs to allocate.
- *
- * @dsds: number of data segment decriptors needed
- *
- * Returns the number of IOCB entries needed to store @dsds.
- */
-inline uint16_t
-qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)
-{
- uint16_t iocbs;
-
- iocbs = 1;
- if (dsds > 1) {
- iocbs += (dsds - 1) / 5;
- if ((dsds - 1) % 5)
- iocbs++;
- }
- return iocbs;
-}
-
static inline int
qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
uint16_t tot_dsds)
@@ -1197,7 +1189,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
uint32_t *cur_dsd, *fcp_dl;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
- struct scatterlist *cur_seg;
int sgc;
uint32_t total_bytes = 0;
uint32_t data_bytes;
@@ -1404,7 +1395,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
if (bundling && tot_prot_dsds) {
/* Walks dif segments */
- cur_seg = scsi_prot_sglist(cmd);
cmd_pkt->control_flags |=
__constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE);
cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
@@ -1467,16 +1457,15 @@ qla24xx_start_scsi(srb_t *sp)
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
handle++;
- if (handle == MAX_OUTSTANDING_COMMANDS)
+ if (handle == req->num_outstanding_cmds)
handle = 1;
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS) {
+ if (index == req->num_outstanding_cmds)
goto queuing_error;
- }
/* Map the sg table so we have an accurate count of sg entries needed */
if (scsi_sg_count(cmd)) {
@@ -1584,7 +1573,6 @@ queuing_error:
return QLA_FUNCTION_FAILED;
}
-
/**
* qla24xx_dif_start_scsi() - Send a SCSI command to the ISP
* @sp: command to send to the ISP
@@ -1641,15 +1629,15 @@ qla24xx_dif_start_scsi(srb_t *sp)
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
handle++;
- if (handle == MAX_OUTSTANDING_COMMANDS)
+ if (handle == req->num_outstanding_cmds)
handle = 1;
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS)
+ if (index == req->num_outstanding_cmds)
goto queuing_error;
/* Compute number of required data segments */
@@ -1822,14 +1810,14 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+ for (index = 1; req->num_outstanding_cmds; index++) {
handle++;
- if (handle == MAX_OUTSTANDING_COMMANDS)
+ if (handle == req->num_outstanding_cmds)
handle = 1;
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS) {
+ if (index == req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x700b,
"No room on outstanding cmd array.\n");
goto queuing_error;
@@ -1853,6 +1841,8 @@ skip_cmd_array:
cnt = RD_REG_DWORD(&reg->isp82.req_q_out);
else if (IS_FWI2_CAPABLE(ha))
cnt = RD_REG_DWORD(&reg->isp24.req_q_out);
+ else if (IS_QLAFX00(ha))
+ cnt = RD_REG_DWORD(&reg->ispfx00.req_q_out);
else
cnt = qla2x00_debounce_register(
ISP_REQ_Q_OUT(ha, &reg->isp));
@@ -1870,8 +1860,13 @@ skip_cmd_array:
req->cnt -= req_cnt;
pkt = req->ring_ptr;
memset(pkt, 0, REQUEST_ENTRY_SIZE);
- pkt->entry_count = req_cnt;
- pkt->handle = handle;
+ if (IS_QLAFX00(ha)) {
+ WRT_REG_BYTE((void __iomem *)&pkt->entry_count, req_cnt);
+ WRT_REG_WORD((void __iomem *)&pkt->handle, handle);
+ } else {
+ pkt->entry_count = req_cnt;
+ pkt->handle = handle;
+ }
queuing_error:
return pkt;
@@ -2263,14 +2258,14 @@ qla82xx_start_scsi(srb_t *sp)
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
handle++;
- if (handle == MAX_OUTSTANDING_COMMANDS)
+ if (handle == req->num_outstanding_cmds)
handle = 1;
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS)
+ if (index == req->num_outstanding_cmds)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -2626,7 +2621,16 @@ qla2x00_start_sp(srb_t *sp)
qla2x00_adisc_iocb(sp, pkt);
break;
case SRB_TM_CMD:
- qla24xx_tm_iocb(sp, pkt);
+ IS_QLAFX00(ha) ?
+ qlafx00_tm_iocb(sp, pkt) :
+ qla24xx_tm_iocb(sp, pkt);
+ break;
+ case SRB_FXIOCB_DCMD:
+ case SRB_FXIOCB_BCMD:
+ qlafx00_fxdisc_iocb(sp, pkt);
+ break;
+ case SRB_ABT_CMD:
+ qlafx00_abort_iocb(sp, pkt);
break;
default:
break;
@@ -2767,15 +2771,15 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
- for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
handle++;
- if (handle == MAX_OUTSTANDING_COMMANDS)
+ if (handle == req->num_outstanding_cmds)
handle = 1;
if (!req->outstanding_cmds[handle])
break;
}
- if (index == MAX_OUTSTANDING_COMMANDS) {
+ if (index == req->num_outstanding_cmds) {
rval = EXT_STATUS_BUSY;
goto queuing_error;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 873c820..2d8e7b8 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -14,8 +14,6 @@
#include <scsi/scsi_eh.h>
static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
-static void qla2x00_process_completed_request(struct scsi_qla_host *,
- struct req_que *, uint32_t);
static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
@@ -106,14 +104,9 @@ qla2100_intr_handler(int irq, void *dev_id)
RD_REG_WORD(&reg->hccr);
}
}
+ qla2x00_handle_mbx_completion(ha, status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
- set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- complete(&ha->mbx_intr_comp);
- }
-
return (IRQ_HANDLED);
}
@@ -223,14 +216,9 @@ qla2300_intr_handler(int irq, void *dev_id)
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD_RELAXED(&reg->hccr);
}
+ qla2x00_handle_mbx_completion(ha, status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
- set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- complete(&ha->mbx_intr_comp);
- }
-
return (IRQ_HANDLED);
}
@@ -489,10 +477,37 @@ qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
if (mb[1] & IDC_DEVICE_STATE_CHANGE) {
ql_log(ql_log_info, vha, 0x506a,
"IDC Device-State changed = 0x%x.\n", mb[4]);
+ if (ha->flags.nic_core_reset_owner)
+ return;
qla83xx_schedule_work(vha, MBA_IDC_AEN);
}
}
+int
+qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
+{
+ struct qla_hw_data *ha = vha->hw;
+ scsi_qla_host_t *vp;
+ uint32_t vp_did;
+ unsigned long flags;
+ int ret = 0;
+
+ if (!ha->num_vhosts)
+ return ret;
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_for_each_entry(vp, &ha->vp_list, list) {
+ vp_did = vp->d_id.b24;
+ if (vp_did == rscn_entry) {
+ ret = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+ return ret;
+}
+
/**
* qla2x00_async_event() - Process aynchronous events.
* @ha: SCSI driver HA context
@@ -899,6 +914,10 @@ skip_rio:
/* Ignore reserved bits from RSCN-payload. */
rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2];
+ /* Skip RSCNs for virtual ports on the same physical port */
+ if (qla2x00_is_a_vp_did(vha, rscn_entry))
+ break;
+
atomic_set(&vha->loop_down_timer, 0);
vha->flags.management_server_logged_in = 0;
@@ -983,14 +1002,25 @@ skip_rio:
mb[1], mb[2], mb[3]);
break;
case MBA_IDC_NOTIFY:
- /* See if we need to quiesce any I/O */
- if (IS_QLA8031(vha->hw))
- if ((mb[2] & 0x7fff) == MBC_PORT_RESET ||
- (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) {
+ if (IS_QLA8031(vha->hw)) {
+ mb[4] = RD_REG_WORD(&reg24->mailbox4);
+ if (((mb[2] & 0x7fff) == MBC_PORT_RESET ||
+ (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) &&
+ (mb[4] & INTERNAL_LOOPBACK_MASK) != 0) {
set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
+ /*
+ * Extend loop down timer since port is active.
+ */
+ if (atomic_read(&vha->loop_state) == LOOP_DOWN)
+ atomic_set(&vha->loop_down_timer,
+ LOOP_DOWN_TIME);
qla2xxx_wake_dpc(vha);
}
+ }
case MBA_IDC_COMPLETE:
+ if (ha->notify_lb_portup_comp)
+ complete(&ha->lb_portup_comp);
+ /* Fallthru */
case MBA_IDC_TIME_EXT:
if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw))
qla81xx_idc_event(vha, mb[0], mb[1]);
@@ -1021,15 +1051,15 @@ skip_rio:
* @ha: SCSI driver HA context
* @index: SRB index
*/
-static void
+void
qla2x00_process_completed_request(struct scsi_qla_host *vha,
- struct req_que *req, uint32_t index)
+ struct req_que *req, uint32_t index)
{
srb_t *sp;
struct qla_hw_data *ha = vha->hw;
/* Validate handle. */
- if (index >= MAX_OUTSTANDING_COMMANDS) {
+ if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x3014,
"Invalid SCSI command index (%x).\n", index);
@@ -1057,7 +1087,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
}
}
-static srb_t *
+srb_t *
qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
struct req_que *req, void *iocb)
{
@@ -1067,7 +1097,7 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
uint16_t index;
index = LSW(pkt->handle);
- if (index >= MAX_OUTSTANDING_COMMANDS) {
+ if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x5031,
"Invalid command index (%x).\n", index);
if (IS_QLA82XX(ha))
@@ -1740,7 +1770,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
sts24 = (struct sts_entry_24xx *) pkt;
/* Validate handle. */
- if (index >= MAX_OUTSTANDING_COMMANDS) {
+ if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x70af,
"Invalid SCSI completion handle 0x%x.\n", index);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -1910,9 +1940,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
req = ha->req_q_map[que];
/* Validate handle. */
- if (handle < MAX_OUTSTANDING_COMMANDS) {
+ if (handle < req->num_outstanding_cmds)
sp = req->outstanding_cmds[handle];
- } else
+ else
sp = NULL;
if (sp == NULL) {
@@ -1934,6 +1964,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
/* Fast path completion. */
if (comp_status == CS_COMPLETE && scsi_status == 0) {
+ qla2x00_do_host_ramp_up(vha);
qla2x00_process_completed_request(vha, req, handle);
return;
@@ -1949,7 +1980,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
return;
}
- lscsi_status = scsi_status & STATUS_MASK;
+ lscsi_status = scsi_status & STATUS_MASK;
fcport = sp->fcport;
@@ -2193,6 +2224,9 @@ out:
cp->cmnd[8], cp->cmnd[9], scsi_bufflen(cp), rsp_info_len,
resid_len, fw_resid_len);
+ if (!res)
+ qla2x00_do_host_ramp_up(vha);
+
if (rsp->status_srb == NULL)
sp->done(ha, sp, res);
}
@@ -2451,6 +2485,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha)
if (rval == QLA_SUCCESS)
goto next_test;
+ rval = QLA_SUCCESS;
WRT_REG_DWORD(&reg->iobase_window, 0x0003);
for (cnt = 100; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
rval == QLA_SUCCESS; cnt--) {
@@ -2569,14 +2604,9 @@ qla24xx_intr_handler(int irq, void *dev_id)
if (unlikely(IS_QLA83XX(ha) && (ha->pdev->revision == 1)))
ndelay(3500);
}
+ qla2x00_handle_mbx_completion(ha, status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
- set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- complete(&ha->mbx_intr_comp);
- }
-
return IRQ_HANDLED;
}
@@ -2719,13 +2749,9 @@ qla24xx_msix_default(int irq, void *dev_id)
}
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
} while (0);
+ qla2x00_handle_mbx_completion(ha, status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
- set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- complete(&ha->mbx_intr_comp);
- }
return IRQ_HANDLED;
}
@@ -2747,6 +2773,12 @@ static struct qla_init_msix_entry qla82xx_msix_entries[2] = {
{ "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
};
+static struct qla_init_msix_entry qla83xx_msix_entries[3] = {
+ { "qla2xxx (default)", qla24xx_msix_default },
+ { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
+ { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
+};
+
static void
qla24xx_disable_msix(struct qla_hw_data *ha)
{
@@ -2827,9 +2859,13 @@ msix_failed:
}
/* Enable MSI-X vectors for the base queue */
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ha->msix_count; i++) {
qentry = &ha->msix_entries[i];
- if (IS_QLA82XX(ha)) {
+ if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
+ ret = request_irq(qentry->vector,
+ qla83xx_msix_entries[i].handler,
+ 0, qla83xx_msix_entries[i].name, rsp);
+ } else if (IS_QLA82XX(ha)) {
ret = request_irq(qentry->vector,
qla82xx_msix_entries[i].handler,
0, qla82xx_msix_entries[i].name, rsp);
@@ -2881,7 +2917,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
/* If possible, enable MSI-X. */
if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
- !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha))
+ !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLAFX00(ha))
goto skip_msi;
if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
@@ -2914,7 +2950,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
skip_msix:
if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
- !IS_QLA8001(ha) && !IS_QLA82XX(ha))
+ !IS_QLA8001(ha) && !IS_QLA82XX(ha) && !IS_QLAFX00(ha))
goto skip_msi;
ret = pci_enable_msi(ha->pdev);
@@ -2940,9 +2976,11 @@ skip_msi:
"Failed to reserve interrupt %d already in use.\n",
ha->pdev->irq);
goto fail;
- } else if (!ha->flags.msi_enabled)
+ } else if (!ha->flags.msi_enabled) {
ql_dbg(ql_dbg_init, vha, 0x0125,
"INTa mode: Enabled.\n");
+ ha->flags.mr_intr_valid = 1;
+ }
clear_risc_ints:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 68c55ea..7257c3c 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -177,10 +177,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- wait_for_completion_timeout(&ha->mbx_intr_comp, mcp->tov * HZ);
-
- clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
-
+ if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
+ mcp->tov * HZ)) {
+ ql_dbg(ql_dbg_mbx, vha, 0x117a,
+ "cmd=%x Timeout.\n", command);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ }
} else {
ql_dbg(ql_dbg_mbx, vha, 0x1011,
"Cmd=%x Polling Mode.\n", command);
@@ -277,9 +281,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/*
* Attempt to capture a firmware dump for further analysis
- * of the current firmware state
+ * of the current firmware state. We do not need to do this
+ * if we are intentionally generating a dump.
*/
- ha->isp_ops->fw_dump(vha, 0);
+ if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
+ ha->isp_ops->fw_dump(vha, 0);
rval = QLA_FUNCTION_TIMEOUT;
}
@@ -900,13 +906,13 @@ qla2x00_abort_command(srb_t *sp)
"Entered %s.\n", __func__);
spin_lock_irqsave(&ha->hardware_lock, flags);
- for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
+ for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
if (req->outstanding_cmds[handle] == sp)
break;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (handle == MAX_OUTSTANDING_COMMANDS) {
+ if (handle == req->num_outstanding_cmds) {
/* command not found */
return QLA_FUNCTION_FAILED;
}
@@ -1633,6 +1639,54 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name,
}
/*
+ * qla24xx_link_initialization
+ * Issue link initialization mailbox command.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * TARGET_QUEUE_LOCK must be released.
+ * ADAPTER_STATE_LOCK must be released.
+ *
+ * Returns:
+ * qla2x00 local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+int
+qla24xx_link_initialize(scsi_qla_host_t *vha)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1152,
+ "Entered %s.\n", __func__);
+
+ if (!IS_FWI2_CAPABLE(vha->hw) || IS_CNA_CAPABLE(vha->hw))
+ return QLA_FUNCTION_FAILED;
+
+ mcp->mb[0] = MBC_LINK_INITIALIZATION;
+ mcp->mb[1] = BIT_6|BIT_4;
+ mcp->mb[2] = 0;
+ mcp->mb[3] = 0;
+ mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1153, "Failed=%x.\n", rval);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1154,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+/*
* qla2x00_lip_reset
* Issue LIP reset mailbox command.
*
@@ -2535,12 +2589,12 @@ qla24xx_abort_command(srb_t *sp)
"Entered %s.\n", __func__);
spin_lock_irqsave(&ha->hardware_lock, flags);
- for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
+ for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
if (req->outstanding_cmds[handle] == sp)
break;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (handle == MAX_OUTSTANDING_COMMANDS) {
+ if (handle == req->num_outstanding_cmds) {
/* Command not found. */
return QLA_FUNCTION_FAILED;
}
@@ -3093,6 +3147,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *vp;
unsigned long flags;
+ int found;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
"Entered %s.\n", __func__);
@@ -3128,13 +3183,17 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
return;
}
+ found = 0;
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list)
- if (vp_idx == vp->vp_idx)
+ list_for_each_entry(vp, &ha->vp_list, list) {
+ if (vp_idx == vp->vp_idx) {
+ found = 1;
break;
+ }
+ }
spin_unlock_irqrestore(&ha->vport_slock, flags);
- if (!vp)
+ if (!found)
return;
vp->d_id.b.domain = rptid_entry->port_id[2];
@@ -3813,6 +3872,39 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
return rval;
}
+static int
+qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_FWI2_CAPABLE(vha->hw))
+ return QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_GET_RNID_PARAMS;
+ mcp->mb[1] = RNID_TYPE_ASIC_TEMP << 8;
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+ *temp = mcp->mb[1];
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x115a,
+ "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
int
qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
@@ -4027,7 +4119,6 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t iter_cnt = 0x1;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f7,
"Entered %s.\n", __func__);
@@ -4053,8 +4144,8 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
mcp->mb[7] = MSW(MSD(mreq->rcv_dma));
/* Iteration count */
- mcp->mb[18] = LSW(iter_cnt);
- mcp->mb[19] = MSW(iter_cnt);
+ mcp->mb[18] = LSW(mreq->iteration_count);
+ mcp->mb[19] = MSW(mreq->iteration_count);
mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
@@ -4415,38 +4506,46 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
}
int
-qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
+qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp)
{
- int rval;
- uint8_t byte;
+ int rval = QLA_FUNCTION_FAILED;
struct qla_hw_data *ha = vha->hw;
+ uint8_t byte;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ca,
"Entered %s.\n", __func__);
- /* Integer part */
- rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1,
- BIT_13|BIT_12|BIT_0);
- if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0x10c9, "Failed=%x.\n", rval);
- ha->flags.thermal_supported = 0;
- goto fail;
+ if (ha->thermal_support & THERMAL_SUPPORT_I2C) {
+ rval = qla2x00_read_sfp(vha, 0, &byte,
+ 0x98, 0x1, 1, BIT_13|BIT_12|BIT_0);
+ *temp = byte;
+ if (rval == QLA_SUCCESS)
+ goto done;
+
+ ql_log(ql_log_warn, vha, 0x10c9,
+ "Thermal not supported through I2C bus, trying alternate "
+ "method (ISP access).\n");
+ ha->thermal_support &= ~THERMAL_SUPPORT_I2C;
}
- *temp = byte;
- /* Fraction part */
- rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x10, 1,
- BIT_13|BIT_12|BIT_0);
- if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0x1019, "Failed=%x.\n", rval);
- ha->flags.thermal_supported = 0;
- goto fail;
+ if (ha->thermal_support & THERMAL_SUPPORT_ISP) {
+ rval = qla2x00_read_asic_temperature(vha, temp);
+ if (rval == QLA_SUCCESS)
+ goto done;
+
+ ql_log(ql_log_warn, vha, 0x1019,
+ "Thermal not supported through ISP.\n");
+ ha->thermal_support &= ~THERMAL_SUPPORT_ISP;
}
- *frac = (byte >> 6) * 25;
+ ql_log(ql_log_warn, vha, 0x1150,
+ "Thermal not supported by this card "
+ "(ignoring further requests).\n");
+ return rval;
+
+done:
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1018,
"Done %s.\n", __func__);
-fail:
return rval;
}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 20fd974..f868a9f 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -523,6 +523,7 @@ qla25xx_free_req_que(struct scsi_qla_host *vha, struct req_que *req)
clear_bit(que_id, ha->req_qid_map);
mutex_unlock(&ha->vport_lock);
}
+ kfree(req->outstanding_cmds);
kfree(req);
req = NULL;
}
@@ -649,6 +650,10 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
goto que_failed;
}
+ ret = qla2x00_alloc_outstanding_cmds(ha, req);
+ if (ret != QLA_SUCCESS)
+ goto que_failed;
+
mutex_lock(&ha->vport_lock);
que_id = find_first_zero_bit(ha->req_qid_map, ha->max_req_queues);
if (que_id >= ha->max_req_queues) {
@@ -685,7 +690,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
"options=0x%x.\n", req->options);
ql_dbg(ql_dbg_init, base_vha, 0x00dd,
"options=0x%x.\n", req->options);
- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++)
req->outstanding_cmds[cnt] = NULL;
req->current_outstanding_cmd = 1;
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
new file mode 100644
index 0000000..d799379
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -0,0 +1,3475 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2013 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include "qla_def.h"
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ratelimit.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_tcq.h>
+#include <linux/utsname.h>
+
+
+/* QLAFX00 specific Mailbox implementation functions */
+
+/*
+ * qlafx00_mailbox_command
+ * Issue mailbox command and waits for completion.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * mcp = driver internal mbx struct pointer.
+ *
+ * Output:
+ * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data.
+ *
+ * Returns:
+ * 0 : QLA_SUCCESS = cmd performed success
+ * 1 : QLA_FUNCTION_FAILED (error encountered)
+ * 6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered)
+ *
+ * Context:
+ * Kernel context.
+ */
+static int
+qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp)
+
+{
+ int rval;
+ unsigned long flags = 0;
+ device_reg_t __iomem *reg;
+ uint8_t abort_active;
+ uint8_t io_lock_on;
+ uint16_t command = 0;
+ uint32_t *iptr;
+ uint32_t __iomem *optr;
+ uint32_t cnt;
+ uint32_t mboxes;
+ unsigned long wait_time;
+ struct qla_hw_data *ha = vha->hw;
+ scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+
+ if (ha->pdev->error_state > pci_channel_io_frozen) {
+ ql_log(ql_log_warn, vha, 0x115c,
+ "error_state is greater than pci_channel_io_frozen, "
+ "exiting.\n");
+ return QLA_FUNCTION_TIMEOUT;
+ }
+
+ if (vha->device_flags & DFLG_DEV_FAILED) {
+ ql_log(ql_log_warn, vha, 0x115f,
+ "Device in failed state, exiting.\n");
+ return QLA_FUNCTION_TIMEOUT;
+ }
+
+ reg = ha->iobase;
+ io_lock_on = base_vha->flags.init_done;
+
+ rval = QLA_SUCCESS;
+ abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+
+ if (ha->flags.pci_channel_io_perm_failure) {
+ ql_log(ql_log_warn, vha, 0x1175,
+ "Perm failure on EEH timeout MBX, exiting.\n");
+ return QLA_FUNCTION_TIMEOUT;
+ }
+
+ if (ha->flags.isp82xx_fw_hung) {
+ /* Setting Link-Down error */
+ mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+ ql_log(ql_log_warn, vha, 0x1176,
+ "FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
+ rval = QLA_FUNCTION_FAILED;
+ goto premature_exit;
+ }
+
+ /*
+ * Wait for active mailbox commands to finish by waiting at most tov
+ * seconds. This is to serialize actual issuing of mailbox cmds during
+ * non ISP abort time.
+ */
+ if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
+ /* Timeout occurred. Return error. */
+ ql_log(ql_log_warn, vha, 0x1177,
+ "Cmd access timeout, cmd=0x%x, Exiting.\n",
+ mcp->mb[0]);
+ return QLA_FUNCTION_TIMEOUT;
+ }
+
+ ha->flags.mbox_busy = 1;
+ /* Save mailbox command for debug */
+ ha->mcp32 = mcp;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1178,
+ "Prepare to issue mbox cmd=0x%x.\n", mcp->mb[0]);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ /* Load mailbox registers. */
+ optr = (uint32_t __iomem *)&reg->ispfx00.mailbox0;
+
+ iptr = mcp->mb;
+ command = mcp->mb[0];
+ mboxes = mcp->out_mb;
+
+ for (cnt = 0; cnt < ha->mbx_count; cnt++) {
+ if (mboxes & BIT_0)
+ WRT_REG_DWORD(optr, *iptr);
+
+ mboxes >>= 1;
+ optr++;
+ iptr++;
+ }
+
+ /* Issue set host interrupt command to send cmd out. */
+ ha->flags.mbox_int = 0;
+ clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1172,
+ (uint8_t *)mcp->mb, 16);
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1173,
+ ((uint8_t *)mcp->mb + 0x10), 16);
+ ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1174,
+ ((uint8_t *)mcp->mb + 0x20), 8);
+
+ /* Unlock mbx registers and wait for interrupt */
+ ql_dbg(ql_dbg_mbx, vha, 0x1179,
+ "Going to unlock irq & waiting for interrupts. "
+ "jiffies=%lx.\n", jiffies);
+
+ /* Wait for mbx cmd completion until timeout */
+ if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
+ set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+
+ QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ wait_for_completion_timeout(&ha->mbx_intr_comp, mcp->tov * HZ);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x112c,
+ "Cmd=%x Polling Mode.\n", command);
+
+ QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
+ while (!ha->flags.mbox_int) {
+ if (time_after(jiffies, wait_time))
+ break;
+
+ /* Check for pending interrupts. */
+ qla2x00_poll(ha->rsp_q_map[0]);
+
+ if (!ha->flags.mbox_int &&
+ !(IS_QLA2200(ha) &&
+ command == MBC_LOAD_RISC_RAM_EXTENDED))
+ usleep_range(10000, 11000);
+ } /* while */
+ ql_dbg(ql_dbg_mbx, vha, 0x112d,
+ "Waited %d sec.\n",
+ (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
+ }
+
+ /* Check whether we timed out */
+ if (ha->flags.mbox_int) {
+ uint32_t *iptr2;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x112e,
+ "Cmd=%x completed.\n", command);
+
+ /* Got interrupt. Clear the flag. */
+ ha->flags.mbox_int = 0;
+ clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+
+ if (ha->mailbox_out32[0] != MBS_COMMAND_COMPLETE)
+ rval = QLA_FUNCTION_FAILED;
+
+ /* Load return mailbox registers. */
+ iptr2 = mcp->mb;
+ iptr = (uint32_t *)&ha->mailbox_out32[0];
+ mboxes = mcp->in_mb;
+ for (cnt = 0; cnt < ha->mbx_count; cnt++) {
+ if (mboxes & BIT_0)
+ *iptr2 = *iptr;
+
+ mboxes >>= 1;
+ iptr2++;
+ iptr++;
+ }
+ } else {
+
+ rval = QLA_FUNCTION_TIMEOUT;
+ }
+
+ ha->flags.mbox_busy = 0;
+
+ /* Clean up */
+ ha->mcp32 = NULL;
+
+ if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
+ ql_dbg(ql_dbg_mbx, vha, 0x113a,
+ "checking for additional resp interrupt.\n");
+
+ /* polling mode for non isp_abort commands. */
+ qla2x00_poll(ha->rsp_q_map[0]);
+ }
+
+ if (rval == QLA_FUNCTION_TIMEOUT &&
+ mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) {
+ if (!io_lock_on || (mcp->flags & IOCTL_CMD) ||
+ ha->flags.eeh_busy) {
+ /* not in dpc. schedule it for dpc to take over. */
+ ql_dbg(ql_dbg_mbx, vha, 0x115d,
+ "Timeout, schedule isp_abort_needed.\n");
+
+ if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
+ !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+ !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+
+ ql_log(ql_log_info, base_vha, 0x115e,
+ "Mailbox cmd timeout occurred, cmd=0x%x, "
+ "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP "
+ "abort.\n", command, mcp->mb[0],
+ ha->flags.eeh_busy);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ }
+ } else if (!abort_active) {
+ /* call abort directly since we are in the DPC thread */
+ ql_dbg(ql_dbg_mbx, vha, 0x1160,
+ "Timeout, calling abort_isp.\n");
+
+ if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
+ !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+ !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+
+ ql_log(ql_log_info, base_vha, 0x1161,
+ "Mailbox cmd timeout occurred, cmd=0x%x, "
+ "mb[0]=0x%x. Scheduling ISP abort ",
+ command, mcp->mb[0]);
+
+ set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
+ clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ if (ha->isp_ops->abort_isp(vha)) {
+ /* Failed. retry later. */
+ set_bit(ISP_ABORT_NEEDED,
+ &vha->dpc_flags);
+ }
+ clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
+ ql_dbg(ql_dbg_mbx, vha, 0x1162,
+ "Finished abort_isp.\n");
+ }
+ }
+ }
+
+premature_exit:
+ /* Allow next mbx cmd to come in. */
+ complete(&ha->mbx_cmd_comp);
+
+ if (rval) {
+ ql_log(ql_log_warn, base_vha, 0x1163,
+ "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, "
+ "mb[3]=%x, cmd=%x ****.\n",
+ mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command);
+ } else {
+ ql_dbg(ql_dbg_mbx, base_vha, 0x1164, "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+/*
+ * qlafx00_driver_shutdown
+ * Indicate a driver shutdown to firmware.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ *
+ * Returns:
+ * local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+static int
+qlafx00_driver_shutdown(scsi_qla_host_t *vha, int tmo)
+{
+ int rval;
+ struct mbx_cmd_32 mc;
+ struct mbx_cmd_32 *mcp = &mc;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1166,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_MR_DRV_SHUTDOWN;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_0;
+ if (tmo)
+ mcp->tov = tmo;
+ else
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qlafx00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1167,
+ "Failed=%x.\n", rval);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1168,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+/*
+ * qlafx00_get_firmware_state
+ * Get adapter firmware state.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * TARGET_QUEUE_LOCK must be released.
+ * ADAPTER_STATE_LOCK must be released.
+ *
+ * Returns:
+ * qla7xxx local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+static int
+qlafx00_get_firmware_state(scsi_qla_host_t *vha, uint32_t *states)
+{
+ int rval;
+ struct mbx_cmd_32 mc;
+ struct mbx_cmd_32 *mcp = &mc;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1169,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qlafx00_mailbox_command(vha, mcp);
+
+ /* Return firmware states. */
+ states[0] = mcp->mb[1];
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x116a,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116b,
+ "Done %s.\n", __func__);
+ }
+ return rval;
+}
+
+/*
+ * qlafx00_init_firmware
+ * Initialize adapter firmware.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * dptr = Initialization control block pointer.
+ * size = size of initialization control block.
+ * TARGET_QUEUE_LOCK must be released.
+ * ADAPTER_STATE_LOCK must be released.
+ *
+ * Returns:
+ * qlafx00 local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+int
+qlafx00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
+{
+ int rval;
+ struct mbx_cmd_32 mc;
+ struct mbx_cmd_32 *mcp = &mc;
+ struct qla_hw_data *ha = vha->hw;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116c,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
+
+ mcp->mb[1] = 0;
+ mcp->mb[2] = MSD(ha->init_cb_dma);
+ mcp->mb[3] = LSD(ha->init_cb_dma);
+
+ mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->buf_size = size;
+ mcp->flags = MBX_DMA_OUT;
+ mcp->tov = MBX_TOV_SECONDS;
+ rval = qlafx00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x116d,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116e,
+ "Done %s.\n", __func__);
+ }
+ return rval;
+}
+
+/*
+ * qlafx00_mbx_reg_test
+ */
+static int
+qlafx00_mbx_reg_test(scsi_qla_host_t *vha)
+{
+ int rval;
+ struct mbx_cmd_32 mc;
+ struct mbx_cmd_32 *mcp = &mc;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x116f,
+ "Entered %s.\n", __func__);
+
+
+ mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
+ mcp->mb[1] = 0xAAAA;
+ mcp->mb[2] = 0x5555;
+ mcp->mb[3] = 0xAA55;
+ mcp->mb[4] = 0x55AA;
+ mcp->mb[5] = 0xA5A5;
+ mcp->mb[6] = 0x5A5A;
+ mcp->mb[7] = 0x2525;
+ mcp->mb[8] = 0xBBBB;
+ mcp->mb[9] = 0x6666;
+ mcp->mb[10] = 0xBB66;
+ mcp->mb[11] = 0x66BB;
+ mcp->mb[12] = 0xB6B6;
+ mcp->mb[13] = 0x6B6B;
+ mcp->mb[14] = 0x3636;
+ mcp->mb[15] = 0xCCCC;
+
+
+ mcp->out_mb = MBX_15|MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
+ MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_15|MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
+ MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->buf_size = 0;
+ mcp->flags = MBX_DMA_OUT;
+ mcp->tov = MBX_TOV_SECONDS;
+ rval = qlafx00_mailbox_command(vha, mcp);
+ if (rval == QLA_SUCCESS) {
+ if (mcp->mb[17] != 0xAAAA || mcp->mb[18] != 0x5555 ||
+ mcp->mb[19] != 0xAA55 || mcp->mb[20] != 0x55AA)
+ rval = QLA_FUNCTION_FAILED;
+ if (mcp->mb[21] != 0xA5A5 || mcp->mb[22] != 0x5A5A ||
+ mcp->mb[23] != 0x2525 || mcp->mb[24] != 0xBBBB)
+ rval = QLA_FUNCTION_FAILED;
+ if (mcp->mb[25] != 0x6666 || mcp->mb[26] != 0xBB66 ||
+ mcp->mb[27] != 0x66BB || mcp->mb[28] != 0xB6B6)
+ rval = QLA_FUNCTION_FAILED;
+ if (mcp->mb[29] != 0x6B6B || mcp->mb[30] != 0x3636 ||
+ mcp->mb[31] != 0xCCCC)
+ rval = QLA_FUNCTION_FAILED;
+ }
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1170,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1171,
+ "Done %s.\n", __func__);
+ }
+ return rval;
+}
+
+/**
+ * qlafx00_pci_config() - Setup ISPFx00 PCI configuration registers.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+int
+qlafx00_pci_config(scsi_qla_host_t *vha)
+{
+ uint16_t w;
+ struct qla_hw_data *ha = vha->hw;
+
+ pci_set_master(ha->pdev);
+ pci_try_set_mwi(ha->pdev);
+
+ pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
+ w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+ w &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(ha->pdev, PCI_COMMAND, w);
+
+ /* PCIe -- adjust Maximum Read Request Size (2048). */
+ if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
+ pcie_set_readrq(ha->pdev, 2048);
+
+ ha->chip_revision = ha->pdev->revision;
+
+ return QLA_SUCCESS;
+}
+
+/**
+ * qlafx00_warm_reset() - Perform warm reset of iSA(CPUs being reset on SOC).
+ * @ha: HA context
+ *
+ */
+static inline void
+qlafx00_soc_cpu_reset(scsi_qla_host_t *vha)
+{
+ unsigned long flags = 0;
+ struct qla_hw_data *ha = vha->hw;
+ int i, core;
+ uint32_t cnt;
+
+ /* Set all 4 cores in reset */
+ for (i = 0; i < 4; i++) {
+ QLAFX00_SET_HBA_SOC_REG(ha,
+ (SOC_SW_RST_CONTROL_REG_CORE0 + 8*i), (0xF01));
+ }
+
+ /* Set all 4 core Clock gating control */
+ for (i = 0; i < 4; i++) {
+ QLAFX00_SET_HBA_SOC_REG(ha,
+ (SOC_SW_RST_CONTROL_REG_CORE0 + 4 + 8*i), (0x01010101));
+ }
+
+ /* Reset all units in Fabric */
+ QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_RST_CONTROL_REG, (0x11F0101));
+
+ /* Reset all interrupt control registers */
+ for (i = 0; i < 115; i++) {
+ QLAFX00_SET_HBA_SOC_REG(ha,
+ (SOC_INTERRUPT_SOURCE_I_CONTROL_REG + 4*i), (0x0));
+ }
+
+ /* Reset Timers control registers. per core */
+ for (core = 0; core < 4; core++)
+ for (i = 0; i < 8; i++)
+ QLAFX00_SET_HBA_SOC_REG(ha,
+ (SOC_CORE_TIMER_REG + 0x100*core + 4*i), (0x0));
+
+ /* Reset per core IRQ ack register */
+ for (core = 0; core < 4; core++)
+ QLAFX00_SET_HBA_SOC_REG(ha,
+ (SOC_IRQ_ACK_REG + 0x100*core), (0x3FF));
+
+ /* Set Fabric control and config to defaults */
+ QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_CONTROL_REG, (0x2));
+ QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_CONFIG_REG, (0x3));
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ /* Kick in Fabric units */
+ QLAFX00_SET_HBA_SOC_REG(ha, SOC_FABRIC_RST_CONTROL_REG, (0x0));
+
+ /* Kick in Core0 to start boot process */
+ QLAFX00_SET_HBA_SOC_REG(ha, SOC_SW_RST_CONTROL_REG_CORE0, (0xF00));
+
+ /* Wait 10secs for soft-reset to complete. */
+ for (cnt = 10; cnt; cnt--) {
+ msleep(1000);
+ barrier();
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+/**
+ * qlafx00_soft_reset() - Soft Reset ISPFx00.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+void
+qlafx00_soft_reset(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (unlikely(pci_channel_offline(ha->pdev) &&
+ ha->flags.pci_channel_io_perm_failure))
+ return;
+
+ ha->isp_ops->disable_intrs(ha);
+ qlafx00_soc_cpu_reset(vha);
+ ha->isp_ops->enable_intrs(ha);
+}
+
+/**
+ * qlafx00_chip_diag() - Test ISPFx00 for proper operation.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+int
+qlafx00_chip_diag(scsi_qla_host_t *vha)
+{
+ int rval = 0;
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = ha->req_q_map[0];
+
+ ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length;
+
+ rval = qlafx00_mbx_reg_test(vha);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x1165,
+ "Failed mailbox send register test\n");
+ } else {
+ /* Flag a successful rval */
+ rval = QLA_SUCCESS;
+ }
+ return rval;
+}
+
+void
+qlafx00_config_rings(struct scsi_qla_host *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
+ struct init_cb_fx *icb;
+ struct req_que *req = ha->req_q_map[0];
+ struct rsp_que *rsp = ha->rsp_q_map[0];
+
+ /* Setup ring parameters in initialization control block. */
+ icb = (struct init_cb_fx *)ha->init_cb;
+ icb->request_q_outpointer = __constant_cpu_to_le16(0);
+ icb->response_q_inpointer = __constant_cpu_to_le16(0);
+ icb->request_q_length = cpu_to_le16(req->length);
+ icb->response_q_length = cpu_to_le16(rsp->length);
+ icb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
+ icb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
+ icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
+ icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
+
+ WRT_REG_DWORD(&reg->req_q_in, 0);
+ WRT_REG_DWORD(&reg->req_q_out, 0);
+
+ WRT_REG_DWORD(&reg->rsp_q_in, 0);
+ WRT_REG_DWORD(&reg->rsp_q_out, 0);
+
+ /* PCI posting */
+ RD_REG_DWORD(&reg->rsp_q_out);
+}
+
+char *
+qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int pcie_reg;
+
+ pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
+ if (pcie_reg) {
+ strcpy(str, "PCIe iSA");
+ return str;
+ }
+ return str;
+}
+
+char *
+qlafx00_fw_version_str(struct scsi_qla_host *vha, char *str)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ sprintf(str, "%s", ha->mr.fw_version);
+ return str;
+}
+
+void
+qlafx00_enable_intrs(struct qla_hw_data *ha)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ ha->interrupts_on = 1;
+ QLAFX00_ENABLE_ICNTRL_REG(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+void
+qlafx00_disable_intrs(struct qla_hw_data *ha)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ ha->interrupts_on = 0;
+ QLAFX00_DISABLE_ICNTRL_REG(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+static void
+qlafx00_tmf_iocb_timeout(void *data)
+{
+ srb_t *sp = (srb_t *)data;
+ struct srb_iocb *tmf = &sp->u.iocb_cmd;
+
+ tmf->u.tmf.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT);
+ complete(&tmf->u.tmf.comp);
+}
+
+static void
+qlafx00_tmf_sp_done(void *data, void *ptr, int res)
+{
+ srb_t *sp = (srb_t *)ptr;
+ struct srb_iocb *tmf = &sp->u.iocb_cmd;
+
+ complete(&tmf->u.tmf.comp);
+}
+
+static int
+qlafx00_async_tm_cmd(fc_port_t *fcport, uint32_t flags,
+ uint32_t lun, uint32_t tag)
+{
+ scsi_qla_host_t *vha = fcport->vha;
+ struct srb_iocb *tm_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ tm_iocb = &sp->u.iocb_cmd;
+ sp->type = SRB_TM_CMD;
+ sp->name = "tmf";
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
+ tm_iocb->u.tmf.flags = flags;
+ tm_iocb->u.tmf.lun = lun;
+ tm_iocb->u.tmf.data = tag;
+ sp->done = qlafx00_tmf_sp_done;
+ tm_iocb->timeout = qlafx00_tmf_iocb_timeout;
+ init_completion(&tm_iocb->u.tmf.comp);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
+ ql_dbg(ql_dbg_async, vha, 0x507b,
+ "Task management command issued target_id=%x\n",
+ fcport->tgt_id);
+
+ wait_for_completion(&tm_iocb->u.tmf.comp);
+
+ rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ?
+ QLA_SUCCESS : QLA_FUNCTION_FAILED;
+
+done_free_sp:
+ sp->free(vha, sp);
+done:
+ return rval;
+}
+
+int
+qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag)
+{
+ return qlafx00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
+}
+
+int
+qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag)
+{
+ return qlafx00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
+}
+
+int
+qlafx00_iospace_config(struct qla_hw_data *ha)
+{
+ if (pci_request_selected_regions(ha->pdev, ha->bars,
+ QLA2XXX_DRIVER_NAME)) {
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x014e,
+ "Failed to reserve PIO/MMIO regions (%s), aborting.\n",
+ pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+
+ /* Use MMIO operations for all accesses. */
+ if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) {
+ ql_log_pci(ql_log_warn, ha->pdev, 0x014f,
+ "Invalid pci I/O region size (%s).\n",
+ pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+ if (pci_resource_len(ha->pdev, 0) < BAR0_LEN_FX00) {
+ ql_log_pci(ql_log_warn, ha->pdev, 0x0127,
+ "Invalid PCI mem BAR0 region size (%s), aborting\n",
+ pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+
+ ha->cregbase =
+ ioremap_nocache(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00);
+ if (!ha->cregbase) {
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0128,
+ "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+
+ if (!(pci_resource_flags(ha->pdev, 2) & IORESOURCE_MEM)) {
+ ql_log_pci(ql_log_warn, ha->pdev, 0x0129,
+ "region #2 not an MMIO resource (%s), aborting\n",
+ pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+ if (pci_resource_len(ha->pdev, 2) < BAR2_LEN_FX00) {
+ ql_log_pci(ql_log_warn, ha->pdev, 0x012a,
+ "Invalid PCI mem BAR2 region size (%s), aborting\n",
+ pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+
+ ha->iobase =
+ ioremap_nocache(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00);
+ if (!ha->iobase) {
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x012b,
+ "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
+ goto iospace_error_exit;
+ }
+
+ /* Determine queue resources */
+ ha->max_req_queues = ha->max_rsp_queues = 1;
+
+ ql_log_pci(ql_log_info, ha->pdev, 0x012c,
+ "Bars 0x%x, iobase0 0x%p, iobase2 0x%p\n",
+ ha->bars, ha->cregbase, ha->iobase);
+
+ return 0;
+
+iospace_error_exit:
+ return -ENOMEM;
+}
+
+static void
+qlafx00_save_queue_ptrs(struct scsi_qla_host *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = ha->req_q_map[0];
+ struct rsp_que *rsp = ha->rsp_q_map[0];
+
+ req->length_fx00 = req->length;
+ req->ring_fx00 = req->ring;
+ req->dma_fx00 = req->dma;
+
+ rsp->length_fx00 = rsp->length;
+ rsp->ring_fx00 = rsp->ring;
+ rsp->dma_fx00 = rsp->dma;
+
+ ql_dbg(ql_dbg_init, vha, 0x012d,
+ "req: %p, ring_fx00: %p, length_fx00: 0x%x,"
+ "req->dma_fx00: 0x%llx\n", req, req->ring_fx00,
+ req->length_fx00, (u64)req->dma_fx00);
+
+ ql_dbg(ql_dbg_init, vha, 0x012e,
+ "rsp: %p, ring_fx00: %p, length_fx00: 0x%x,"
+ "rsp->dma_fx00: 0x%llx\n", rsp, rsp->ring_fx00,
+ rsp->length_fx00, (u64)rsp->dma_fx00);
+}
+
+static int
+qlafx00_config_queues(struct scsi_qla_host *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = ha->req_q_map[0];
+ struct rsp_que *rsp = ha->rsp_q_map[0];
+ dma_addr_t bar2_hdl = pci_resource_start(ha->pdev, 2);
+
+ req->length = ha->req_que_len;
+ req->ring = (void *)ha->iobase + ha->req_que_off;
+ req->dma = bar2_hdl + ha->req_que_off;
+ if ((!req->ring) || (req->length == 0)) {
+ ql_log_pci(ql_log_info, ha->pdev, 0x012f,
+ "Unable to allocate memory for req_ring\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ ql_dbg(ql_dbg_init, vha, 0x0130,
+ "req: %p req_ring pointer %p req len 0x%x "
+ "req off 0x%x\n, req->dma: 0x%llx",
+ req, req->ring, req->length,
+ ha->req_que_off, (u64)req->dma);
+
+ rsp->length = ha->rsp_que_len;
+ rsp->ring = (void *)ha->iobase + ha->rsp_que_off;
+ rsp->dma = bar2_hdl + ha->rsp_que_off;
+ if ((!rsp->ring) || (rsp->length == 0)) {
+ ql_log_pci(ql_log_info, ha->pdev, 0x0131,
+ "Unable to allocate memory for rsp_ring\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ ql_dbg(ql_dbg_init, vha, 0x0132,
+ "rsp: %p rsp_ring pointer %p rsp len 0x%x "
+ "rsp off 0x%x, rsp->dma: 0x%llx\n",
+ rsp, rsp->ring, rsp->length,
+ ha->rsp_que_off, (u64)rsp->dma);
+
+ return QLA_SUCCESS;
+}
+
+static int
+qlafx00_init_fw_ready(scsi_qla_host_t *vha)
+{
+ int rval = 0;
+ unsigned long wtime;
+ uint16_t wait_time; /* Wait time */
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
+ uint32_t aenmbx, aenmbx7 = 0;
+ uint32_t state[5];
+ bool done = false;
+
+ /* 30 seconds wait - Adjust if required */
+ wait_time = 30;
+
+ /* wait time before firmware ready */
+ wtime = jiffies + (wait_time * HZ);
+ do {
+ aenmbx = RD_REG_DWORD(&reg->aenmailbox0);
+ barrier();
+ ql_dbg(ql_dbg_mbx, vha, 0x0133,
+ "aenmbx: 0x%x\n", aenmbx);
+
+ switch (aenmbx) {
+ case MBA_FW_NOT_STARTED:
+ case MBA_FW_STARTING:
+ break;
+
+ case MBA_SYSTEM_ERR:
+ case MBA_REQ_TRANSFER_ERR:
+ case MBA_RSP_TRANSFER_ERR:
+ case MBA_FW_INIT_FAILURE:
+ qlafx00_soft_reset(vha);
+ break;
+
+ case MBA_FW_RESTART_CMPLT:
+ /* Set the mbx and rqstq intr code */
+ aenmbx7 = RD_REG_DWORD(&reg->aenmailbox7);
+ ha->mbx_intr_code = MSW(aenmbx7);
+ ha->rqstq_intr_code = LSW(aenmbx7);
+ ha->req_que_off = RD_REG_DWORD(&reg->aenmailbox1);
+ ha->rsp_que_off = RD_REG_DWORD(&reg->aenmailbox3);
+ ha->req_que_len = RD_REG_DWORD(&reg->aenmailbox5);
+ ha->rsp_que_len = RD_REG_DWORD(&reg->aenmailbox6);
+ WRT_REG_DWORD(&reg->aenmailbox0, 0);
+ RD_REG_DWORD_RELAXED(&reg->aenmailbox0);
+ ql_dbg(ql_dbg_init, vha, 0x0134,
+ "f/w returned mbx_intr_code: 0x%x, "
+ "rqstq_intr_code: 0x%x\n",
+ ha->mbx_intr_code, ha->rqstq_intr_code);
+ QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
+ rval = QLA_SUCCESS;
+ done = true;
+ break;
+
+ default:
+ /* If fw is apparently not ready. In order to continue,
+ * we might need to issue Mbox cmd, but the problem is
+ * that the DoorBell vector values that come with the
+ * 8060 AEN are most likely gone by now (and thus no
+ * bell would be rung on the fw side when mbox cmd is
+ * issued). We have to therefore grab the 8060 AEN
+ * shadow regs (filled in by FW when the last 8060
+ * AEN was being posted).
+ * Do the following to determine what is needed in
+ * order to get the FW ready:
+ * 1. reload the 8060 AEN values from the shadow regs
+ * 2. clear int status to get rid of possible pending
+ * interrupts
+ * 3. issue Get FW State Mbox cmd to determine fw state
+ * Set the mbx and rqstq intr code from Shadow Regs
+ */
+ aenmbx7 = RD_REG_DWORD(&reg->initval7);
+ ha->mbx_intr_code = MSW(aenmbx7);
+ ha->rqstq_intr_code = LSW(aenmbx7);
+ ha->req_que_off = RD_REG_DWORD(&reg->initval1);
+ ha->rsp_que_off = RD_REG_DWORD(&reg->initval3);
+ ha->req_que_len = RD_REG_DWORD(&reg->initval5);
+ ha->rsp_que_len = RD_REG_DWORD(&reg->initval6);
+ ql_dbg(ql_dbg_init, vha, 0x0135,
+ "f/w returned mbx_intr_code: 0x%x, "
+ "rqstq_intr_code: 0x%x\n",
+ ha->mbx_intr_code, ha->rqstq_intr_code);
+ QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
+
+ /* Get the FW state */
+ rval = qlafx00_get_firmware_state(vha, state);
+ if (rval != QLA_SUCCESS) {
+ /* Retry if timer has not expired */
+ break;
+ }
+
+ if (state[0] == FSTATE_FX00_CONFIG_WAIT) {
+ /* Firmware is waiting to be
+ * initialized by driver
+ */
+ rval = QLA_SUCCESS;
+ done = true;
+ break;
+ }
+
+ /* Issue driver shutdown and wait until f/w recovers.
+ * Driver should continue to poll until 8060 AEN is
+ * received indicating firmware recovery.
+ */
+ ql_dbg(ql_dbg_init, vha, 0x0136,
+ "Sending Driver shutdown fw_state 0x%x\n",
+ state[0]);
+
+ rval = qlafx00_driver_shutdown(vha, 10);
+ if (rval != QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
+ msleep(500);
+
+ wtime = jiffies + (wait_time * HZ);
+ break;
+ }
+
+ if (!done) {
+ if (time_after_eq(jiffies, wtime)) {
+ ql_dbg(ql_dbg_init, vha, 0x0137,
+ "Init f/w failed: aen[7]: 0x%x\n",
+ RD_REG_DWORD(&reg->aenmailbox7));
+ rval = QLA_FUNCTION_FAILED;
+ done = true;
+ break;
+ }
+ /* Delay for a while */
+ msleep(500);
+ }
+ } while (!done);
+
+ if (rval)
+ ql_dbg(ql_dbg_init, vha, 0x0138,
+ "%s **** FAILED ****.\n", __func__);
+ else
+ ql_dbg(ql_dbg_init, vha, 0x0139,
+ "%s **** SUCCESS ****.\n", __func__);
+
+ return rval;
+}
+
+/*
+ * qlafx00_fw_ready() - Waits for firmware ready.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+int
+qlafx00_fw_ready(scsi_qla_host_t *vha)
+{
+ int rval;
+ unsigned long wtime;
+ uint16_t wait_time; /* Wait time if loop is coming ready */
+ uint32_t state[5];
+
+ rval = QLA_SUCCESS;
+
+ wait_time = 10;
+
+ /* wait time before firmware ready */
+ wtime = jiffies + (wait_time * HZ);
+
+ /* Wait for ISP to finish init */
+ if (!vha->flags.init_done)
+ ql_dbg(ql_dbg_init, vha, 0x013a,
+ "Waiting for init to complete...\n");
+
+ do {
+ rval = qlafx00_get_firmware_state(vha, state);
+
+ if (rval == QLA_SUCCESS) {
+ if (state[0] == FSTATE_FX00_INITIALIZED) {
+ ql_dbg(ql_dbg_init, vha, 0x013b,
+ "fw_state=%x\n", state[0]);
+ rval = QLA_SUCCESS;
+ break;
+ }
+ }
+ rval = QLA_FUNCTION_FAILED;
+
+ if (time_after_eq(jiffies, wtime))
+ break;
+
+ /* Delay for a while */
+ msleep(500);
+
+ ql_dbg(ql_dbg_init, vha, 0x013c,
+ "fw_state=%x curr time=%lx.\n", state[0], jiffies);
+ } while (1);
+
+
+ if (rval)
+ ql_dbg(ql_dbg_init, vha, 0x013d,
+ "Firmware ready **** FAILED ****.\n");
+ else
+ ql_dbg(ql_dbg_init, vha, 0x013e,
+ "Firmware ready **** SUCCESS ****.\n");
+
+ return rval;
+}
+
+static int
+qlafx00_find_all_targets(scsi_qla_host_t *vha,
+ struct list_head *new_fcports)
+{
+ int rval;
+ uint16_t tgt_id;
+ fc_port_t *fcport, *new_fcport;
+ int found;
+ struct qla_hw_data *ha = vha->hw;
+
+ rval = QLA_SUCCESS;
+
+ if (!test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
+ return QLA_FUNCTION_FAILED;
+
+ if ((atomic_read(&vha->loop_down_timer) ||
+ STATE_TRANSITION(vha))) {
+ atomic_set(&vha->loop_down_timer, 0);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ return QLA_FUNCTION_FAILED;
+ }
+
+ ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x2088,
+ "Listing Target bit map...\n");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha,
+ 0x2089, (uint8_t *)ha->gid_list, 32);
+
+ /* Allocate temporary rmtport for any new rmtports discovered. */
+ new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
+ if (new_fcport == NULL)
+ return QLA_MEMORY_ALLOC_FAILED;
+
+ for_each_set_bit(tgt_id, (void *)ha->gid_list,
+ QLAFX00_TGT_NODE_LIST_SIZE) {
+
+ /* Send get target node info */
+ new_fcport->tgt_id = tgt_id;
+ rval = qlafx00_fx_disc(vha, new_fcport,
+ FXDISC_GET_TGT_NODE_INFO);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x208a,
+ "Target info scan failed -- assuming zero-entry "
+ "result...\n");
+ continue;
+ }
+
+ /* Locate matching device in database. */
+ found = 0;
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (memcmp(new_fcport->port_name,
+ fcport->port_name, WWN_SIZE))
+ continue;
+
+ found++;
+
+ /*
+ * If tgt_id is same and state FCS_ONLINE, nothing
+ * changed.
+ */
+ if (fcport->tgt_id == new_fcport->tgt_id &&
+ atomic_read(&fcport->state) == FCS_ONLINE)
+ break;
+
+ /*
+ * Tgt ID changed or device was marked to be updated.
+ */
+ ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x208b,
+ "TGT-ID Change(%s): Present tgt id: "
+ "0x%x state: 0x%x "
+ "wwnn = %llx wwpn = %llx.\n",
+ __func__, fcport->tgt_id,
+ atomic_read(&fcport->state),
+ (unsigned long long)wwn_to_u64(fcport->node_name),
+ (unsigned long long)wwn_to_u64(fcport->port_name));
+
+ ql_log(ql_log_info, vha, 0x208c,
+ "TGT-ID Announce(%s): Discovered tgt "
+ "id 0x%x wwnn = %llx "
+ "wwpn = %llx.\n", __func__, new_fcport->tgt_id,
+ (unsigned long long)
+ wwn_to_u64(new_fcport->node_name),
+ (unsigned long long)
+ wwn_to_u64(new_fcport->port_name));
+
+ if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ fcport->old_tgt_id = fcport->tgt_id;
+ fcport->tgt_id = new_fcport->tgt_id;
+ ql_log(ql_log_info, vha, 0x208d,
+ "TGT-ID: New fcport Added: %p\n", fcport);
+ qla2x00_update_fcport(vha, fcport);
+ } else {
+ ql_log(ql_log_info, vha, 0x208e,
+ " Existing TGT-ID %x did not get "
+ " offline event from firmware.\n",
+ fcport->old_tgt_id);
+ qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ kfree(new_fcport);
+ return rval;
+ }
+ break;
+ }
+
+ if (found)
+ continue;
+
+ /* If device was not in our fcports list, then add it. */
+ list_add_tail(&new_fcport->list, new_fcports);
+
+ /* Allocate a new replacement fcport. */
+ new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
+ if (new_fcport == NULL)
+ return QLA_MEMORY_ALLOC_FAILED;
+ }
+
+ kfree(new_fcport);
+ return rval;
+}
+
+/*
+ * qlafx00_configure_all_targets
+ * Setup target devices with node ID's.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ *
+ * Returns:
+ * 0 = success.
+ * BIT_0 = error
+ */
+static int
+qlafx00_configure_all_targets(scsi_qla_host_t *vha)
+{
+ int rval;
+ fc_port_t *fcport, *rmptemp;
+ LIST_HEAD(new_fcports);
+
+ rval = qlafx00_fx_disc(vha, &vha->hw->mr.fcport,
+ FXDISC_GET_TGT_NODE_LIST);
+ if (rval != QLA_SUCCESS) {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ return rval;
+ }
+
+ rval = qlafx00_find_all_targets(vha, &new_fcports);
+ if (rval != QLA_SUCCESS) {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ return rval;
+ }
+
+ /*
+ * Delete all previous devices marked lost.
+ */
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ break;
+
+ if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
+ if (fcport->port_type != FCT_INITIATOR)
+ qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ }
+ }
+
+ /*
+ * Add the new devices to our devices list.
+ */
+ list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) {
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ break;
+
+ qla2x00_update_fcport(vha, fcport);
+ list_move_tail(&fcport->list, &vha->vp_fcports);
+ ql_log(ql_log_info, vha, 0x208f,
+ "Attach new target id 0x%x wwnn = %llx "
+ "wwpn = %llx.\n",
+ fcport->tgt_id,
+ (unsigned long long)wwn_to_u64(fcport->node_name),
+ (unsigned long long)wwn_to_u64(fcport->port_name));
+ }
+
+ /* Free all new device structures not processed. */
+ list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) {
+ list_del(&fcport->list);
+ kfree(fcport);
+ }
+
+ return rval;
+}
+
+/*
+ * qlafx00_configure_devices
+ * Updates Fibre Channel Device Database with what is actually on loop.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ *
+ * Returns:
+ * 0 = success.
+ * 1 = error.
+ * 2 = database was full and device was not configured.
+ */
+int
+qlafx00_configure_devices(scsi_qla_host_t *vha)
+{
+ int rval;
+ unsigned long flags, save_flags;
+ rval = QLA_SUCCESS;
+
+ save_flags = flags = vha->dpc_flags;
+
+ ql_dbg(ql_dbg_disc, vha, 0x2090,
+ "Configure devices -- dpc flags =0x%lx\n", flags);
+
+ rval = qlafx00_configure_all_targets(vha);
+
+ if (rval == QLA_SUCCESS) {
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ atomic_set(&vha->loop_state, LOOP_READY);
+ ql_log(ql_log_info, vha, 0x2091,
+ "Device Ready\n");
+ }
+ }
+
+ if (rval) {
+ ql_dbg(ql_dbg_disc, vha, 0x2092,
+ "%s *** FAILED ***.\n", __func__);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0x2093,
+ "%s: exiting normally.\n", __func__);
+ }
+ return rval;
+}
+
+static void
+qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ fc_port_t *fcport;
+
+ vha->flags.online = 0;
+ ha->flags.chip_reset_done = 0;
+ ha->mr.fw_hbt_en = 0;
+ clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ vha->qla_stats.total_isp_aborts++;
+
+ ql_log(ql_log_info, vha, 0x013f,
+ "Performing ISP error recovery - ha = %p.\n", ha);
+
+ ha->isp_ops->reset_chip(vha);
+
+ if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
+ atomic_set(&vha->loop_state, LOOP_DOWN);
+ atomic_set(&vha->loop_down_timer,
+ QLAFX00_LOOP_DOWN_TIME);
+ } else {
+ if (!atomic_read(&vha->loop_down_timer))
+ atomic_set(&vha->loop_down_timer,
+ QLAFX00_LOOP_DOWN_TIME);
+ }
+
+ /* Clear all async request states across all VPs. */
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ fcport->flags = 0;
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
+ }
+
+ if (!ha->flags.eeh_busy) {
+ /* Requeue all commands in outstanding command list. */
+ qla2x00_abort_all_cmds(vha, DID_RESET << 16);
+ }
+
+ qla2x00_free_irqs(vha);
+ set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
+
+ /* Clear the Interrupts */
+ QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
+
+ ql_log(ql_log_info, vha, 0x0140,
+ "%s Done done - ha=%p.\n", __func__, ha);
+}
+
+/**
+ * qlafx00_init_response_q_entries() - Initializes response queue entries.
+ * @ha: HA context
+ *
+ * Beginning of request ring has initialization control block already built
+ * by nvram config routine.
+ *
+ * Returns 0 on success.
+ */
+void
+qlafx00_init_response_q_entries(struct rsp_que *rsp)
+{
+ uint16_t cnt;
+ response_t *pkt;
+
+ rsp->ring_ptr = rsp->ring;
+ rsp->ring_index = 0;
+ rsp->status_srb = NULL;
+ pkt = rsp->ring_ptr;
+ for (cnt = 0; cnt < rsp->length; cnt++) {
+ pkt->signature = RESPONSE_PROCESSED;
+ WRT_REG_DWORD((void __iomem *)&pkt->signature,
+ RESPONSE_PROCESSED);
+ pkt++;
+ }
+}
+
+int
+qlafx00_rescan_isp(scsi_qla_host_t *vha)
+{
+ uint32_t status = QLA_FUNCTION_FAILED;
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
+ uint32_t aenmbx7;
+
+ qla2x00_request_irqs(ha, ha->rsp_q_map[0]);
+
+ aenmbx7 = RD_REG_DWORD(&reg->aenmailbox7);
+ ha->mbx_intr_code = MSW(aenmbx7);
+ ha->rqstq_intr_code = LSW(aenmbx7);
+ ha->req_que_off = RD_REG_DWORD(&reg->aenmailbox1);
+ ha->rsp_que_off = RD_REG_DWORD(&reg->aenmailbox3);
+ ha->req_que_len = RD_REG_DWORD(&reg->aenmailbox5);
+ ha->rsp_que_len = RD_REG_DWORD(&reg->aenmailbox6);
+
+ ql_dbg(ql_dbg_disc, vha, 0x2094,
+ "fw returned mbx_intr_code: 0x%x, rqstq_intr_code: 0x%x "
+ " Req que offset 0x%x Rsp que offset 0x%x\n",
+ ha->mbx_intr_code, ha->rqstq_intr_code,
+ ha->req_que_off, ha->rsp_que_len);
+
+ /* Clear the Interrupts */
+ QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
+
+ status = qla2x00_init_rings(vha);
+ if (!status) {
+ vha->flags.online = 1;
+
+ /* if no cable then assume it's good */
+ if ((vha->device_flags & DFLG_NO_CABLE))
+ status = 0;
+ /* Register system information */
+ if (qlafx00_fx_disc(vha,
+ &vha->hw->mr.fcport, FXDISC_REG_HOST_INFO))
+ ql_dbg(ql_dbg_disc, vha, 0x2095,
+ "failed to register host info\n");
+ }
+ scsi_unblock_requests(vha->host);
+ return status;
+}
+
+void
+qlafx00_timer_routine(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t fw_heart_beat;
+ uint32_t aenmbx0;
+ struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
+
+ /* Check firmware health */
+ if (ha->mr.fw_hbt_cnt)
+ ha->mr.fw_hbt_cnt--;
+ else {
+ if ((!ha->flags.mr_reset_hdlr_active) &&
+ (!test_bit(UNLOADING, &vha->dpc_flags)) &&
+ (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
+ (ha->mr.fw_hbt_en)) {
+ fw_heart_beat = RD_REG_DWORD(&reg->fwheartbeat);
+ if (fw_heart_beat != ha->mr.old_fw_hbt_cnt) {
+ ha->mr.old_fw_hbt_cnt = fw_heart_beat;
+ ha->mr.fw_hbt_miss_cnt = 0;
+ } else {
+ ha->mr.fw_hbt_miss_cnt++;
+ if (ha->mr.fw_hbt_miss_cnt ==
+ QLAFX00_HEARTBEAT_MISS_CNT) {
+ set_bit(ISP_ABORT_NEEDED,
+ &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ ha->mr.fw_hbt_miss_cnt = 0;
+ }
+ }
+ }
+ ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
+ }
+
+ if (test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags)) {
+ /* Reset recovery to be performed in timer routine */
+ aenmbx0 = RD_REG_DWORD(&reg->aenmailbox0);
+ if (ha->mr.fw_reset_timer_exp) {
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ ha->mr.fw_reset_timer_exp = 0;
+ } else if (aenmbx0 == MBA_FW_RESTART_CMPLT) {
+ /* Wake up DPC to rescan the targets */
+ set_bit(FX00_TARGET_SCAN, &vha->dpc_flags);
+ clear_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
+ } else if ((aenmbx0 == MBA_FW_STARTING) &&
+ (!ha->mr.fw_hbt_en)) {
+ ha->mr.fw_hbt_en = 1;
+ } else if (!ha->mr.fw_reset_timer_tick) {
+ if (aenmbx0 == ha->mr.old_aenmbx0_state)
+ ha->mr.fw_reset_timer_exp = 1;
+ ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
+ } else if (aenmbx0 == 0xFFFFFFFF) {
+ uint32_t data0, data1;
+
+ data0 = QLAFX00_RD_REG(ha,
+ QLAFX00_BAR1_BASE_ADDR_REG);
+ data1 = QLAFX00_RD_REG(ha,
+ QLAFX00_PEX0_WIN0_BASE_ADDR_REG);
+
+ data0 &= 0xffff0000;
+ data1 &= 0x0000ffff;
+
+ QLAFX00_WR_REG(ha,
+ QLAFX00_PEX0_WIN0_BASE_ADDR_REG,
+ (data0 | data1));
+ } else if ((aenmbx0 & 0xFF00) == MBA_FW_POLL_STATE) {
+ ha->mr.fw_reset_timer_tick =
+ QLAFX00_MAX_RESET_INTERVAL;
+ }
+ ha->mr.old_aenmbx0_state = aenmbx0;
+ ha->mr.fw_reset_timer_tick--;
+ }
+}
+
+/*
+ * qlfx00a_reset_initialize
+ * Re-initialize after a iSA device reset.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ *
+ * Returns:
+ * 0 = success
+ */
+int
+qlafx00_reset_initialize(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (vha->device_flags & DFLG_DEV_FAILED) {
+ ql_dbg(ql_dbg_init, vha, 0x0142,
+ "Device in failed state\n");
+ return QLA_SUCCESS;
+ }
+
+ ha->flags.mr_reset_hdlr_active = 1;
+
+ if (vha->flags.online) {
+ scsi_block_requests(vha->host);
+ qlafx00_abort_isp_cleanup(vha);
+ }
+
+ ql_log(ql_log_info, vha, 0x0143,
+ "(%s): succeeded.\n", __func__);
+ ha->flags.mr_reset_hdlr_active = 0;
+ return QLA_SUCCESS;
+}
+
+/*
+ * qlafx00_abort_isp
+ * Resets ISP and aborts all outstanding commands.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ *
+ * Returns:
+ * 0 = success
+ */
+int
+qlafx00_abort_isp(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (vha->flags.online) {
+ if (unlikely(pci_channel_offline(ha->pdev) &&
+ ha->flags.pci_channel_io_perm_failure)) {
+ clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
+ return QLA_SUCCESS;
+ }
+
+ scsi_block_requests(vha->host);
+ qlafx00_abort_isp_cleanup(vha);
+ }
+
+ ql_log(ql_log_info, vha, 0x0145,
+ "(%s): succeeded.\n", __func__);
+
+ return QLA_SUCCESS;
+}
+
+static inline fc_port_t*
+qlafx00_get_fcport(struct scsi_qla_host *vha, int tgt_id)
+{
+ fc_port_t *fcport;
+
+ /* Check for matching device in remote port list. */
+ fcport = NULL;
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->tgt_id == tgt_id) {
+ ql_dbg(ql_dbg_async, vha, 0x5072,
+ "Matching fcport(%p) found with TGT-ID: 0x%x "
+ "and Remote TGT_ID: 0x%x\n",
+ fcport, fcport->tgt_id, tgt_id);
+ break;
+ }
+ }
+ return fcport;
+}
+
+static void
+qlafx00_tgt_detach(struct scsi_qla_host *vha, int tgt_id)
+{
+ fc_port_t *fcport;
+
+ ql_log(ql_log_info, vha, 0x5073,
+ "Detach TGT-ID: 0x%x\n", tgt_id);
+
+ fcport = qlafx00_get_fcport(vha, tgt_id);
+ if (!fcport)
+ return;
+
+ qla2x00_mark_device_lost(vha, fcport, 0, 0);
+
+ return;
+}
+
+int
+qlafx00_process_aen(struct scsi_qla_host *vha, struct qla_work_evt *evt)
+{
+ int rval = 0;
+ uint32_t aen_code, aen_data;
+
+ aen_code = FCH_EVT_VENDOR_UNIQUE;
+ aen_data = evt->u.aenfx.evtcode;
+
+ switch (evt->u.aenfx.evtcode) {
+ case QLAFX00_MBA_PORT_UPDATE: /* Port database update */
+ if (evt->u.aenfx.mbx[1] == 0) {
+ if (evt->u.aenfx.mbx[2] == 1) {
+ if (!vha->flags.fw_tgt_reported)
+ vha->flags.fw_tgt_reported = 1;
+ atomic_set(&vha->loop_down_timer, 0);
+ atomic_set(&vha->loop_state, LOOP_UP);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ } else if (evt->u.aenfx.mbx[2] == 2) {
+ qlafx00_tgt_detach(vha, evt->u.aenfx.mbx[3]);
+ }
+ } else if (evt->u.aenfx.mbx[1] == 0xffff) {
+ if (evt->u.aenfx.mbx[2] == 1) {
+ if (!vha->flags.fw_tgt_reported)
+ vha->flags.fw_tgt_reported = 1;
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ } else if (evt->u.aenfx.mbx[2] == 2) {
+ vha->device_flags |= DFLG_NO_CABLE;
+ qla2x00_mark_all_devices_lost(vha, 1);
+ }
+ }
+ break;
+ case QLAFX00_MBA_LINK_UP:
+ aen_code = FCH_EVT_LINKUP;
+ aen_data = 0;
+ break;
+ case QLAFX00_MBA_LINK_DOWN:
+ aen_code = FCH_EVT_LINKDOWN;
+ aen_data = 0;
+ break;
+ }
+
+ fc_host_post_event(vha->host, fc_get_event_number(),
+ aen_code, aen_data);
+
+ return rval;
+}
+
+static void
+qlafx00_update_host_attr(scsi_qla_host_t *vha, struct port_info_data *pinfo)
+{
+ u64 port_name = 0, node_name = 0;
+
+ port_name = (unsigned long long)wwn_to_u64(pinfo->port_name);
+ node_name = (unsigned long long)wwn_to_u64(pinfo->node_name);
+
+ fc_host_node_name(vha->host) = node_name;
+ fc_host_port_name(vha->host) = port_name;
+ if (!pinfo->port_type)
+ vha->hw->current_topology = ISP_CFG_F;
+ if (pinfo->link_status == QLAFX00_LINK_STATUS_UP)
+ atomic_set(&vha->loop_state, LOOP_READY);
+ else if (pinfo->link_status == QLAFX00_LINK_STATUS_DOWN)
+ atomic_set(&vha->loop_state, LOOP_DOWN);
+ vha->hw->link_data_rate = (uint16_t)pinfo->link_config;
+}
+
+static void
+qla2x00_fxdisc_iocb_timeout(void *data)
+{
+ srb_t *sp = (srb_t *)data;
+ struct srb_iocb *lio = &sp->u.iocb_cmd;
+
+ complete(&lio->u.fxiocb.fxiocb_comp);
+}
+
+static void
+qla2x00_fxdisc_sp_done(void *data, void *ptr, int res)
+{
+ srb_t *sp = (srb_t *)ptr;
+ struct srb_iocb *lio = &sp->u.iocb_cmd;
+
+ complete(&lio->u.fxiocb.fxiocb_comp);
+}
+
+int
+qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
+{
+ srb_t *sp;
+ struct srb_iocb *fdisc;
+ int rval = QLA_FUNCTION_FAILED;
+ struct qla_hw_data *ha = vha->hw;
+ struct host_system_info *phost_info;
+ struct register_host_info *preg_hsi;
+ struct new_utsname *p_sysid = NULL;
+ struct timeval tv;
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ fdisc = &sp->u.iocb_cmd;
+ switch (fx_type) {
+ case FXDISC_GET_CONFIG_INFO:
+ fdisc->u.fxiocb.flags =
+ SRB_FXDISC_RESP_DMA_VALID;
+ fdisc->u.fxiocb.rsp_len = sizeof(struct config_info_data);
+ break;
+ case FXDISC_GET_PORT_INFO:
+ fdisc->u.fxiocb.flags =
+ SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID;
+ fdisc->u.fxiocb.rsp_len = QLAFX00_PORT_DATA_INFO;
+ fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->port_id);
+ break;
+ case FXDISC_GET_TGT_NODE_INFO:
+ fdisc->u.fxiocb.flags =
+ SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID;
+ fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_INFO;
+ fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->tgt_id);
+ break;
+ case FXDISC_GET_TGT_NODE_LIST:
+ fdisc->u.fxiocb.flags =
+ SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID;
+ fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_LIST_SIZE;
+ break;
+ case FXDISC_REG_HOST_INFO:
+ fdisc->u.fxiocb.flags = SRB_FXDISC_REQ_DMA_VALID;
+ fdisc->u.fxiocb.req_len = sizeof(struct register_host_info);
+ p_sysid = utsname();
+ if (!p_sysid) {
+ ql_log(ql_log_warn, vha, 0x303c,
+ "Not able to get the system informtion\n");
+ goto done_free_sp;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (fdisc->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) {
+ fdisc->u.fxiocb.req_addr = dma_alloc_coherent(&ha->pdev->dev,
+ fdisc->u.fxiocb.req_len,
+ &fdisc->u.fxiocb.req_dma_handle, GFP_KERNEL);
+ if (!fdisc->u.fxiocb.req_addr)
+ goto done_free_sp;
+
+ if (fx_type == FXDISC_REG_HOST_INFO) {
+ preg_hsi = (struct register_host_info *)
+ fdisc->u.fxiocb.req_addr;
+ phost_info = &preg_hsi->hsi;
+ memset(preg_hsi, 0, sizeof(struct register_host_info));
+ phost_info->os_type = OS_TYPE_LINUX;
+ strncpy(phost_info->sysname,
+ p_sysid->sysname, SYSNAME_LENGTH);
+ strncpy(phost_info->nodename,
+ p_sysid->nodename, NODENAME_LENGTH);
+ strncpy(phost_info->release,
+ p_sysid->release, RELEASE_LENGTH);
+ strncpy(phost_info->version,
+ p_sysid->version, VERSION_LENGTH);
+ strncpy(phost_info->machine,
+ p_sysid->machine, MACHINE_LENGTH);
+ strncpy(phost_info->domainname,
+ p_sysid->domainname, DOMNAME_LENGTH);
+ strncpy(phost_info->hostdriver,
+ QLA2XXX_VERSION, VERSION_LENGTH);
+ do_gettimeofday(&tv);
+ preg_hsi->utc = (uint64_t)tv.tv_sec;
+ ql_dbg(ql_dbg_init, vha, 0x0149,
+ "ISP%04X: Host registration with firmware\n",
+ ha->pdev->device);
+ ql_dbg(ql_dbg_init, vha, 0x014a,
+ "os_type = '%d', sysname = '%s', nodname = '%s'\n",
+ phost_info->os_type,
+ phost_info->sysname,
+ phost_info->nodename);
+ ql_dbg(ql_dbg_init, vha, 0x014b,
+ "release = '%s', version = '%s'\n",
+ phost_info->release,
+ phost_info->version);
+ ql_dbg(ql_dbg_init, vha, 0x014c,
+ "machine = '%s' "
+ "domainname = '%s', hostdriver = '%s'\n",
+ phost_info->machine,
+ phost_info->domainname,
+ phost_info->hostdriver);
+ ql_dump_buffer(ql_dbg_init + ql_dbg_disc, vha, 0x014d,
+ (uint8_t *)phost_info,
+ sizeof(struct host_system_info));
+ }
+ }
+
+ if (fdisc->u.fxiocb.flags & SRB_FXDISC_RESP_DMA_VALID) {
+ fdisc->u.fxiocb.rsp_addr = dma_alloc_coherent(&ha->pdev->dev,
+ fdisc->u.fxiocb.rsp_len,
+ &fdisc->u.fxiocb.rsp_dma_handle, GFP_KERNEL);
+ if (!fdisc->u.fxiocb.rsp_addr)
+ goto done_unmap_req;
+ }
+
+ sp->type = SRB_FXIOCB_DCMD;
+ sp->name = "fxdisc";
+ qla2x00_init_timer(sp, FXDISC_TIMEOUT);
+ fdisc->timeout = qla2x00_fxdisc_iocb_timeout;
+ fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type);
+ sp->done = qla2x00_fxdisc_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_unmap_dma;
+
+ wait_for_completion(&fdisc->u.fxiocb.fxiocb_comp);
+
+ if (fx_type == FXDISC_GET_CONFIG_INFO) {
+ struct config_info_data *pinfo =
+ (struct config_info_data *) fdisc->u.fxiocb.rsp_addr;
+ memcpy(&vha->hw->mr.product_name, pinfo->product_name,
+ sizeof(vha->hw->mr.product_name));
+ memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name,
+ sizeof(vha->hw->mr.symbolic_name));
+ memcpy(&vha->hw->mr.serial_num, pinfo->serial_num,
+ sizeof(vha->hw->mr.serial_num));
+ memcpy(&vha->hw->mr.hw_version, pinfo->hw_version,
+ sizeof(vha->hw->mr.hw_version));
+ memcpy(&vha->hw->mr.fw_version, pinfo->fw_version,
+ sizeof(vha->hw->mr.fw_version));
+ strim(vha->hw->mr.fw_version);
+ memcpy(&vha->hw->mr.uboot_version, pinfo->uboot_version,
+ sizeof(vha->hw->mr.uboot_version));
+ memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num,
+ sizeof(vha->hw->mr.fru_serial_num));
+ } else if (fx_type == FXDISC_GET_PORT_INFO) {
+ struct port_info_data *pinfo =
+ (struct port_info_data *) fdisc->u.fxiocb.rsp_addr;
+ memcpy(vha->node_name, pinfo->node_name, WWN_SIZE);
+ memcpy(vha->port_name, pinfo->port_name, WWN_SIZE);
+ vha->d_id.b.domain = pinfo->port_id[0];
+ vha->d_id.b.area = pinfo->port_id[1];
+ vha->d_id.b.al_pa = pinfo->port_id[2];
+ qlafx00_update_host_attr(vha, pinfo);
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0141,
+ (uint8_t *)pinfo, 16);
+ } else if (fx_type == FXDISC_GET_TGT_NODE_INFO) {
+ struct qlafx00_tgt_node_info *pinfo =
+ (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr;
+ memcpy(fcport->node_name, pinfo->tgt_node_wwnn, WWN_SIZE);
+ memcpy(fcport->port_name, pinfo->tgt_node_wwpn, WWN_SIZE);
+ fcport->port_type = FCT_TARGET;
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0144,
+ (uint8_t *)pinfo, 16);
+ } else if (fx_type == FXDISC_GET_TGT_NODE_LIST) {
+ struct qlafx00_tgt_node_info *pinfo =
+ (struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr;
+ ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0146,
+ (uint8_t *)pinfo, 16);
+ memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE);
+ }
+ rval = le32_to_cpu(fdisc->u.fxiocb.result);
+
+done_unmap_dma:
+ if (fdisc->u.fxiocb.rsp_addr)
+ dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.rsp_len,
+ fdisc->u.fxiocb.rsp_addr, fdisc->u.fxiocb.rsp_dma_handle);
+
+done_unmap_req:
+ if (fdisc->u.fxiocb.req_addr)
+ dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
+ fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
+done_free_sp:
+ sp->free(vha, sp);
+done:
+ return rval;
+}
+
+static void
+qlafx00_abort_iocb_timeout(void *data)
+{
+ srb_t *sp = (srb_t *)data;
+ struct srb_iocb *abt = &sp->u.iocb_cmd;
+
+ abt->u.abt.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT);
+ complete(&abt->u.abt.comp);
+}
+
+static void
+qlafx00_abort_sp_done(void *data, void *ptr, int res)
+{
+ srb_t *sp = (srb_t *)ptr;
+ struct srb_iocb *abt = &sp->u.iocb_cmd;
+
+ complete(&abt->u.abt.comp);
+}
+
+static int
+qlafx00_async_abt_cmd(srb_t *cmd_sp)
+{
+ scsi_qla_host_t *vha = cmd_sp->fcport->vha;
+ fc_port_t *fcport = cmd_sp->fcport;
+ struct srb_iocb *abt_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ abt_iocb = &sp->u.iocb_cmd;
+ sp->type = SRB_ABT_CMD;
+ sp->name = "abort";
+ qla2x00_init_timer(sp, FXDISC_TIMEOUT);
+ abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
+ sp->done = qlafx00_abort_sp_done;
+ abt_iocb->timeout = qlafx00_abort_iocb_timeout;
+ init_completion(&abt_iocb->u.abt.comp);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
+ ql_dbg(ql_dbg_async, vha, 0x507c,
+ "Abort command issued - hdl=%x, target_id=%x\n",
+ cmd_sp->handle, fcport->tgt_id);
+
+ wait_for_completion(&abt_iocb->u.abt.comp);
+
+ rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
+ QLA_SUCCESS : QLA_FUNCTION_FAILED;
+
+done_free_sp:
+ sp->free(vha, sp);
+done:
+ return rval;
+}
+
+int
+qlafx00_abort_command(srb_t *sp)
+{
+ unsigned long flags = 0;
+
+ uint32_t handle;
+ fc_port_t *fcport = sp->fcport;
+ struct scsi_qla_host *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = vha->req;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ for (handle = 1; handle < DEFAULT_OUTSTANDING_COMMANDS; handle++) {
+ if (req->outstanding_cmds[handle] == sp)
+ break;
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ if (handle == DEFAULT_OUTSTANDING_COMMANDS) {
+ /* Command not found. */
+ return QLA_FUNCTION_FAILED;
+ }
+ return qlafx00_async_abt_cmd(sp);
+}
+
+/*
+ * qlafx00_initialize_adapter
+ * Initialize board.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ *
+ * Returns:
+ * 0 = success
+ */
+int
+qlafx00_initialize_adapter(scsi_qla_host_t *vha)
+{
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+
+ /* Clear adapter flags. */
+ vha->flags.online = 0;
+ ha->flags.chip_reset_done = 0;
+ vha->flags.reset_active = 0;
+ ha->flags.pci_channel_io_perm_failure = 0;
+ ha->flags.eeh_busy = 0;
+ ha->thermal_support = 0;
+ atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
+ atomic_set(&vha->loop_state, LOOP_DOWN);
+ vha->device_flags = DFLG_NO_CABLE;
+ vha->dpc_flags = 0;
+ vha->flags.management_server_logged_in = 0;
+ vha->marker_needed = 0;
+ ha->isp_abort_cnt = 0;
+ ha->beacon_blink_led = 0;
+
+ set_bit(0, ha->req_qid_map);
+ set_bit(0, ha->rsp_qid_map);
+
+ ql_dbg(ql_dbg_init, vha, 0x0147,
+ "Configuring PCI space...\n");
+
+ rval = ha->isp_ops->pci_config(vha);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x0148,
+ "Unable to configure PCI space.\n");
+ return rval;
+ }
+
+ rval = qlafx00_init_fw_ready(vha);
+ if (rval != QLA_SUCCESS)
+ return rval;
+
+ qlafx00_save_queue_ptrs(vha);
+
+ rval = qlafx00_config_queues(vha);
+ if (rval != QLA_SUCCESS)
+ return rval;
+
+ /*
+ * Allocate the array of outstanding commands
+ * now that we know the firmware resources.
+ */
+ rval = qla2x00_alloc_outstanding_cmds(ha, vha->req);
+ if (rval != QLA_SUCCESS)
+ return rval;
+
+ rval = qla2x00_init_rings(vha);
+ ha->flags.chip_reset_done = 1;
+
+ return rval;
+}
+
+uint32_t
+qlafx00_fw_state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int rval = QLA_FUNCTION_FAILED;
+ uint32_t state[1];
+
+ if (qla2x00_reset_active(vha))
+ ql_log(ql_log_warn, vha, 0x70ce,
+ "ISP reset active.\n");
+ else if (!vha->hw->flags.eeh_busy) {
+ rval = qlafx00_get_firmware_state(vha, state);
+ }
+ if (rval != QLA_SUCCESS)
+ memset(state, -1, sizeof(state));
+
+ return state[0];
+}
+
+void
+qlafx00_get_host_speed(struct Scsi_Host *shost)
+{
+ struct qla_hw_data *ha = ((struct scsi_qla_host *)
+ (shost_priv(shost)))->hw;
+ u32 speed = FC_PORTSPEED_UNKNOWN;
+
+ switch (ha->link_data_rate) {
+ case QLAFX00_PORT_SPEED_2G:
+ speed = FC_PORTSPEED_2GBIT;
+ break;
+ case QLAFX00_PORT_SPEED_4G:
+ speed = FC_PORTSPEED_4GBIT;
+ break;
+ case QLAFX00_PORT_SPEED_8G:
+ speed = FC_PORTSPEED_8GBIT;
+ break;
+ case QLAFX00_PORT_SPEED_10G:
+ speed = FC_PORTSPEED_10GBIT;
+ break;
+ }
+ fc_host_speed(shost) = speed;
+}
+
+/** QLAFX00 specific ISR implementation functions */
+
+static inline void
+qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
+ uint32_t sense_len, struct rsp_que *rsp, int res)
+{
+ struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_cmnd *cp = GET_CMD_SP(sp);
+ uint32_t track_sense_len;
+
+ SET_FW_SENSE_LEN(sp, sense_len);
+
+ if (sense_len >= SCSI_SENSE_BUFFERSIZE)
+ sense_len = SCSI_SENSE_BUFFERSIZE;
+
+ SET_CMD_SENSE_LEN(sp, sense_len);
+ SET_CMD_SENSE_PTR(sp, cp->sense_buffer);
+ track_sense_len = sense_len;
+
+ if (sense_len > par_sense_len)
+ sense_len = par_sense_len;
+
+ memcpy(cp->sense_buffer, sense_data, sense_len);
+
+ SET_FW_SENSE_LEN(sp, GET_FW_SENSE_LEN(sp) - sense_len);
+
+ SET_CMD_SENSE_PTR(sp, cp->sense_buffer + sense_len);
+ track_sense_len -= sense_len;
+ SET_CMD_SENSE_LEN(sp, track_sense_len);
+
+ ql_dbg(ql_dbg_io, vha, 0x304d,
+ "sense_len=0x%x par_sense_len=0x%x track_sense_len=0x%x.\n",
+ sense_len, par_sense_len, track_sense_len);
+ if (GET_FW_SENSE_LEN(sp) > 0) {
+ rsp->status_srb = sp;
+ cp->result = res;
+ }
+
+ if (sense_len) {
+ ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039,
+ "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n",
+ sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
+ cp);
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049,
+ cp->sense_buffer, sense_len);
+ }
+}
+
+static void
+qlafx00_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct tsk_mgmt_entry_fx00 *pkt, srb_t *sp,
+ __le16 sstatus, __le16 cpstatus)
+{
+ struct srb_iocb *tmf;
+
+ tmf = &sp->u.iocb_cmd;
+ if (cpstatus != cpu_to_le16((uint16_t)CS_COMPLETE) ||
+ (sstatus & cpu_to_le16((uint16_t)SS_RESPONSE_INFO_LEN_VALID)))
+ cpstatus = cpu_to_le16((uint16_t)CS_INCOMPLETE);
+ tmf->u.tmf.comp_status = cpstatus;
+ sp->done(vha, sp, 0);
+}
+
+static void
+qlafx00_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct abort_iocb_entry_fx00 *pkt)
+{
+ const char func[] = "ABT_IOCB";
+ srb_t *sp;
+ struct srb_iocb *abt;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (!sp)
+ return;
+
+ abt = &sp->u.iocb_cmd;
+ abt->u.abt.comp_status = pkt->tgt_id_sts;
+ sp->done(vha, sp, 0);
+}
+
+static void
+qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct ioctl_iocb_entry_fx00 *pkt)
+{
+ const char func[] = "IOSB_IOCB";
+ srb_t *sp;
+ struct fc_bsg_job *bsg_job;
+ struct srb_iocb *iocb_job;
+ int res;
+ struct qla_mt_iocb_rsp_fx00 fstatus;
+ uint8_t *fw_sts_ptr;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (!sp)
+ return;
+
+ if (sp->type == SRB_FXIOCB_DCMD) {
+ iocb_job = &sp->u.iocb_cmd;
+ iocb_job->u.fxiocb.seq_number = pkt->seq_no;
+ iocb_job->u.fxiocb.fw_flags = pkt->fw_iotcl_flags;
+ iocb_job->u.fxiocb.result = pkt->status;
+ if (iocb_job->u.fxiocb.flags & SRB_FXDISC_RSP_DWRD_VALID)
+ iocb_job->u.fxiocb.req_data =
+ pkt->dataword_r;
+ } else {
+ bsg_job = sp->u.bsg_job;
+
+ memset(&fstatus, 0, sizeof(struct qla_mt_iocb_rsp_fx00));
+
+ fstatus.reserved_1 = pkt->reserved_0;
+ fstatus.func_type = pkt->comp_func_num;
+ fstatus.ioctl_flags = pkt->fw_iotcl_flags;
+ fstatus.ioctl_data = pkt->dataword_r;
+ fstatus.adapid = pkt->adapid;
+ fstatus.adapid_hi = pkt->adapid_hi;
+ fstatus.reserved_2 = pkt->reserved_1;
+ fstatus.res_count = pkt->residuallen;
+ fstatus.status = pkt->status;
+ fstatus.seq_number = pkt->seq_no;
+ memcpy(fstatus.reserved_3,
+ pkt->reserved_2, 20 * sizeof(uint8_t));
+
+ fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
+ sizeof(struct fc_bsg_reply);
+
+ memcpy(fw_sts_ptr, (uint8_t *)&fstatus,
+ sizeof(struct qla_mt_iocb_rsp_fx00));
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
+ sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t);
+
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x5080,
+ (uint8_t *)pkt, sizeof(struct ioctl_iocb_entry_fx00));
+
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x5074,
+ (uint8_t *)fw_sts_ptr, sizeof(struct qla_mt_iocb_rsp_fx00));
+
+ res = bsg_job->reply->result = DID_OK << 16;
+ bsg_job->reply->reply_payload_rcv_len =
+ bsg_job->reply_payload.payload_len;
+ }
+ sp->done(vha, sp, res);
+}
+
+/**
+ * qlafx00_status_entry() - Process a Status IOCB entry.
+ * @ha: SCSI driver HA context
+ * @pkt: Entry pointer
+ */
+static void
+qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
+{
+ srb_t *sp;
+ fc_port_t *fcport;
+ struct scsi_cmnd *cp;
+ struct sts_entry_fx00 *sts;
+ __le16 comp_status;
+ __le16 scsi_status;
+ uint16_t ox_id;
+ __le16 lscsi_status;
+ int32_t resid;
+ uint32_t sense_len, par_sense_len, rsp_info_len, resid_len,
+ fw_resid_len;
+ uint8_t *rsp_info = NULL, *sense_data = NULL;
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t hindex, handle;
+ uint16_t que;
+ struct req_que *req;
+ int logit = 1;
+ int res = 0;
+
+ sts = (struct sts_entry_fx00 *) pkt;
+
+ comp_status = sts->comp_status;
+ scsi_status = sts->scsi_status & cpu_to_le16((uint16_t)SS_MASK);
+ hindex = sts->handle;
+ handle = LSW(hindex);
+
+ que = MSW(hindex);
+ req = ha->req_q_map[que];
+
+ /* Validate handle. */
+ if (handle < req->num_outstanding_cmds)
+ sp = req->outstanding_cmds[handle];
+ else
+ sp = NULL;
+
+ if (sp == NULL) {
+ ql_dbg(ql_dbg_io, vha, 0x3034,
+ "Invalid status handle (0x%x).\n", handle);
+
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ return;
+ }
+
+ if (sp->type == SRB_TM_CMD) {
+ req->outstanding_cmds[handle] = NULL;
+ qlafx00_tm_iocb_entry(vha, req, pkt, sp,
+ scsi_status, comp_status);
+ return;
+ }
+
+ /* Fast path completion. */
+ if (comp_status == CS_COMPLETE && scsi_status == 0) {
+ qla2x00_do_host_ramp_up(vha);
+ qla2x00_process_completed_request(vha, req, handle);
+ return;
+ }
+
+ req->outstanding_cmds[handle] = NULL;
+ cp = GET_CMD_SP(sp);
+ if (cp == NULL) {
+ ql_dbg(ql_dbg_io, vha, 0x3048,
+ "Command already returned (0x%x/%p).\n",
+ handle, sp);
+
+ return;
+ }
+
+ lscsi_status = scsi_status & cpu_to_le16((uint16_t)STATUS_MASK);
+
+ fcport = sp->fcport;
+
+ ox_id = 0;
+ sense_len = par_sense_len = rsp_info_len = resid_len =
+ fw_resid_len = 0;
+ if (scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID))
+ sense_len = sts->sense_len;
+ if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER
+ | (uint16_t)SS_RESIDUAL_OVER)))
+ resid_len = le32_to_cpu(sts->residual_len);
+ if (comp_status == cpu_to_le16((uint16_t)CS_DATA_UNDERRUN))
+ fw_resid_len = le32_to_cpu(sts->residual_len);
+ rsp_info = sense_data = sts->data;
+ par_sense_len = sizeof(sts->data);
+
+ /* Check for overrun. */
+ if (comp_status == CS_COMPLETE &&
+ scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_OVER))
+ comp_status = cpu_to_le16((uint16_t)CS_DATA_OVERRUN);
+
+ /*
+ * Based on Host and scsi status generate status code for Linux
+ */
+ switch (le16_to_cpu(comp_status)) {
+ case CS_COMPLETE:
+ case CS_QUEUE_FULL:
+ if (scsi_status == 0) {
+ res = DID_OK << 16;
+ break;
+ }
+ if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER
+ | (uint16_t)SS_RESIDUAL_OVER))) {
+ resid = resid_len;
+ scsi_set_resid(cp, resid);
+
+ if (!lscsi_status &&
+ ((unsigned)(scsi_bufflen(cp) - resid) <
+ cp->underflow)) {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3050,
+ "Mid-layer underflow "
+ "detected (0x%x of 0x%x bytes).\n",
+ resid, scsi_bufflen(cp));
+
+ res = DID_ERROR << 16;
+ break;
+ }
+ }
+ res = DID_OK << 16 | le16_to_cpu(lscsi_status);
+
+ if (lscsi_status ==
+ cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3051,
+ "QUEUE FULL detected.\n");
+ break;
+ }
+ logit = 0;
+ if (lscsi_status != cpu_to_le16((uint16_t)SS_CHECK_CONDITION))
+ break;
+
+ memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ if (!(scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)))
+ break;
+
+ qlafx00_handle_sense(sp, sense_data, par_sense_len, sense_len,
+ rsp, res);
+ break;
+
+ case CS_DATA_UNDERRUN:
+ /* Use F/W calculated residual length. */
+ if (IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha))
+ resid = fw_resid_len;
+ else
+ resid = resid_len;
+ scsi_set_resid(cp, resid);
+ if (scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_UNDER)) {
+ if ((IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha))
+ && fw_resid_len != resid_len) {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3052,
+ "Dropped frame(s) detected "
+ "(0x%x of 0x%x bytes).\n",
+ resid, scsi_bufflen(cp));
+
+ res = DID_ERROR << 16 |
+ le16_to_cpu(lscsi_status);
+ goto check_scsi_status;
+ }
+
+ if (!lscsi_status &&
+ ((unsigned)(scsi_bufflen(cp) - resid) <
+ cp->underflow)) {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3053,
+ "Mid-layer underflow "
+ "detected (0x%x of 0x%x bytes, "
+ "cp->underflow: 0x%x).\n",
+ resid, scsi_bufflen(cp), cp->underflow);
+
+ res = DID_ERROR << 16;
+ break;
+ }
+ } else if (lscsi_status !=
+ cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL) &&
+ lscsi_status != cpu_to_le16((uint16_t)SAM_STAT_BUSY)) {
+ /*
+ * scsi status of task set and busy are considered
+ * to be task not completed.
+ */
+
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3054,
+ "Dropped frame(s) detected (0x%x "
+ "of 0x%x bytes).\n", resid,
+ scsi_bufflen(cp));
+
+ res = DID_ERROR << 16 | le16_to_cpu(lscsi_status);
+ goto check_scsi_status;
+ } else {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3055,
+ "scsi_status: 0x%x, lscsi_status: 0x%x\n",
+ scsi_status, lscsi_status);
+ }
+
+ res = DID_OK << 16 | le16_to_cpu(lscsi_status);
+ logit = 0;
+
+check_scsi_status:
+ /*
+ * Check to see if SCSI Status is non zero. If so report SCSI
+ * Status.
+ */
+ if (lscsi_status != 0) {
+ if (lscsi_status ==
+ cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3056,
+ "QUEUE FULL detected.\n");
+ logit = 1;
+ break;
+ }
+ if (lscsi_status !=
+ cpu_to_le16((uint16_t)SS_CHECK_CONDITION))
+ break;
+
+ memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ if (!(scsi_status &
+ cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)))
+ break;
+
+ qlafx00_handle_sense(sp, sense_data, par_sense_len,
+ sense_len, rsp, res);
+ }
+ break;
+
+ case CS_PORT_LOGGED_OUT:
+ case CS_PORT_CONFIG_CHG:
+ case CS_PORT_BUSY:
+ case CS_INCOMPLETE:
+ case CS_PORT_UNAVAILABLE:
+ case CS_TIMEOUT:
+ case CS_RESET:
+
+ /*
+ * We are going to have the fc class block the rport
+ * while we try to recover so instruct the mid layer
+ * to requeue until the class decides how to handle this.
+ */
+ res = DID_TRANSPORT_DISRUPTED << 16;
+
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3057,
+ "Port down status: port-state=0x%x.\n",
+ atomic_read(&fcport->state));
+
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
+ break;
+
+ case CS_ABORTED:
+ res = DID_RESET << 16;
+ break;
+
+ default:
+ res = DID_ERROR << 16;
+ break;
+ }
+
+ if (logit)
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3058,
+ "FCP command status: 0x%x-0x%x (0x%x) "
+ "nexus=%ld:%d:%d tgt_id: 0x%x lscsi_status: 0x%x"
+ "cdb=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x len=0x%x "
+ "rsp_info=0x%x resid=0x%x fw_resid=0x%x "
+ "sense_len=0x%x, par_sense_len=0x%x, rsp_info_len=0x%x\n",
+ comp_status, scsi_status, res, vha->host_no,
+ cp->device->id, cp->device->lun, fcport->tgt_id,
+ lscsi_status, cp->cmnd[0], cp->cmnd[1], cp->cmnd[2],
+ cp->cmnd[3], cp->cmnd[4], cp->cmnd[5], cp->cmnd[6],
+ cp->cmnd[7], cp->cmnd[8], cp->cmnd[9], scsi_bufflen(cp),
+ rsp_info_len, resid_len, fw_resid_len, sense_len,
+ par_sense_len, rsp_info_len);
+
+ if (!res)
+ qla2x00_do_host_ramp_up(vha);
+
+ if (rsp->status_srb == NULL)
+ sp->done(ha, sp, res);
+}
+
+/**
+ * qlafx00_status_cont_entry() - Process a Status Continuations entry.
+ * @ha: SCSI driver HA context
+ * @pkt: Entry pointer
+ *
+ * Extended sense data.
+ */
+static void
+qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
+{
+ uint8_t sense_sz = 0;
+ struct qla_hw_data *ha = rsp->hw;
+ struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
+ srb_t *sp = rsp->status_srb;
+ struct scsi_cmnd *cp;
+ uint32_t sense_len;
+ uint8_t *sense_ptr;
+
+ if (!sp) {
+ ql_dbg(ql_dbg_io, vha, 0x3037,
+ "no SP, sp = %p\n", sp);
+ return;
+ }
+
+ if (!GET_FW_SENSE_LEN(sp)) {
+ ql_dbg(ql_dbg_io, vha, 0x304b,
+ "no fw sense data, sp = %p\n", sp);
+ return;
+ }
+ cp = GET_CMD_SP(sp);
+ if (cp == NULL) {
+ ql_log(ql_log_warn, vha, 0x303b,
+ "cmd is NULL: already returned to OS (sp=%p).\n", sp);
+
+ rsp->status_srb = NULL;
+ return;
+ }
+
+ if (!GET_CMD_SENSE_LEN(sp)) {
+ ql_dbg(ql_dbg_io, vha, 0x304c,
+ "no sense data, sp = %p\n", sp);
+ } else {
+ sense_len = GET_CMD_SENSE_LEN(sp);
+ sense_ptr = GET_CMD_SENSE_PTR(sp);
+ ql_dbg(ql_dbg_io, vha, 0x304f,
+ "sp=%p sense_len=0x%x sense_ptr=%p.\n",
+ sp, sense_len, sense_ptr);
+
+ if (sense_len > sizeof(pkt->data))
+ sense_sz = sizeof(pkt->data);
+ else
+ sense_sz = sense_len;
+
+ /* Move sense data. */
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304e,
+ (uint8_t *)pkt, sizeof(sts_cont_entry_t));
+ memcpy(sense_ptr, pkt->data, sense_sz);
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304a,
+ sense_ptr, sense_sz);
+
+ sense_len -= sense_sz;
+ sense_ptr += sense_sz;
+
+ SET_CMD_SENSE_PTR(sp, sense_ptr);
+ SET_CMD_SENSE_LEN(sp, sense_len);
+ }
+ sense_len = GET_FW_SENSE_LEN(sp);
+ sense_len = (sense_len > sizeof(pkt->data)) ?
+ (sense_len - sizeof(pkt->data)) : 0;
+ SET_FW_SENSE_LEN(sp, sense_len);
+
+ /* Place command on done queue. */
+ if (sense_len == 0) {
+ rsp->status_srb = NULL;
+ sp->done(ha, sp, cp->result);
+ }
+}
+
+/**
+ * qlafx00_multistatus_entry() - Process Multi response queue entries.
+ * @ha: SCSI driver HA context
+ */
+static void
+qlafx00_multistatus_entry(struct scsi_qla_host *vha,
+ struct rsp_que *rsp, void *pkt)
+{
+ srb_t *sp;
+ struct multi_sts_entry_fx00 *stsmfx;
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t handle, hindex, handle_count, i;
+ uint16_t que;
+ struct req_que *req;
+ __le32 *handle_ptr;
+
+ stsmfx = (struct multi_sts_entry_fx00 *) pkt;
+
+ handle_count = stsmfx->handle_count;
+
+ if (handle_count > MAX_HANDLE_COUNT) {
+ ql_dbg(ql_dbg_io, vha, 0x3035,
+ "Invalid handle count (0x%x).\n", handle_count);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ return;
+ }
+
+ handle_ptr = &stsmfx->handles[0];
+
+ for (i = 0; i < handle_count; i++) {
+ hindex = le32_to_cpu(*handle_ptr);
+ handle = LSW(hindex);
+ que = MSW(hindex);
+ req = ha->req_q_map[que];
+
+ /* Validate handle. */
+ if (handle < req->num_outstanding_cmds)
+ sp = req->outstanding_cmds[handle];
+ else
+ sp = NULL;
+
+ if (sp == NULL) {
+ ql_dbg(ql_dbg_io, vha, 0x3044,
+ "Invalid status handle (0x%x).\n", handle);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ return;
+ }
+ qla2x00_process_completed_request(vha, req, handle);
+ handle_ptr++;
+ }
+}
+
+/**
+ * qlafx00_error_entry() - Process an error entry.
+ * @ha: SCSI driver HA context
+ * @pkt: Entry pointer
+ */
+static void
+qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp,
+ struct sts_entry_fx00 *pkt, uint8_t estatus, uint8_t etype)
+{
+ srb_t *sp;
+ struct qla_hw_data *ha = vha->hw;
+ const char func[] = "ERROR-IOCB";
+ uint16_t que = MSW(pkt->handle);
+ struct req_que *req = NULL;
+ int res = DID_ERROR << 16;
+
+ ql_dbg(ql_dbg_async, vha, 0x507f,
+ "type of error status in response: 0x%x\n", estatus);
+
+ req = ha->req_q_map[que];
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (sp) {
+ sp->done(ha, sp, res);
+ return;
+ }
+
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+}
+
+/**
+ * qlafx00_process_response_queue() - Process response queue entries.
+ * @ha: SCSI driver HA context
+ */
+static void
+qlafx00_process_response_queue(struct scsi_qla_host *vha,
+ struct rsp_que *rsp)
+{
+ struct sts_entry_fx00 *pkt;
+ response_t *lptr;
+
+ if (!vha->flags.online)
+ return;
+
+ while (RD_REG_DWORD((void __iomem *)&(rsp->ring_ptr->signature)) !=
+ RESPONSE_PROCESSED) {
+ lptr = rsp->ring_ptr;
+ memcpy_fromio(rsp->rsp_pkt, (void __iomem *)lptr,
+ sizeof(rsp->rsp_pkt));
+ pkt = (struct sts_entry_fx00 *)rsp->rsp_pkt;
+
+ rsp->ring_index++;
+ if (rsp->ring_index == rsp->length) {
+ rsp->ring_index = 0;
+ rsp->ring_ptr = rsp->ring;
+ } else {
+ rsp->ring_ptr++;
+ }
+
+ if (pkt->entry_status != 0 &&
+ pkt->entry_type != IOCTL_IOSB_TYPE_FX00) {
+ qlafx00_error_entry(vha, rsp,
+ (struct sts_entry_fx00 *)pkt, pkt->entry_status,
+ pkt->entry_type);
+ goto next_iter;
+ continue;
+ }
+
+ switch (pkt->entry_type) {
+ case STATUS_TYPE_FX00:
+ qlafx00_status_entry(vha, rsp, pkt);
+ break;
+
+ case STATUS_CONT_TYPE_FX00:
+ qlafx00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
+ break;
+
+ case MULTI_STATUS_TYPE_FX00:
+ qlafx00_multistatus_entry(vha, rsp, pkt);
+ break;
+
+ case ABORT_IOCB_TYPE_FX00:
+ qlafx00_abort_iocb_entry(vha, rsp->req,
+ (struct abort_iocb_entry_fx00 *)pkt);
+ break;
+
+ case IOCTL_IOSB_TYPE_FX00:
+ qlafx00_ioctl_iosb_entry(vha, rsp->req,
+ (struct ioctl_iocb_entry_fx00 *)pkt);
+ break;
+ default:
+ /* Type Not Supported. */
+ ql_dbg(ql_dbg_async, vha, 0x5081,
+ "Received unknown response pkt type %x "
+ "entry status=%x.\n",
+ pkt->entry_type, pkt->entry_status);
+ break;
+ }
+next_iter:
+ WRT_REG_DWORD((void __iomem *)&lptr->signature,
+ RESPONSE_PROCESSED);
+ wmb();
+ }
+
+ /* Adjust ring index */
+ WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
+}
+
+/**
+ * qlafx00_async_event() - Process aynchronous events.
+ * @ha: SCSI driver HA context
+ */
+static void
+qlafx00_async_event(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_fx00 __iomem *reg;
+ int data_size = 1;
+
+ reg = &ha->iobase->ispfx00;
+ /* Setup to process RIO completion. */
+ switch (ha->aenmb[0]) {
+ case QLAFX00_MBA_SYSTEM_ERR: /* System Error */
+ ql_log(ql_log_warn, vha, 0x5079,
+ "ISP System Error - mbx1=%x\n", ha->aenmb[0]);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ break;
+
+ case QLAFX00_MBA_SHUTDOWN_RQSTD: /* Shutdown requested */
+ ql_dbg(ql_dbg_async, vha, 0x5076,
+ "Asynchronous FW shutdown requested.\n");
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ break;
+
+ case QLAFX00_MBA_PORT_UPDATE: /* Port database update */
+ ha->aenmb[1] = RD_REG_WORD(&reg->aenmailbox1);
+ ha->aenmb[2] = RD_REG_WORD(&reg->aenmailbox2);
+ ha->aenmb[3] = RD_REG_WORD(&reg->aenmailbox3);
+ ql_dbg(ql_dbg_async, vha, 0x5077,
+ "Asynchronous port Update received "
+ "aenmb[0]: %x, aenmb[1]: %x, aenmb[2]: %x, aenmb[3]: %x\n",
+ ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]);
+ data_size = 4;
+ break;
+ default:
+ ha->aenmb[1] = RD_REG_WORD(&reg->aenmailbox1);
+ ha->aenmb[2] = RD_REG_WORD(&reg->aenmailbox2);
+ ha->aenmb[3] = RD_REG_WORD(&reg->aenmailbox3);
+ ha->aenmb[4] = RD_REG_WORD(&reg->aenmailbox4);
+ ha->aenmb[5] = RD_REG_WORD(&reg->aenmailbox5);
+ ha->aenmb[6] = RD_REG_WORD(&reg->aenmailbox6);
+ ha->aenmb[7] = RD_REG_WORD(&reg->aenmailbox7);
+ ql_dbg(ql_dbg_async, vha, 0x5078,
+ "AEN:%04x %04x %04x %04x :%04x %04x %04x %04x\n",
+ ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3],
+ ha->aenmb[4], ha->aenmb[5], ha->aenmb[6], ha->aenmb[7]);
+ break;
+ }
+ qlafx00_post_aenfx_work(vha, ha->aenmb[0],
+ (uint32_t *)ha->aenmb, data_size);
+}
+
+/**
+ *
+ * qlafx00x_mbx_completion() - Process mailbox command completions.
+ * @ha: SCSI driver HA context
+ * @mb16: Mailbox16 register
+ */
+static void
+qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0)
+{
+ uint16_t cnt;
+ uint16_t __iomem *wptr;
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
+
+ if (!ha->mcp32)
+ ql_dbg(ql_dbg_async, vha, 0x507e, "MBX pointer ERROR.\n");
+
+ /* Load return mailbox registers. */
+ ha->flags.mbox_int = 1;
+ ha->mailbox_out32[0] = mb0;
+ wptr = (uint16_t __iomem *)&reg->mailbox17;
+
+ for (cnt = 1; cnt < ha->mbx_count; cnt++) {
+ ha->mailbox_out32[cnt] = RD_REG_WORD(wptr);
+ wptr++;
+ }
+}
+
+/**
+ * qlafx00_intr_handler() - Process interrupts for the ISPFX00.
+ * @irq:
+ * @dev_id: SCSI driver HA context
+ *
+ * Called by system whenever the host adapter generates an interrupt.
+ *
+ * Returns handled flag.
+ */
+irqreturn_t
+qlafx00_intr_handler(int irq, void *dev_id)
+{
+ scsi_qla_host_t *vha;
+ struct qla_hw_data *ha;
+ struct device_reg_fx00 __iomem *reg;
+ int status;
+ unsigned long iter;
+ uint32_t stat;
+ uint32_t mb[8];
+ struct rsp_que *rsp;
+ unsigned long flags;
+ uint32_t clr_intr = 0;
+
+ rsp = (struct rsp_que *) dev_id;
+ if (!rsp) {
+ ql_log(ql_log_info, NULL, 0x507d,
+ "%s: NULL response queue pointer.\n", __func__);
+ return IRQ_NONE;
+ }
+
+ ha = rsp->hw;
+ reg = &ha->iobase->ispfx00;
+ status = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ return IRQ_HANDLED;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ vha = pci_get_drvdata(ha->pdev);
+ for (iter = 50; iter--; clr_intr = 0) {
+ stat = QLAFX00_RD_INTR_REG(ha);
+ if ((stat & QLAFX00_HST_INT_STS_BITS) == 0)
+ break;
+
+ switch (stat & QLAFX00_HST_INT_STS_BITS) {
+ case QLAFX00_INTR_MB_CMPLT:
+ case QLAFX00_INTR_MB_RSP_CMPLT:
+ case QLAFX00_INTR_MB_ASYNC_CMPLT:
+ case QLAFX00_INTR_ALL_CMPLT:
+ mb[0] = RD_REG_WORD(&reg->mailbox16);
+ qlafx00_mbx_completion(vha, mb[0]);
+ status |= MBX_INTERRUPT;
+ clr_intr |= QLAFX00_INTR_MB_CMPLT;
+ break;
+ case QLAFX00_INTR_ASYNC_CMPLT:
+ case QLAFX00_INTR_RSP_ASYNC_CMPLT:
+ ha->aenmb[0] = RD_REG_WORD(&reg->aenmailbox0);
+ qlafx00_async_event(vha);
+ clr_intr |= QLAFX00_INTR_ASYNC_CMPLT;
+ break;
+ case QLAFX00_INTR_RSP_CMPLT:
+ qlafx00_process_response_queue(vha, rsp);
+ clr_intr |= QLAFX00_INTR_RSP_CMPLT;
+ break;
+ default:
+ ql_dbg(ql_dbg_async, vha, 0x507a,
+ "Unrecognized interrupt type (%d).\n", stat);
+ break;
+ }
+ QLAFX00_CLR_INTR_REG(ha, clr_intr);
+ QLAFX00_RD_INTR_REG(ha);
+ }
+
+ qla2x00_handle_mbx_completion(ha, status);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/** QLAFX00 specific IOCB implementation functions */
+
+static inline cont_a64_entry_t *
+qlafx00_prep_cont_type1_iocb(struct req_que *req,
+ cont_a64_entry_t *lcont_pkt)
+{
+ cont_a64_entry_t *cont_pkt;
+
+ /* Adjust ring index. */
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
+ } else {
+ req->ring_ptr++;
+ }
+
+ cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
+
+ /* Load packet defaults. */
+ lcont_pkt->entry_type = CONTINUE_A64_TYPE_FX00;
+
+ return cont_pkt;
+}
+
+static inline void
+qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
+ uint16_t tot_dsds, struct cmd_type_7_fx00 *lcmd_pkt)
+{
+ uint16_t avail_dsds;
+ __le32 *cur_dsd;
+ scsi_qla_host_t *vha;
+ struct scsi_cmnd *cmd;
+ struct scatterlist *sg;
+ int i, cont;
+ struct req_que *req;
+ cont_a64_entry_t lcont_pkt;
+ cont_a64_entry_t *cont_pkt;
+
+ vha = sp->fcport->vha;
+ req = vha->req;
+
+ cmd = GET_CMD_SP(sp);
+ cont = 0;
+ cont_pkt = NULL;
+
+ /* Update entry type to indicate Command Type 3 IOCB */
+ lcmd_pkt->entry_type = FX00_COMMAND_TYPE_7;
+
+ /* No data transfer */
+ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
+ lcmd_pkt->byte_count = __constant_cpu_to_le32(0);
+ return;
+ }
+
+ /* Set transfer direction */
+ if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+ lcmd_pkt->cntrl_flags = TMF_WRITE_DATA;
+ vha->qla_stats.output_bytes += scsi_bufflen(cmd);
+ } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+ lcmd_pkt->cntrl_flags = TMF_READ_DATA;
+ vha->qla_stats.input_bytes += scsi_bufflen(cmd);
+ }
+
+ /* One DSD is available in the Command Type 3 IOCB */
+ avail_dsds = 1;
+ cur_dsd = (__le32 *)&lcmd_pkt->dseg_0_address;
+
+ /* Load data segments */
+ scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+ dma_addr_t sle_dma;
+
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ /*
+ * Five DSDs are available in the Continuation
+ * Type 1 IOCB.
+ */
+ memset(&lcont_pkt, 0, REQUEST_ENTRY_SIZE);
+ cont_pkt =
+ qlafx00_prep_cont_type1_iocb(req, &lcont_pkt);
+ cur_dsd = (__le32 *)lcont_pkt.dseg_0_address;
+ avail_dsds = 5;
+ cont = 1;
+ }
+
+ sle_dma = sg_dma_address(sg);
+ *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ avail_dsds--;
+ if (avail_dsds == 0 && cont == 1) {
+ cont = 0;
+ memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt,
+ REQUEST_ENTRY_SIZE);
+ }
+
+ }
+ if (avail_dsds != 0 && cont == 1) {
+ memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt,
+ REQUEST_ENTRY_SIZE);
+ }
+}
+
+/**
+ * qlafx00_start_scsi() - Send a SCSI command to the ISP
+ * @sp: command to send to the ISP
+ *
+ * Returns non-zero if a failure occurred, else zero.
+ */
+int
+qlafx00_start_scsi(srb_t *sp)
+{
+ int ret, nseg;
+ unsigned long flags;
+ uint32_t index;
+ uint32_t handle;
+ uint16_t cnt;
+ uint16_t req_cnt;
+ uint16_t tot_dsds;
+ struct req_que *req = NULL;
+ struct rsp_que *rsp = NULL;
+ struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+ struct scsi_qla_host *vha = sp->fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ struct cmd_type_7_fx00 *cmd_pkt;
+ struct cmd_type_7_fx00 lcmd_pkt;
+ struct scsi_lun llun;
+ char tag[2];
+
+ /* Setup device pointers. */
+ ret = 0;
+
+ rsp = ha->rsp_q_map[0];
+ req = vha->req;
+
+ /* So we know we haven't pci_map'ed anything yet */
+ tot_dsds = 0;
+
+ /* Forcing marker needed for now */
+ vha->marker_needed = 0;
+
+ /* Send marker if required */
+ if (vha->marker_needed != 0) {
+ if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ QLA_SUCCESS)
+ return QLA_FUNCTION_FAILED;
+ vha->marker_needed = 0;
+ }
+
+ /* Acquire ring specific lock */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ /* Check for room in outstanding command list. */
+ handle = req->current_outstanding_cmd;
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
+ handle++;
+ if (handle == req->num_outstanding_cmds)
+ handle = 1;
+ if (!req->outstanding_cmds[handle])
+ break;
+ }
+ if (index == req->num_outstanding_cmds)
+ goto queuing_error;
+
+ /* Map the sg table so we have an accurate count of sg entries needed */
+ if (scsi_sg_count(cmd)) {
+ nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
+ scsi_sg_count(cmd), cmd->sc_data_direction);
+ if (unlikely(!nseg))
+ goto queuing_error;
+ } else
+ nseg = 0;
+
+ tot_dsds = nseg;
+ req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+ if (req->cnt < (req_cnt + 2)) {
+ cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
+
+ if (req->ring_index < cnt)
+ req->cnt = cnt - req->ring_index;
+ else
+ req->cnt = req->length -
+ (req->ring_index - cnt);
+ if (req->cnt < (req_cnt + 2))
+ goto queuing_error;
+ }
+
+ /* Build command packet. */
+ req->current_outstanding_cmd = handle;
+ req->outstanding_cmds[handle] = sp;
+ sp->handle = handle;
+ cmd->host_scribble = (unsigned char *)(unsigned long)handle;
+ req->cnt -= req_cnt;
+
+ cmd_pkt = (struct cmd_type_7_fx00 *)req->ring_ptr;
+
+ memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE);
+
+ lcmd_pkt.handle = MAKE_HANDLE(req->id, sp->handle);
+ lcmd_pkt.handle_hi = 0;
+ lcmd_pkt.dseg_count = cpu_to_le16(tot_dsds);
+ lcmd_pkt.tgt_idx = cpu_to_le16(sp->fcport->tgt_id);
+
+ int_to_scsilun(cmd->device->lun, &llun);
+ host_to_adap((uint8_t *)&llun, (uint8_t *)&lcmd_pkt.lun,
+ sizeof(lcmd_pkt.lun));
+
+ /* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
+ if (scsi_populate_tag_msg(cmd, tag)) {
+ switch (tag[0]) {
+ case HEAD_OF_QUEUE_TAG:
+ lcmd_pkt.task = TSK_HEAD_OF_QUEUE;
+ break;
+ case ORDERED_QUEUE_TAG:
+ lcmd_pkt.task = TSK_ORDERED;
+ break;
+ }
+ }
+
+ /* Load SCSI command packet. */
+ host_to_adap(cmd->cmnd, lcmd_pkt.fcp_cdb, sizeof(lcmd_pkt.fcp_cdb));
+ lcmd_pkt.byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
+
+ /* Build IOCB segments */
+ qlafx00_build_scsi_iocbs(sp, cmd_pkt, tot_dsds, &lcmd_pkt);
+
+ /* Set total data segment count. */
+ lcmd_pkt.entry_count = (uint8_t)req_cnt;
+
+ /* Specify response queue number where completion should happen */
+ lcmd_pkt.entry_status = (uint8_t) rsp->id;
+
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e,
+ (uint8_t *)cmd->cmnd, cmd->cmd_len);
+ ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3032,
+ (uint8_t *)&lcmd_pkt, REQUEST_ENTRY_SIZE);
+
+ memcpy_toio((void __iomem *)cmd_pkt, &lcmd_pkt, REQUEST_ENTRY_SIZE);
+ wmb();
+
+ /* Adjust ring index. */
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
+ } else
+ req->ring_ptr++;
+
+ sp->flags |= SRB_DMA_VALID;
+
+ /* Set chip new ring index. */
+ WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return QLA_SUCCESS;
+
+queuing_error:
+ if (tot_dsds)
+ scsi_dma_unmap(cmd);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ return QLA_FUNCTION_FAILED;
+}
+
+void
+qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb)
+{
+ struct srb_iocb *fxio = &sp->u.iocb_cmd;
+ scsi_qla_host_t *vha = sp->fcport->vha;
+ struct req_que *req = vha->req;
+ struct tsk_mgmt_entry_fx00 tm_iocb;
+ struct scsi_lun llun;
+
+ memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00));
+ tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00;
+ tm_iocb.entry_count = 1;
+ tm_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle));
+ tm_iocb.handle_hi = 0;
+ tm_iocb.timeout = cpu_to_le16(qla2x00_get_async_timeout(vha) + 2);
+ tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id);
+ tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags);
+ if (tm_iocb.control_flags == cpu_to_le32((uint32_t)TCF_LUN_RESET)) {
+ int_to_scsilun(fxio->u.tmf.lun, &llun);
+ host_to_adap((uint8_t *)&llun, (uint8_t *)&tm_iocb.lun,
+ sizeof(struct scsi_lun));
+ }
+
+ memcpy((void *)ptm_iocb, &tm_iocb,
+ sizeof(struct tsk_mgmt_entry_fx00));
+ wmb();
+}
+
+void
+qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb)
+{
+ struct srb_iocb *fxio = &sp->u.iocb_cmd;
+ scsi_qla_host_t *vha = sp->fcport->vha;
+ struct req_que *req = vha->req;
+ struct abort_iocb_entry_fx00 abt_iocb;
+
+ memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00));
+ abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00;
+ abt_iocb.entry_count = 1;
+ abt_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle));
+ abt_iocb.abort_handle =
+ cpu_to_le32(MAKE_HANDLE(req->id, fxio->u.abt.cmd_hndl));
+ abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id);
+ abt_iocb.req_que_no = cpu_to_le16(req->id);
+
+ memcpy((void *)pabt_iocb, &abt_iocb,
+ sizeof(struct abort_iocb_entry_fx00));
+ wmb();
+}
+
+void
+qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
+{
+ struct srb_iocb *fxio = &sp->u.iocb_cmd;
+ struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
+ struct fc_bsg_job *bsg_job;
+ struct fxdisc_entry_fx00 fx_iocb;
+ uint8_t entry_cnt = 1;
+
+ memset(&fx_iocb, 0, sizeof(struct fxdisc_entry_fx00));
+ fx_iocb.entry_type = FX00_IOCB_TYPE;
+ fx_iocb.handle = cpu_to_le32(sp->handle);
+ fx_iocb.entry_count = entry_cnt;
+
+ if (sp->type == SRB_FXIOCB_DCMD) {
+ fx_iocb.func_num =
+ sp->u.iocb_cmd.u.fxiocb.req_func_type;
+ fx_iocb.adapid = fxio->u.fxiocb.adapter_id;
+ fx_iocb.adapid_hi = fxio->u.fxiocb.adapter_id_hi;
+ fx_iocb.reserved_0 = fxio->u.fxiocb.reserved_0;
+ fx_iocb.reserved_1 = fxio->u.fxiocb.reserved_1;
+ fx_iocb.dataword_extra = fxio->u.fxiocb.req_data_extra;
+
+ if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) {
+ fx_iocb.req_dsdcnt = cpu_to_le16(1);
+ fx_iocb.req_xfrcnt =
+ cpu_to_le16(fxio->u.fxiocb.req_len);
+ fx_iocb.dseg_rq_address[0] =
+ cpu_to_le32(LSD(fxio->u.fxiocb.req_dma_handle));
+ fx_iocb.dseg_rq_address[1] =
+ cpu_to_le32(MSD(fxio->u.fxiocb.req_dma_handle));
+ fx_iocb.dseg_rq_len =
+ cpu_to_le32(fxio->u.fxiocb.req_len);
+ }
+
+ if (fxio->u.fxiocb.flags & SRB_FXDISC_RESP_DMA_VALID) {
+ fx_iocb.rsp_dsdcnt = cpu_to_le16(1);
+ fx_iocb.rsp_xfrcnt =
+ cpu_to_le16(fxio->u.fxiocb.rsp_len);
+ fx_iocb.dseg_rsp_address[0] =
+ cpu_to_le32(LSD(fxio->u.fxiocb.rsp_dma_handle));
+ fx_iocb.dseg_rsp_address[1] =
+ cpu_to_le32(MSD(fxio->u.fxiocb.rsp_dma_handle));
+ fx_iocb.dseg_rsp_len =
+ cpu_to_le32(fxio->u.fxiocb.rsp_len);
+ }
+
+ if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DWRD_VALID) {
+ fx_iocb.dataword = fxio->u.fxiocb.req_data;
+ }
+ fx_iocb.flags = fxio->u.fxiocb.flags;
+ } else {
+ struct scatterlist *sg;
+ bsg_job = sp->u.bsg_job;
+ piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
+ &bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+
+ fx_iocb.func_num = piocb_rqst->func_type;
+ fx_iocb.adapid = piocb_rqst->adapid;
+ fx_iocb.adapid_hi = piocb_rqst->adapid_hi;
+ fx_iocb.reserved_0 = piocb_rqst->reserved_0;
+ fx_iocb.reserved_1 = piocb_rqst->reserved_1;
+ fx_iocb.dataword_extra = piocb_rqst->dataword_extra;
+ fx_iocb.dataword = piocb_rqst->dataword;
+ fx_iocb.req_xfrcnt = piocb_rqst->req_len;
+ fx_iocb.rsp_xfrcnt = piocb_rqst->rsp_len;
+
+ if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) {
+ int avail_dsds, tot_dsds;
+ cont_a64_entry_t lcont_pkt;
+ cont_a64_entry_t *cont_pkt = NULL;
+ __le32 *cur_dsd;
+ int index = 0, cont = 0;
+
+ fx_iocb.req_dsdcnt =
+ cpu_to_le16(bsg_job->request_payload.sg_cnt);
+ tot_dsds =
+ bsg_job->request_payload.sg_cnt;
+ cur_dsd = (__le32 *)&fx_iocb.dseg_rq_address[0];
+ avail_dsds = 1;
+ for_each_sg(bsg_job->request_payload.sg_list, sg,
+ tot_dsds, index) {
+ dma_addr_t sle_dma;
+
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ /*
+ * Five DSDs are available in the Cont.
+ * Type 1 IOCB.
+ */
+ memset(&lcont_pkt, 0,
+ REQUEST_ENTRY_SIZE);
+ cont_pkt =
+ qlafx00_prep_cont_type1_iocb(
+ sp->fcport->vha->req,
+ &lcont_pkt);
+ cur_dsd = (__le32 *)
+ lcont_pkt.dseg_0_address;
+ avail_dsds = 5;
+ cont = 1;
+ entry_cnt++;
+ }
+
+ sle_dma = sg_dma_address(sg);
+ *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ avail_dsds--;
+
+ if (avail_dsds == 0 && cont == 1) {
+ cont = 0;
+ memcpy_toio(
+ (void __iomem *)cont_pkt,
+ &lcont_pkt, REQUEST_ENTRY_SIZE);
+ ql_dump_buffer(
+ ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x3042,
+ (uint8_t *)&lcont_pkt,
+ REQUEST_ENTRY_SIZE);
+ }
+ }
+ if (avail_dsds != 0 && cont == 1) {
+ memcpy_toio((void __iomem *)cont_pkt,
+ &lcont_pkt, REQUEST_ENTRY_SIZE);
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x3043,
+ (uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
+ }
+ }
+
+ if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) {
+ int avail_dsds, tot_dsds;
+ cont_a64_entry_t lcont_pkt;
+ cont_a64_entry_t *cont_pkt = NULL;
+ __le32 *cur_dsd;
+ int index = 0, cont = 0;
+
+ fx_iocb.rsp_dsdcnt =
+ cpu_to_le16(bsg_job->reply_payload.sg_cnt);
+ tot_dsds = bsg_job->reply_payload.sg_cnt;
+ cur_dsd = (__le32 *)&fx_iocb.dseg_rsp_address[0];
+ avail_dsds = 1;
+
+ for_each_sg(bsg_job->reply_payload.sg_list, sg,
+ tot_dsds, index) {
+ dma_addr_t sle_dma;
+
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ /*
+ * Five DSDs are available in the Cont.
+ * Type 1 IOCB.
+ */
+ memset(&lcont_pkt, 0,
+ REQUEST_ENTRY_SIZE);
+ cont_pkt =
+ qlafx00_prep_cont_type1_iocb(
+ sp->fcport->vha->req,
+ &lcont_pkt);
+ cur_dsd = (__le32 *)
+ lcont_pkt.dseg_0_address;
+ avail_dsds = 5;
+ cont = 1;
+ entry_cnt++;
+ }
+
+ sle_dma = sg_dma_address(sg);
+ *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ avail_dsds--;
+
+ if (avail_dsds == 0 && cont == 1) {
+ cont = 0;
+ memcpy_toio((void __iomem *)cont_pkt,
+ &lcont_pkt,
+ REQUEST_ENTRY_SIZE);
+ ql_dump_buffer(
+ ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x3045,
+ (uint8_t *)&lcont_pkt,
+ REQUEST_ENTRY_SIZE);
+ }
+ }
+ if (avail_dsds != 0 && cont == 1) {
+ memcpy_toio((void __iomem *)cont_pkt,
+ &lcont_pkt, REQUEST_ENTRY_SIZE);
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x3046,
+ (uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
+ }
+ }
+
+ if (piocb_rqst->flags & SRB_FXDISC_REQ_DWRD_VALID)
+ fx_iocb.dataword = piocb_rqst->dataword;
+ fx_iocb.flags = piocb_rqst->flags;
+ fx_iocb.entry_count = entry_cnt;
+ }
+
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
+ sp->fcport->vha, 0x3047,
+ (uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00));
+
+ memcpy((void *)pfxiocb, &fx_iocb,
+ sizeof(struct fxdisc_entry_fx00));
+ wmb();
+}
diff --git a/drivers/scsi/qla2xxx/qla_mr.h b/drivers/scsi/qla2xxx/qla_mr.h
new file mode 100644
index 0000000..1a092af
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_mr.h
@@ -0,0 +1,510 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2013 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#ifndef __QLA_MR_H
+#define __QLA_MR_H
+
+/*
+ * The PCI VendorID and DeviceID for our board.
+ */
+#define PCI_DEVICE_ID_QLOGIC_ISPF001 0xF001
+
+/* FX00 specific definitions */
+
+#define FX00_COMMAND_TYPE_7 0x07 /* Command Type 7 entry for 7XXX */
+struct cmd_type_7_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ uint32_t handle; /* System handle. */
+ uint32_t handle_hi;
+
+ __le16 tgt_idx; /* Target Idx. */
+ uint16_t timeout; /* Command timeout. */
+
+ __le16 dseg_count; /* Data segment count. */
+ uint16_t scsi_rsp_dsd_len;
+
+ struct scsi_lun lun; /* LUN (LE). */
+
+ uint8_t cntrl_flags;
+
+ uint8_t task_mgmt_flags; /* Task management flags. */
+
+ uint8_t task;
+
+ uint8_t crn;
+
+ uint8_t fcp_cdb[MAX_CMDSZ]; /* SCSI command words. */
+ __le32 byte_count; /* Total byte count. */
+
+ uint32_t dseg_0_address[2]; /* Data segment 0 address. */
+ uint32_t dseg_0_len; /* Data segment 0 length. */
+};
+
+/*
+ * ISP queue - marker entry structure definition.
+ */
+struct mrk_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t handle_count; /* Handle count. */
+ uint8_t entry_status; /* Entry Status. */
+
+ uint32_t handle; /* System handle. */
+ uint32_t handle_hi; /* System handle. */
+
+ uint16_t tgt_id; /* Target ID. */
+
+ uint8_t modifier; /* Modifier (7-0). */
+ uint8_t reserved_1;
+
+ uint8_t reserved_2[5];
+
+ uint8_t lun[8]; /* FCP LUN (BE). */
+ uint8_t reserved_3[36];
+};
+
+
+#define STATUS_TYPE_FX00 0x01 /* Status entry. */
+struct sts_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ uint32_t handle; /* System handle. */
+ uint32_t handle_hi; /* System handle. */
+
+ __le16 comp_status; /* Completion status. */
+ uint16_t reserved_0; /* OX_ID used by the firmware. */
+
+ __le32 residual_len; /* FW calc residual transfer length. */
+
+ uint16_t reserved_1;
+ uint16_t state_flags; /* State flags. */
+
+ uint16_t reserved_2;
+ __le16 scsi_status; /* SCSI status. */
+
+ uint32_t sense_len; /* FCP SENSE length. */
+ uint8_t data[32]; /* FCP response/sense information. */
+};
+
+
+#define MAX_HANDLE_COUNT 15
+#define MULTI_STATUS_TYPE_FX00 0x0D
+
+struct multi_sts_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t sys_define; /* System defined. */
+ uint8_t handle_count;
+ uint8_t entry_status;
+
+ __le32 handles[MAX_HANDLE_COUNT];
+};
+
+#define TSK_MGMT_IOCB_TYPE_FX00 0x05
+struct tsk_mgmt_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define;
+ uint8_t entry_status; /* Entry Status. */
+
+ __le32 handle; /* System handle. */
+
+ uint32_t handle_hi; /* System handle. */
+
+ __le16 tgt_id; /* Target Idx. */
+
+ uint16_t reserved_1;
+
+ uint16_t delay; /* Activity delay in seconds. */
+
+ __le16 timeout; /* Command timeout. */
+
+ struct scsi_lun lun; /* LUN (LE). */
+
+ __le32 control_flags; /* Control Flags. */
+
+ uint8_t reserved_2[32];
+};
+
+
+#define ABORT_IOCB_TYPE_FX00 0x08 /* Abort IOCB status. */
+struct abort_iocb_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ __le32 handle; /* System handle. */
+ __le32 handle_hi; /* System handle. */
+
+ __le16 tgt_id_sts; /* Completion status. */
+ __le16 options;
+
+ __le32 abort_handle; /* System handle. */
+ __le32 abort_handle_hi; /* System handle. */
+
+ __le16 req_que_no;
+ uint8_t reserved_1[38];
+};
+
+#define IOCTL_IOSB_TYPE_FX00 0x0C
+struct ioctl_iocb_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ uint32_t handle; /* System handle. */
+ uint32_t reserved_0; /* System handle. */
+
+ uint16_t comp_func_num;
+ __le16 fw_iotcl_flags;
+
+ __le32 dataword_r; /* Data word returned */
+ uint32_t adapid; /* Adapter ID */
+ uint32_t adapid_hi; /* Adapter ID high */
+ uint32_t reserved_1;
+
+ __le32 seq_no;
+ uint8_t reserved_2[20];
+ uint32_t residuallen;
+ __le32 status;
+};
+
+#define STATUS_CONT_TYPE_FX00 0x04
+
+#define FX00_IOCB_TYPE 0x0B
+struct fxdisc_entry_fx00 {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System Defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ __le32 handle; /* System handle. */
+ __le32 reserved_0; /* System handle. */
+
+ __le16 func_num;
+ __le16 req_xfrcnt;
+ __le16 req_dsdcnt;
+ __le16 rsp_xfrcnt;
+ __le16 rsp_dsdcnt;
+ uint8_t flags;
+ uint8_t reserved_1;
+
+ __le32 dseg_rq_address[2]; /* Data segment 0 address. */
+ __le32 dseg_rq_len; /* Data segment 0 length. */
+ __le32 dseg_rsp_address[2]; /* Data segment 1 address. */
+ __le32 dseg_rsp_len; /* Data segment 1 length. */
+
+ __le32 dataword;
+ __le32 adapid;
+ __le32 adapid_hi;
+ __le32 dataword_extra;
+};
+
+struct qlafx00_tgt_node_info {
+ uint8_t tgt_node_wwpn[WWN_SIZE];
+ uint8_t tgt_node_wwnn[WWN_SIZE];
+ uint32_t tgt_node_state;
+ uint8_t reserved[128];
+ uint32_t reserved_1[8];
+ uint64_t reserved_2[4];
+} __packed;
+
+#define QLAFX00_TGT_NODE_INFO sizeof(struct qlafx00_tgt_node_info)
+
+#define QLAFX00_LINK_STATUS_DOWN 0x10
+#define QLAFX00_LINK_STATUS_UP 0x11
+
+#define QLAFX00_PORT_SPEED_2G 0x2
+#define QLAFX00_PORT_SPEED_4G 0x4
+#define QLAFX00_PORT_SPEED_8G 0x8
+#define QLAFX00_PORT_SPEED_10G 0xa
+struct port_info_data {
+ uint8_t port_state;
+ uint8_t port_type;
+ uint16_t port_identifier;
+ uint32_t up_port_state;
+ uint8_t fw_ver_num[32];
+ uint8_t portal_attrib;
+ uint16_t host_option;
+ uint8_t reset_delay;
+ uint8_t pdwn_retry_cnt;
+ uint16_t max_luns2tgt;
+ uint8_t risc_ver;
+ uint8_t pconn_option;
+ uint16_t risc_option;
+ uint16_t max_frame_len;
+ uint16_t max_iocb_alloc;
+ uint16_t exec_throttle;
+ uint8_t retry_cnt;
+ uint8_t retry_delay;
+ uint8_t port_name[8];
+ uint8_t port_id[3];
+ uint8_t link_status;
+ uint8_t plink_rate;
+ uint32_t link_config;
+ uint16_t adap_haddr;
+ uint8_t tgt_disc;
+ uint8_t log_tout;
+ uint8_t node_name[8];
+ uint16_t erisc_opt1;
+ uint8_t resp_acc_tmr;
+ uint8_t intr_del_tmr;
+ uint8_t erisc_opt2;
+ uint8_t alt_port_name[8];
+ uint8_t alt_node_name[8];
+ uint8_t link_down_tout;
+ uint8_t conn_type;
+ uint8_t fc_fw_mode;
+ uint32_t uiReserved[48];
+} __packed;
+
+/* OS Type Designations */
+#define OS_TYPE_UNKNOWN 0
+#define OS_TYPE_LINUX 2
+
+/* Linux Info */
+#define SYSNAME_LENGTH 128
+#define NODENAME_LENGTH 64
+#define RELEASE_LENGTH 64
+#define VERSION_LENGTH 64
+#define MACHINE_LENGTH 64
+#define DOMNAME_LENGTH 64
+
+struct host_system_info {
+ uint32_t os_type;
+ char sysname[SYSNAME_LENGTH];
+ char nodename[NODENAME_LENGTH];
+ char release[RELEASE_LENGTH];
+ char version[VERSION_LENGTH];
+ char machine[MACHINE_LENGTH];
+ char domainname[DOMNAME_LENGTH];
+ char hostdriver[VERSION_LENGTH];
+ uint32_t reserved[64];
+} __packed;
+
+struct register_host_info {
+ struct host_system_info hsi; /* host system info */
+ uint64_t utc; /* UTC (system time) */
+ uint32_t reserved[64]; /* future additions */
+} __packed;
+
+
+#define QLAFX00_PORT_DATA_INFO (sizeof(struct port_info_data))
+#define QLAFX00_TGT_NODE_LIST_SIZE (sizeof(uint32_t) * 32)
+
+struct config_info_data {
+ uint8_t product_name[256];
+ uint8_t symbolic_name[64];
+ uint8_t serial_num[32];
+ uint8_t hw_version[16];
+ uint8_t fw_version[16];
+ uint8_t uboot_version[16];
+ uint8_t fru_serial_num[32];
+
+ uint8_t fc_port_count;
+ uint8_t iscsi_port_count;
+ uint8_t reserved1[2];
+
+ uint8_t mode;
+ uint8_t log_level;
+ uint8_t reserved2[2];
+
+ uint32_t log_size;
+
+ uint8_t tgt_pres_mode;
+ uint8_t iqn_flags;
+ uint8_t lun_mapping;
+
+ uint64_t adapter_id;
+
+ uint32_t cluster_key_len;
+ uint8_t cluster_key[10];
+
+ uint64_t cluster_master_id;
+ uint64_t cluster_slave_id;
+ uint8_t cluster_flags;
+} __packed;
+
+#define FXDISC_GET_CONFIG_INFO 0x01
+#define FXDISC_GET_PORT_INFO 0x02
+#define FXDISC_GET_TGT_NODE_INFO 0x80
+#define FXDISC_GET_TGT_NODE_LIST 0x81
+#define FXDISC_REG_HOST_INFO 0x99
+
+#define QLAFX00_HBA_ICNTRL_REG 0x21B08
+#define QLAFX00_ICR_ENB_MASK 0x80000000
+#define QLAFX00_ICR_DIS_MASK 0x7fffffff
+#define QLAFX00_HST_RST_REG 0x18264
+#define QLAFX00_HST_TO_HBA_REG 0x20A04
+#define QLAFX00_HBA_TO_HOST_REG 0x21B70
+#define QLAFX00_HST_INT_STS_BITS 0x7
+#define QLAFX00_BAR1_BASE_ADDR_REG 0x40018
+#define QLAFX00_PEX0_WIN0_BASE_ADDR_REG 0x41824
+
+#define QLAFX00_INTR_MB_CMPLT 0x1
+#define QLAFX00_INTR_RSP_CMPLT 0x2
+#define QLAFX00_INTR_MB_RSP_CMPLT 0x3
+#define QLAFX00_INTR_ASYNC_CMPLT 0x4
+#define QLAFX00_INTR_MB_ASYNC_CMPLT 0x5
+#define QLAFX00_INTR_RSP_ASYNC_CMPLT 0x6
+#define QLAFX00_INTR_ALL_CMPLT 0x7
+
+#define QLAFX00_MBA_SYSTEM_ERR 0x8002
+#define QLAFX00_MBA_LINK_UP 0x8011
+#define QLAFX00_MBA_LINK_DOWN 0x8012
+#define QLAFX00_MBA_PORT_UPDATE 0x8014
+#define QLAFX00_MBA_SHUTDOWN_RQSTD 0x8062
+
+#define SOC_SW_RST_CONTROL_REG_CORE0 0x0020800
+#define SOC_FABRIC_RST_CONTROL_REG 0x0020840
+#define SOC_FABRIC_CONTROL_REG 0x0020200
+#define SOC_FABRIC_CONFIG_REG 0x0020204
+
+#define SOC_INTERRUPT_SOURCE_I_CONTROL_REG 0x0020B00
+#define SOC_CORE_TIMER_REG 0x0021850
+#define SOC_IRQ_ACK_REG 0x00218b4
+
+#define CONTINUE_A64_TYPE_FX00 0x03 /* Continuation entry. */
+
+#define QLAFX00_SET_HST_INTR(ha, value) \
+ WRT_REG_DWORD((ha)->cregbase + QLAFX00_HST_TO_HBA_REG, \
+ value)
+
+#define QLAFX00_CLR_HST_INTR(ha, value) \
+ WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG, \
+ ~value)
+
+#define QLAFX00_RD_INTR_REG(ha) \
+ RD_REG_DWORD((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG)
+
+#define QLAFX00_CLR_INTR_REG(ha, value) \
+ WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG, \
+ ~value)
+
+#define QLAFX00_SET_HBA_SOC_REG(ha, off, val)\
+ WRT_REG_DWORD((ha)->cregbase + off, val)
+
+#define QLAFX00_GET_HBA_SOC_REG(ha, off)\
+ RD_REG_DWORD((ha)->cregbase + off)
+
+#define QLAFX00_HBA_RST_REG(ha, val)\
+ WRT_REG_DWORD((ha)->cregbase + QLAFX00_HST_RST_REG, val)
+
+#define QLAFX00_RD_ICNTRL_REG(ha) \
+ RD_REG_DWORD((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG)
+
+#define QLAFX00_ENABLE_ICNTRL_REG(ha) \
+ WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG, \
+ (QLAFX00_GET_HBA_SOC_REG(ha, QLAFX00_HBA_ICNTRL_REG) | \
+ QLAFX00_ICR_ENB_MASK))
+
+#define QLAFX00_DISABLE_ICNTRL_REG(ha) \
+ WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG, \
+ (QLAFX00_GET_HBA_SOC_REG(ha, QLAFX00_HBA_ICNTRL_REG) & \
+ QLAFX00_ICR_DIS_MASK))
+
+#define QLAFX00_RD_REG(ha, off) \
+ RD_REG_DWORD((ha)->cregbase + off)
+
+#define QLAFX00_WR_REG(ha, off, val) \
+ WRT_REG_DWORD((ha)->cregbase + off, val)
+
+struct qla_mt_iocb_rqst_fx00 {
+ __le32 reserved_0;
+
+ __le16 func_type;
+ uint8_t flags;
+ uint8_t reserved_1;
+
+ __le32 dataword;
+
+ __le32 adapid;
+ __le32 adapid_hi;
+
+ __le32 dataword_extra;
+
+ __le32 req_len;
+
+ __le32 rsp_len;
+};
+
+struct qla_mt_iocb_rsp_fx00 {
+ uint32_t reserved_1;
+
+ uint16_t func_type;
+ __le16 ioctl_flags;
+
+ __le32 ioctl_data;
+
+ uint32_t adapid;
+ uint32_t adapid_hi;
+
+ uint32_t reserved_2;
+ __le32 seq_number;
+
+ uint8_t reserved_3[20];
+
+ int32_t res_count;
+
+ __le32 status;
+};
+
+
+#define MAILBOX_REGISTER_COUNT_FX00 16
+#define AEN_MAILBOX_REGISTER_COUNT_FX00 8
+#define MAX_FIBRE_DEVICES_FX00 512
+#define MAX_LUNS_FX00 0x1024
+#define MAX_TARGETS_FX00 MAX_ISA_DEVICES
+#define REQUEST_ENTRY_CNT_FX00 512 /* Number of request entries. */
+#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
+
+/*
+ * Firmware state codes for QLAFX00 adapters
+ */
+#define FSTATE_FX00_CONFIG_WAIT 0x0000 /* Waiting for driver to issue
+ * Initialize FW Mbox cmd
+ */
+#define FSTATE_FX00_INITIALIZED 0x1000 /* FW has been initialized by
+ * the driver
+ */
+
+#define FX00_DEF_RATOV 10
+
+struct mr_data_fx00 {
+ uint8_t product_name[256];
+ uint8_t symbolic_name[64];
+ uint8_t serial_num[32];
+ uint8_t hw_version[16];
+ uint8_t fw_version[16];
+ uint8_t uboot_version[16];
+ uint8_t fru_serial_num[32];
+ fc_port_t fcport; /* fcport used for requests
+ * that are not linked
+ * to a particular target
+ */
+ uint8_t fw_hbt_en;
+ uint8_t fw_hbt_cnt;
+ uint8_t fw_hbt_miss_cnt;
+ uint32_t old_fw_hbt_cnt;
+ uint16_t fw_reset_timer_tick;
+ uint8_t fw_reset_timer_exp;
+ uint32_t old_aenmbx0_state;
+};
+
+#define QLAFX00_LOOP_DOWN_TIME 615 /* 600 */
+#define QLAFX00_HEARTBEAT_INTERVAL 6 /* number of seconds */
+#define QLAFX00_HEARTBEAT_MISS_CNT 3 /* number of miss */
+#define QLAFX00_RESET_INTERVAL 120 /* number of seconds */
+#define QLAFX00_MAX_RESET_INTERVAL 600 /* number of seconds */
+#endif
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 3e3f593..cce0cd0 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -847,14 +847,21 @@ static int
qla82xx_rom_lock(struct qla_hw_data *ha)
{
int done = 0, timeout = 0;
+ uint32_t lock_owner = 0;
+ scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
while (!done) {
/* acquire semaphore2 from PCI HW block */
done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK));
if (done == 1)
break;
- if (timeout >= qla82xx_rom_lock_timeout)
+ if (timeout >= qla82xx_rom_lock_timeout) {
+ lock_owner = qla82xx_rd_32(ha, QLA82XX_ROM_LOCK_ID);
+ ql_dbg(ql_dbg_p3p, vha, 0xb085,
+ "Failed to acquire rom lock, acquired by %d.\n",
+ lock_owner);
return -1;
+ }
timeout++;
}
qla82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER);
@@ -2067,9 +2074,6 @@ qla82xx_intr_handler(int irq, void *dev_id)
}
WRT_REG_DWORD(&reg->host_int, 0);
}
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (!ha->flags.msi_enabled)
- qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
#ifdef QL_DEBUG_LEVEL_17
if (!irq && ha->flags.eeh_busy)
@@ -2078,11 +2082,12 @@ qla82xx_intr_handler(int irq, void *dev_id)
status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
#endif
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
- set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- complete(&ha->mbx_intr_comp);
- }
+ qla2x00_handle_mbx_completion(ha, status);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ if (!ha->flags.msi_enabled)
+ qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
+
return IRQ_HANDLED;
}
@@ -2142,8 +2147,6 @@ qla82xx_msix_default(int irq, void *dev_id)
WRT_REG_DWORD(&reg->host_int, 0);
} while (0);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
#ifdef QL_DEBUG_LEVEL_17
if (!irq && ha->flags.eeh_busy)
ql_log(ql_log_warn, vha, 0x5044,
@@ -2151,11 +2154,9 @@ qla82xx_msix_default(int irq, void *dev_id)
status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat);
#endif
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
- (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
- set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- complete(&ha->mbx_intr_comp);
- }
+ qla2x00_handle_mbx_completion(ha, status);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
return IRQ_HANDLED;
}
@@ -3338,7 +3339,7 @@ void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha)
ha->flags.mbox_busy = 0;
ql_log(ql_log_warn, vha, 0x6010,
"Doing premature completion of mbx command.\n");
- if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags))
+ if (test_and_clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags))
complete(&ha->mbx_intr_comp);
}
}
@@ -3629,7 +3630,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
req = ha->req_q_map[que];
if (!req)
continue;
- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
if (!sp->u.scmd.ctx ||
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 6c953e8..d268e84 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -897,7 +897,7 @@ struct ct6_dsd {
#define FLT_REG_BOOT_CODE_82XX 0x78
#define FLT_REG_FW_82XX 0x74
#define FLT_REG_GOLD_FW_82XX 0x75
-#define FLT_REG_VPD_82XX 0x81
+#define FLT_REG_VPD_8XXX 0x81
#define FA_VPD_SIZE_82XX 0x400
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3a1661c..3e21e9f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -47,6 +47,7 @@ MODULE_PARM_DESC(ql2xenableclass2,
"Specify if Class 2 operations are supported from the very "
"beginning. Default is 0 - class 2 not supported.");
+
int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO);
MODULE_PARM_DESC(ql2xlogintimeout,
@@ -103,16 +104,13 @@ MODULE_PARM_DESC(ql2xshiftctondsd,
"Set to control shifting of command type processing "
"based on total number of SG elements.");
-static void qla2x00_free_device(scsi_qla_host_t *);
-
int ql2xfdmienable=1;
module_param(ql2xfdmienable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xfdmienable,
"Enables FDMI registrations. "
"0 - no FDMI. Default is 1 - perform FDMI.");
-#define MAX_Q_DEPTH 32
-static int ql2xmaxqdepth = MAX_Q_DEPTH;
+int ql2xmaxqdepth = MAX_Q_DEPTH;
module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xmaxqdepth,
"Maximum queue depth to set for each LUN. "
@@ -237,6 +235,7 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
static int qla2x00_change_queue_type(struct scsi_device *, int);
+static void qla2x00_free_device(scsi_qla_host_t *);
struct scsi_host_template qla2xxx_driver_template = {
.module = THIS_MODULE,
@@ -355,22 +354,35 @@ fail_req_map:
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
{
- if (req && req->ring)
+ if (IS_QLAFX00(ha)) {
+ if (req && req->ring_fx00)
+ dma_free_coherent(&ha->pdev->dev,
+ (req->length_fx00 + 1) * sizeof(request_t),
+ req->ring_fx00, req->dma_fx00);
+ } else if (req && req->ring)
dma_free_coherent(&ha->pdev->dev,
(req->length + 1) * sizeof(request_t),
req->ring, req->dma);
+ if (req)
+ kfree(req->outstanding_cmds);
+
kfree(req);
req = NULL;
}
static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
{
- if (rsp && rsp->ring)
+ if (IS_QLAFX00(ha)) {
+ if (rsp && rsp->ring)
+ dma_free_coherent(&ha->pdev->dev,
+ (rsp->length_fx00 + 1) * sizeof(request_t),
+ rsp->ring_fx00, rsp->dma_fx00);
+ } else if (rsp && rsp->ring) {
dma_free_coherent(&ha->pdev->dev,
(rsp->length + 1) * sizeof(response_t),
rsp->ring, rsp->dma);
-
+ }
kfree(rsp);
rsp = NULL;
}
@@ -628,7 +640,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr)
}
CMD_SP(cmd) = NULL;
- mempool_free(sp, ha->srb_mempool);
+ qla2x00_rel_sp(sp->fcport->vha, sp);
}
static void
@@ -655,6 +667,9 @@ qla2x00_sp_compl(void *data, void *ptr, int res)
cmd->scsi_done(cmd);
}
+/* If we are SP1 here, we need to still take and release the host_lock as SP1
+ * does not have the changes necessary to avoid taking host->host_lock.
+ */
static int
qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
@@ -716,9 +731,11 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto qc24_target_busy;
}
- sp = qla2x00_get_sp(base_vha, fcport, GFP_ATOMIC);
- if (!sp)
+ sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+ if (!sp) {
+ set_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags);
goto qc24_host_busy;
+ }
sp->u.scmd.cmd = cmd;
sp->type = SRB_SCSI_CMD;
@@ -731,6 +748,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3013,
"Start scsi failed rval=%d for cmd=%p.\n", rval, cmd);
+ set_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags);
goto qc24_host_busy_free_sp;
}
@@ -1010,7 +1028,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
spin_lock_irqsave(&ha->hardware_lock, flags);
req = vha->req;
for (cnt = 1; status == QLA_SUCCESS &&
- cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+ cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (!sp)
continue;
@@ -1299,15 +1317,18 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
}
}
+ if (IS_QLAFX00(ha))
+ return QLA_SUCCESS;
+
if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) {
+ atomic_set(&vha->loop_state, LOOP_DOWN);
+ atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
+ qla2x00_mark_all_devices_lost(vha, 0);
ret = qla2x00_full_login_lip(vha);
if (ret != QLA_SUCCESS) {
ql_dbg(ql_dbg_taskm, vha, 0x802d,
"full_login_lip=%d.\n", ret);
}
- atomic_set(&vha->loop_state, LOOP_DOWN);
- atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(vha, 0);
}
if (ha->flags.enable_lip_reset) {
@@ -1337,7 +1358,9 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
req = ha->req_q_map[que];
if (!req)
continue;
- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+ if (!req->outstanding_cmds)
+ continue;
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
req->outstanding_cmds[cnt] = NULL;
@@ -1453,6 +1476,81 @@ qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
return tag_type;
}
+static void
+qla2x00_host_ramp_down_queuedepth(scsi_qla_host_t *vha)
+{
+ scsi_qla_host_t *vp;
+ struct Scsi_Host *shost;
+ struct scsi_device *sdev;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+
+ ha->host_last_rampdown_time = jiffies;
+
+ if (ha->cfg_lun_q_depth <= vha->host->cmd_per_lun)
+ return;
+
+ if ((ha->cfg_lun_q_depth / 2) < vha->host->cmd_per_lun)
+ ha->cfg_lun_q_depth = vha->host->cmd_per_lun;
+ else
+ ha->cfg_lun_q_depth = ha->cfg_lun_q_depth / 2;
+
+ /*
+ * Geometrically ramp down the queue depth for all devices on this
+ * adapter
+ */
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_for_each_entry(vp, &ha->vp_list, list) {
+ shost = vp->host;
+ shost_for_each_device(sdev, shost) {
+ if (sdev->queue_depth > shost->cmd_per_lun) {
+ if (sdev->queue_depth < ha->cfg_lun_q_depth)
+ continue;
+ ql_log(ql_log_warn, vp, 0x3031,
+ "%ld:%d:%d: Ramping down queue depth to %d",
+ vp->host_no, sdev->id, sdev->lun,
+ ha->cfg_lun_q_depth);
+ qla2x00_change_queue_depth(sdev,
+ ha->cfg_lun_q_depth, SCSI_QDEPTH_DEFAULT);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+ return;
+}
+
+static void
+qla2x00_host_ramp_up_queuedepth(scsi_qla_host_t *vha)
+{
+ scsi_qla_host_t *vp;
+ struct Scsi_Host *shost;
+ struct scsi_device *sdev;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+
+ ha->host_last_rampup_time = jiffies;
+ ha->cfg_lun_q_depth++;
+
+ /*
+ * Linearly ramp up the queue depth for all devices on this
+ * adapter
+ */
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_for_each_entry(vp, &ha->vp_list, list) {
+ shost = vp->host;
+ shost_for_each_device(sdev, shost) {
+ if (sdev->queue_depth > ha->cfg_lun_q_depth)
+ continue;
+ qla2x00_change_queue_depth(sdev, ha->cfg_lun_q_depth,
+ SCSI_QDEPTH_RAMP_UP);
+ }
+ }
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+ return;
+}
+
/**
* qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
* @ha: HA context
@@ -1730,6 +1828,9 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
mqiobase_exit:
ha->msix_count = ha->max_rsp_queues + 1;
+
+ qlt_83xx_iospace_config(ha);
+
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011f,
"MSIX Count:%d.\n", ha->msix_count);
return 0;
@@ -1773,6 +1874,7 @@ static struct isp_operations qla2100_isp_ops = {
.start_scsi = qla2x00_start_scsi,
.abort_isp = qla2x00_abort_isp,
.iospace_config = qla2x00_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
};
static struct isp_operations qla2300_isp_ops = {
@@ -1810,6 +1912,7 @@ static struct isp_operations qla2300_isp_ops = {
.start_scsi = qla2x00_start_scsi,
.abort_isp = qla2x00_abort_isp,
.iospace_config = qla2x00_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
};
static struct isp_operations qla24xx_isp_ops = {
@@ -1847,6 +1950,7 @@ static struct isp_operations qla24xx_isp_ops = {
.start_scsi = qla24xx_start_scsi,
.abort_isp = qla2x00_abort_isp,
.iospace_config = qla2x00_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
};
static struct isp_operations qla25xx_isp_ops = {
@@ -1884,6 +1988,7 @@ static struct isp_operations qla25xx_isp_ops = {
.start_scsi = qla24xx_dif_start_scsi,
.abort_isp = qla2x00_abort_isp,
.iospace_config = qla2x00_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
};
static struct isp_operations qla81xx_isp_ops = {
@@ -1921,6 +2026,7 @@ static struct isp_operations qla81xx_isp_ops = {
.start_scsi = qla24xx_dif_start_scsi,
.abort_isp = qla2x00_abort_isp,
.iospace_config = qla2x00_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
};
static struct isp_operations qla82xx_isp_ops = {
@@ -1958,6 +2064,7 @@ static struct isp_operations qla82xx_isp_ops = {
.start_scsi = qla82xx_start_scsi,
.abort_isp = qla82xx_abort_isp,
.iospace_config = qla82xx_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
};
static struct isp_operations qla83xx_isp_ops = {
@@ -1995,6 +2102,45 @@ static struct isp_operations qla83xx_isp_ops = {
.start_scsi = qla24xx_dif_start_scsi,
.abort_isp = qla2x00_abort_isp,
.iospace_config = qla83xx_iospace_config,
+ .initialize_adapter = qla2x00_initialize_adapter,
+};
+
+static struct isp_operations qlafx00_isp_ops = {
+ .pci_config = qlafx00_pci_config,
+ .reset_chip = qlafx00_soft_reset,
+ .chip_diag = qlafx00_chip_diag,
+ .config_rings = qlafx00_config_rings,
+ .reset_adapter = qlafx00_soft_reset,
+ .nvram_config = NULL,
+ .update_fw_options = NULL,
+ .load_risc = NULL,
+ .pci_info_str = qlafx00_pci_info_str,
+ .fw_version_str = qlafx00_fw_version_str,
+ .intr_handler = qlafx00_intr_handler,
+ .enable_intrs = qlafx00_enable_intrs,
+ .disable_intrs = qlafx00_disable_intrs,
+ .abort_command = qlafx00_abort_command,
+ .target_reset = qlafx00_abort_target,
+ .lun_reset = qlafx00_lun_reset,
+ .fabric_login = NULL,
+ .fabric_logout = NULL,
+ .calc_req_entries = NULL,
+ .build_iocbs = NULL,
+ .prep_ms_iocb = qla24xx_prep_ms_iocb,
+ .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb,
+ .read_nvram = qla24xx_read_nvram_data,
+ .write_nvram = qla24xx_write_nvram_data,
+ .fw_dump = NULL,
+ .beacon_on = qla24xx_beacon_on,
+ .beacon_off = qla24xx_beacon_off,
+ .beacon_blink = NULL,
+ .read_optrom = qla24xx_read_optrom_data,
+ .write_optrom = qla24xx_write_optrom_data,
+ .get_flash_version = qla24xx_get_flash_version,
+ .start_scsi = qlafx00_start_scsi,
+ .abort_isp = qlafx00_abort_isp,
+ .iospace_config = qlafx00_iospace_config,
+ .initialize_adapter = qlafx00_initialize_adapter,
};
static inline void
@@ -2107,6 +2253,9 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->device_type |= DT_T10_PI;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
+ case PCI_DEVICE_ID_QLOGIC_ISPF001:
+ ha->device_type |= DT_ISPFX00;
+ break;
}
if (IS_QLA82XX(ha))
@@ -2154,7 +2303,7 @@ qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
/*
* PCI driver interface
*/
-static int __devinit
+static int
qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
int ret = -ENODEV;
@@ -2180,7 +2329,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2031 ||
- pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031) {
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
mem_only = 1;
ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
@@ -2230,6 +2380,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->init_cb_size = sizeof(init_cb_t);
ha->link_data_rate = PORT_SPEED_UNKNOWN;
ha->optrom_size = OPTROM_SIZE_2300;
+ ha->cfg_lun_q_depth = ql2xmaxqdepth;
/* Assign ISP specific operations. */
if (IS_QLA2100(ha)) {
@@ -2307,6 +2458,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->mbx_count = MAILBOX_REGISTER_COUNT;
req_length = REQUEST_ENTRY_CNT_24XX;
rsp_length = RESPONSE_ENTRY_CNT_2300;
+ ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
ha->gid_list_info_size = 8;
@@ -2338,6 +2490,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->mbx_count = MAILBOX_REGISTER_COUNT;
req_length = REQUEST_ENTRY_CNT_24XX;
rsp_length = RESPONSE_ENTRY_CNT_2300;
+ ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
ha->gid_list_info_size = 8;
@@ -2348,6 +2501,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
ha->nvram_conf_off = ~0;
ha->nvram_data_off = ~0;
+ } else if (IS_QLAFX00(ha)) {
+ ha->max_fibre_devices = MAX_FIBRE_DEVICES_FX00;
+ ha->mbx_count = MAILBOX_REGISTER_COUNT_FX00;
+ ha->aen_mbx_count = AEN_MAILBOX_REGISTER_COUNT_FX00;
+ req_length = REQUEST_ENTRY_CNT_FX00;
+ rsp_length = RESPONSE_ENTRY_CNT_FX00;
+ ha->init_cb_size = sizeof(struct init_cb_fx);
+ ha->isp_ops = &qlafx00_isp_ops;
+ ha->port_down_retry_count = 30; /* default value */
+ ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
+ ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
+ ha->mr.fw_hbt_en = 1;
}
ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
@@ -2377,6 +2542,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
complete(&ha->mbx_cmd_comp);
init_completion(&ha->mbx_intr_comp);
init_completion(&ha->dcbx_comp);
+ init_completion(&ha->lb_portup_comp);
set_bit(0, (unsigned long *) ha->vp_idx_map);
@@ -2411,13 +2577,24 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host = base_vha->host;
base_vha->req = req;
- host->can_queue = req->length + 128;
+ if (IS_QLAFX00(ha))
+ host->can_queue = 1024;
+ else
+ host->can_queue = req->length + 128;
if (IS_QLA2XXX_MIDTYPE(ha))
base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
else
base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
base_vha->vp_idx;
+ /* Setup fcport template structure. */
+ ha->mr.fcport.vha = base_vha;
+ ha->mr.fcport.port_type = FCT_UNKNOWN;
+ ha->mr.fcport.loop_id = FC_NO_LOOP_ID;
+ qla2x00_set_fcport_state(&ha->mr.fcport, FCS_UNCONFIGURED);
+ ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED;
+ ha->mr.fcport.scan_state = 1;
+
/* Set the SG table size based on ISP type */
if (!IS_FWI2_CAPABLE(ha)) {
if (IS_QLA2100(ha))
@@ -2473,6 +2650,13 @@ que_init:
rsp->req = req;
req->rsp = rsp;
+ if (IS_QLAFX00(ha)) {
+ ha->rsp_q_map[0] = rsp;
+ ha->req_q_map[0] = req;
+ set_bit(0, ha->req_qid_map);
+ set_bit(0, ha->rsp_qid_map);
+ }
+
/* FWI2-capable only. */
req->req_q_in = &ha->iobase->isp24.req_q_in;
req->req_q_out = &ha->iobase->isp24.req_q_out;
@@ -2485,6 +2669,13 @@ que_init:
rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out;
}
+ if (IS_QLAFX00(ha)) {
+ req->req_q_in = &ha->iobase->ispfx00.req_q_in;
+ req->req_q_out = &ha->iobase->ispfx00.req_q_out;
+ rsp->rsp_q_in = &ha->iobase->ispfx00.rsp_q_in;
+ rsp->rsp_q_out = &ha->iobase->ispfx00.rsp_q_out;
+ }
+
if (IS_QLA82XX(ha)) {
req->req_q_out = &ha->iobase->isp82.req_q_out[0];
rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0];
@@ -2506,7 +2697,7 @@ que_init:
"req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
- if (qla2x00_initialize_adapter(base_vha)) {
+ if (ha->isp_ops->initialize_adapter(base_vha)) {
ql_log(ql_log_fatal, base_vha, 0x00d6,
"Failed to initialize adapter - Adapter flags %x.\n",
base_vha->device_flags);
@@ -2631,13 +2822,24 @@ skip_dpc:
qla2x00_alloc_sysfs_attr(base_vha);
+ if (IS_QLAFX00(ha)) {
+ ret = qlafx00_fx_disc(base_vha,
+ &base_vha->hw->mr.fcport, FXDISC_GET_CONFIG_INFO);
+
+ ret = qlafx00_fx_disc(base_vha,
+ &base_vha->hw->mr.fcport, FXDISC_GET_PORT_INFO);
+
+ /* Register system information */
+ ret = qlafx00_fx_disc(base_vha,
+ &base_vha->hw->mr.fcport, FXDISC_REG_HOST_INFO);
+ }
+
qla2x00_init_host_attr(base_vha);
qla2x00_dfs_setup(base_vha);
ql_log(ql_log_info, base_vha, 0x00fb,
- "QLogic %s - %s.\n",
- ha->model_number, ha->model_desc ? ha->model_desc : "");
+ "QLogic %s - %s.\n", ha->model_number, ha->model_desc);
ql_log(ql_log_info, base_vha, 0x00fc,
"ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n",
pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info),
@@ -2688,6 +2890,8 @@ iospace_config_failed:
} else {
if (ha->iobase)
iounmap(ha->iobase);
+ if (ha->cregbase)
+ iounmap(ha->cregbase);
}
pci_release_selected_regions(ha->pdev, ha->bars);
kfree(ha);
@@ -2720,6 +2924,9 @@ qla2x00_shutdown(struct pci_dev *pdev)
scsi_qla_host_t *vha;
struct qla_hw_data *ha;
+ if (!atomic_read(&pdev->enable_cnt))
+ return;
+
vha = pci_get_drvdata(pdev);
ha = vha->hw;
@@ -2772,14 +2979,12 @@ qla2x00_remove_one(struct pci_dev *pdev)
set_bit(UNLOADING, &base_vha->dpc_flags);
mutex_lock(&ha->vport_lock);
while (ha->cur_vport_count) {
- struct Scsi_Host *scsi_host;
-
spin_lock_irqsave(&ha->vport_slock, flags);
BUG_ON(base_vha->list.next == &ha->vp_list);
/* This assumes first entry in ha->vp_list is always base vha */
vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list);
- scsi_host = scsi_host_get(vha->host);
+ scsi_host_get(vha->host);
spin_unlock_irqrestore(&ha->vport_slock, flags);
mutex_unlock(&ha->vport_lock);
@@ -2868,6 +3073,9 @@ qla2x00_remove_one(struct pci_dev *pdev)
if (ha->iobase)
iounmap(ha->iobase);
+ if (ha->cregbase)
+ iounmap(ha->cregbase);
+
if (ha->mqiobase)
iounmap(ha->mqiobase);
@@ -2976,6 +3184,12 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
int do_login, int defer)
{
+ if (IS_QLAFX00(vha->hw)) {
+ qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
+ qla2x00_schedule_rport_del(vha, fcport, defer);
+ return;
+ }
+
if (atomic_read(&fcport->state) == FCS_ONLINE &&
vha->vp_idx == fcport->vha->vp_idx) {
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
@@ -3618,6 +3832,22 @@ qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code)
kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp);
}
+int
+qlafx00_post_aenfx_work(struct scsi_qla_host *vha, uint32_t evtcode,
+ uint32_t *data, int cnt)
+{
+ struct qla_work_evt *e;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_AENFX);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.aenfx.evtcode = evtcode;
+ e->u.aenfx.count = cnt;
+ memcpy(e->u.aenfx.mbx, data, sizeof(*data) * cnt);
+ return qla2x00_post_work(vha, e);
+}
+
void
qla2x00_do_work(struct scsi_qla_host *vha)
{
@@ -3666,6 +3896,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
case QLA_EVT_UEVENT:
qla2x00_uevent_emit(vha, e->u.uevent.code);
break;
+ case QLA_EVT_AENFX:
+ qlafx00_process_aen(vha, e);
+ break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
@@ -3974,6 +4207,8 @@ qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha)
uint32_t idc_lck_rcvry_stage_mask = 0x3;
uint32_t idc_lck_rcvry_owner_mask = 0x3c;
struct qla_hw_data *ha = base_vha->hw;
+ ql_dbg(ql_dbg_p3p, base_vha, 0xb086,
+ "Trying force recovery of the IDC lock.\n");
rval = qla83xx_rd_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY, &data);
if (rval)
@@ -4065,6 +4300,7 @@ qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id)
{
uint16_t options = (requester_id << 15) | BIT_6;
uint32_t data;
+ uint32_t lock_owner;
struct qla_hw_data *ha = base_vha->hw;
/* IDC-lock implementation using driver-lock/lock-id remote registers */
@@ -4076,8 +4312,11 @@ retry_lock:
qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID,
ha->portnum);
} else {
+ qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID,
+ &lock_owner);
ql_dbg(ql_dbg_p3p, base_vha, 0xb063,
- "Failed to acquire IDC lock. retrying...\n");
+ "Failed to acquire IDC lock, acquired by %d, "
+ "retrying...\n", lock_owner);
/* Retry/Perform IDC-Lock recovery */
if (qla83xx_idc_lock_recovery(base_vha)
@@ -4494,6 +4733,38 @@ qla2x00_do_dpc(void *data)
ql_dbg(ql_dbg_dpc, base_vha, 0x4006,
"FCoE context reset end.\n");
}
+ } else if (IS_QLAFX00(ha)) {
+ if (test_and_clear_bit(ISP_UNRECOVERABLE,
+ &base_vha->dpc_flags)) {
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4020,
+ "Firmware Reset Recovery\n");
+ if (qlafx00_reset_initialize(base_vha)) {
+ /* Failed. Abort isp later. */
+ if (!test_bit(UNLOADING,
+ &base_vha->dpc_flags))
+ set_bit(ISP_UNRECOVERABLE,
+ &base_vha->dpc_flags);
+ ql_dbg(ql_dbg_dpc, base_vha,
+ 0x4021,
+ "Reset Recovery Failed\n");
+ }
+ }
+
+ if (test_and_clear_bit(FX00_TARGET_SCAN,
+ &base_vha->dpc_flags)) {
+ ql_dbg(ql_dbg_dpc, base_vha, 0x4022,
+ "ISPFx00 Target Scan scheduled\n");
+ if (qlafx00_rescan_isp(base_vha)) {
+ if (!test_bit(UNLOADING,
+ &base_vha->dpc_flags))
+ set_bit(ISP_UNRECOVERABLE,
+ &base_vha->dpc_flags);
+ ql_dbg(ql_dbg_dpc, base_vha, 0x401e,
+ "ISPFx00 Target Scan Failed\n");
+ }
+ ql_dbg(ql_dbg_dpc, base_vha, 0x401f,
+ "ISPFx00 Target Scan End\n");
+ }
}
if (test_and_clear_bit(ISP_ABORT_NEEDED,
@@ -4532,6 +4803,9 @@ qla2x00_do_dpc(void *data)
clear_bit(SCR_PENDING, &base_vha->dpc_flags);
}
+ if (IS_QLAFX00(ha))
+ goto loop_resync_check;
+
if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
"Quiescence mode scheduled.\n");
@@ -4556,7 +4830,7 @@ qla2x00_do_dpc(void *data)
}
if (test_and_clear_bit(RESET_MARKER_NEEDED,
- &base_vha->dpc_flags) &&
+ &base_vha->dpc_flags) &&
(!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
ql_dbg(ql_dbg_dpc, base_vha, 0x400b,
@@ -4579,9 +4853,9 @@ qla2x00_do_dpc(void *data)
ql_dbg(ql_dbg_dpc, base_vha, 0x400e,
"Relogin end.\n");
}
-
+loop_resync_check:
if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
- &base_vha->dpc_flags)) {
+ &base_vha->dpc_flags)) {
ql_dbg(ql_dbg_dpc, base_vha, 0x400f,
"Loop resync scheduled.\n");
@@ -4599,12 +4873,27 @@ qla2x00_do_dpc(void *data)
"Loop resync end.\n");
}
+ if (IS_QLAFX00(ha))
+ goto intr_on_check;
+
if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&
atomic_read(&base_vha->loop_state) == LOOP_READY) {
clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags);
qla2xxx_flash_npiv_conf(base_vha);
}
+ if (test_and_clear_bit(HOST_RAMP_DOWN_QUEUE_DEPTH,
+ &base_vha->dpc_flags)) {
+ /* Prevents simultaneous ramp up and down */
+ clear_bit(HOST_RAMP_UP_QUEUE_DEPTH,
+ &base_vha->dpc_flags);
+ qla2x00_host_ramp_down_queuedepth(base_vha);
+ }
+
+ if (test_and_clear_bit(HOST_RAMP_UP_QUEUE_DEPTH,
+ &base_vha->dpc_flags))
+ qla2x00_host_ramp_up_queuedepth(base_vha);
+intr_on_check:
if (!ha->interrupts_on)
ha->isp_ops->enable_intrs(ha);
@@ -4612,7 +4901,8 @@ qla2x00_do_dpc(void *data)
&base_vha->dpc_flags))
ha->isp_ops->beacon_blink(base_vha);
- qla2x00_do_dpc_all_vps(base_vha);
+ if (!IS_QLAFX00(ha))
+ qla2x00_do_dpc_all_vps(base_vha);
ha->dpc_active = 0;
end_loop:
@@ -4708,6 +4998,9 @@ qla2x00_timer(scsi_qla_host_t *vha)
qla82xx_watchdog(vha);
}
+ if (!vha->vp_idx && IS_QLAFX00(ha))
+ qlafx00_timer_routine(vha);
+
/* Loop down handler. */
if (atomic_read(&vha->loop_down_timer) > 0 &&
!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
@@ -4733,7 +5026,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
cpu_flags);
req = ha->req_q_map[0];
for (index = 1;
- index < MAX_OUTSTANDING_COMMANDS;
+ index < req->num_outstanding_cmds;
index++) {
fc_port_t *sfcp;
@@ -4802,7 +5095,9 @@ qla2x00_timer(scsi_qla_host_t *vha)
test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) ||
test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) ||
test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
- test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) {
+ test_bit(RELOGIN_NEEDED, &vha->dpc_flags) ||
+ test_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags) ||
+ test_bit(HOST_RAMP_UP_QUEUE_DEPTH, &vha->dpc_flags))) {
ql_dbg(ql_dbg_timer, vha, 0x600b,
"isp_abort_needed=%d loop_resync_needed=%d "
"fcport_update_needed=%d start_dpc=%d "
@@ -4815,12 +5110,15 @@ qla2x00_timer(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_timer, vha, 0x600c,
"beacon_blink_needed=%d isp_unrecoverable=%d "
"fcoe_ctx_reset_needed=%d vp_dpc_needed=%d "
- "relogin_needed=%d.\n",
+ "relogin_needed=%d, host_ramp_down_needed=%d "
+ "host_ramp_up_needed=%d.\n",
test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags),
test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags),
test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags),
test_bit(VP_DPC_NEEDED, &vha->dpc_flags),
- test_bit(RELOGIN_NEEDED, &vha->dpc_flags));
+ test_bit(RELOGIN_NEEDED, &vha->dpc_flags),
+ test_bit(HOST_RAMP_UP_QUEUE_DEPTH, &vha->dpc_flags),
+ test_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags));
qla2xxx_wake_dpc(vha);
}
@@ -5220,6 +5518,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8031) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISPF001) },
{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
@@ -5236,7 +5535,7 @@ static struct pci_driver qla2xxx_pci_driver = {
.err_handler = &qla2xxx_err_handler,
};
-static struct file_operations apidev_fops = {
+static const struct file_operations apidev_fops = {
.owner = THIS_MODULE,
.llseek = noop_llseek,
};
diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h
index 892a81e..46ef0ac 100644
--- a/drivers/scsi/qla2xxx/qla_settings.h
+++ b/drivers/scsi/qla2xxx/qla_settings.h
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 32fdc2a..3bef673 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@@ -798,20 +798,8 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
case FLT_REG_BOOTLOAD_82XX:
ha->flt_region_bootload = start;
break;
- case FLT_REG_VPD_82XX:
- ha->flt_region_vpd = start;
- break;
- case FLT_REG_FCOE_VPD_0:
- if (!IS_QLA8031(ha))
- break;
- ha->flt_region_vpd_nvram = start;
- if (ha->flags.port0)
- ha->flt_region_vpd = start;
- break;
- case FLT_REG_FCOE_VPD_1:
- if (!IS_QLA8031(ha))
- break;
- if (!ha->flags.port0)
+ case FLT_REG_VPD_8XXX:
+ if (IS_CNA_CAPABLE(ha))
ha->flt_region_vpd = start;
break;
case FLT_REG_FCOE_NVRAM_0:
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 80f4b84..83a8f7a 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(qlini_mode,
"\"disabled\" - initiator mode will never be enabled; "
"\"enabled\" (default) - initiator mode will always stay enabled.");
-static int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
+int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
/*
* From scsi/fc/fc_fcp.h
@@ -544,102 +544,6 @@ out_free_id_list:
return res;
}
-static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
- struct qla_tgt_sess *sess)
-{
- struct qla_hw_data *ha = vha->hw;
- struct qla_port_24xx_data *pmap24;
- bool res, found = false;
- int rc, i;
- uint16_t loop_id = 0xFFFF; /* to eliminate compiler's warning */
- uint16_t entries;
- void *pmap;
- int pmap_len;
- fc_port_t *fcport;
- int global_resets;
- unsigned long flags;
-
-retry:
- global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
-
- rc = qla2x00_get_node_name_list(vha, &pmap, &pmap_len);
- if (rc != QLA_SUCCESS) {
- res = false;
- goto out;
- }
-
- pmap24 = pmap;
- entries = pmap_len/sizeof(*pmap24);
-
- for (i = 0; i < entries; ++i) {
- if (!memcmp(sess->port_name, pmap24[i].port_name, WWN_SIZE)) {
- loop_id = le16_to_cpu(pmap24[i].loop_id);
- found = true;
- break;
- }
- }
-
- kfree(pmap);
-
- if (!found) {
- res = false;
- goto out;
- }
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf046,
- "qlt_check_fcport_exist(): loop_id %d", loop_id);
-
- fcport = kzalloc(sizeof(*fcport), GFP_KERNEL);
- if (fcport == NULL) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf047,
- "qla_target(%d): Allocation of tmp FC port failed",
- vha->vp_idx);
- res = false;
- goto out;
- }
-
- fcport->loop_id = loop_id;
-
- rc = qla2x00_get_port_database(vha, fcport, 0);
- if (rc != QLA_SUCCESS) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf048,
- "qla_target(%d): Failed to retrieve fcport "
- "information -- get_port_database() returned %x "
- "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id);
- res = false;
- goto out_free_fcport;
- }
-
- if (global_resets !=
- atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002,
- "qla_target(%d): global reset during session discovery"
- " (counter was %d, new %d), retrying",
- vha->vp_idx, global_resets,
- atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count));
- goto retry;
- }
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003,
- "Updating sess %p s_id %x:%x:%x, loop_id %d) to d_id %x:%x:%x, "
- "loop_id %d", sess, sess->s_id.b.domain, sess->s_id.b.al_pa,
- sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
-
- spin_lock_irqsave(&ha->hardware_lock, flags);
- ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
- (fcport->flags & FCF_CONF_COMP_SUPPORTED));
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
- res = true;
-
-out_free_fcport:
- kfree(fcport);
-
-out:
- return res;
-}
-
/* ha->hardware_lock supposed to be held on entry */
static void qlt_undelete_sess(struct qla_tgt_sess *sess)
{
@@ -663,43 +567,13 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
del_list_entry);
if (time_after_eq(jiffies, sess->expires)) {
- bool cancel;
-
qlt_undelete_sess(sess);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- cancel = qlt_check_fcport_exist(vha, sess);
-
- if (cancel) {
- if (sess->deleted) {
- /*
- * sess was again deleted while we were
- * discovering it
- */
- spin_lock_irqsave(&ha->hardware_lock,
- flags);
- continue;
- }
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf049,
- "qla_target(%d): cancel deletion of "
- "session for port %02x:%02x:%02x:%02x:%02x:"
- "%02x:%02x:%02x (loop ID %d), because "
- " it isn't deleted by firmware",
- vha->vp_idx, sess->port_name[0],
- sess->port_name[1], sess->port_name[2],
- sess->port_name[3], sess->port_name[4],
- sess->port_name[5], sess->port_name[6],
- sess->port_name[7], sess->loop_id);
- } else {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
- "Timeout: sess %p about to be deleted\n",
- sess);
- ha->tgt.tgt_ops->shutdown_sess(sess);
- ha->tgt.tgt_ops->put_sess(sess);
- }
-
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
+ "Timeout: sess %p about to be deleted\n",
+ sess);
+ ha->tgt.tgt_ops->shutdown_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
} else {
schedule_delayed_work(&tgt->sess_del_work,
jiffies - sess->expires);
@@ -884,9 +758,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
sess->loop_id);
sess->local = 0;
}
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
@@ -1119,6 +992,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
nack->u.isp24.status = ntfy->u.isp24.status;
nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
+ nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
@@ -1570,7 +1444,7 @@ static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha)
/* always increment cmd handle */
do {
++h;
- if (h > MAX_OUTSTANDING_COMMANDS)
+ if (h > DEFAULT_OUTSTANDING_COMMANDS)
h = 1; /* 0 is QLA_TGT_NULL_HANDLE */
if (h == ha->tgt.current_handle) {
ql_dbg(ql_dbg_tgt, vha, 0xe04e,
@@ -2441,7 +2315,7 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
return NULL;
}
/* handle-1 is actually used */
- if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) {
+ if (unlikely(handle > DEFAULT_OUTSTANDING_COMMANDS)) {
ql_dbg(ql_dbg_tgt, vha, 0xe052,
"qla_target(%d): Wrong handle %x received\n",
vha->vp_idx, handle);
@@ -2584,25 +2458,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
ha->tgt.tgt_ops->free_cmd(cmd);
}
-/* ha->hardware_lock supposed to be held on entry */
-/* called via callback from qla2xxx */
-void qlt_ctio_completion(struct scsi_qla_host *vha, uint32_t handle)
-{
- struct qla_hw_data *ha = vha->hw;
- struct qla_tgt *tgt = ha->tgt.qla_tgt;
-
- if (likely(tgt == NULL)) {
- ql_dbg(ql_dbg_tgt, vha, 0xe021,
- "CTIO, but target mode not enabled"
- " (ha %d %p handle %#x)", vha->vp_idx, ha, handle);
- return;
- }
-
- tgt->irq_cmd_count++;
- qlt_do_ctio_completion(vha, handle, CTIO_SUCCESS, NULL);
- tgt->irq_cmd_count--;
-}
-
static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha,
uint8_t task_codes)
{
@@ -2724,7 +2579,9 @@ static void qlt_do_work(struct work_struct *work)
/*
* Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
*/
+ spin_lock_irqsave(&ha->hardware_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
out_term:
@@ -2736,9 +2593,9 @@ out_term:
spin_lock_irqsave(&ha->hardware_lock, flags);
qlt_send_term_exchange(vha, NULL, &cmd->atio, 1);
kmem_cache_free(qla_tgt_cmd_cachep, cmd);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (sess)
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
/* ha->hardware_lock supposed to be held on entry */
@@ -4187,16 +4044,16 @@ static void qlt_abort_work(struct qla_tgt *tgt,
rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess);
if (rc != 0)
goto out_term;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
out_term:
qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (sess)
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static void qlt_tmr_work(struct qla_tgt *tgt,
@@ -4244,16 +4101,16 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
if (rc != 0)
goto out_term;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
out_term:
qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (sess)
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static void qlt_sess_work_fn(struct work_struct *work)
@@ -4305,6 +4162,12 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
if (!QLA_TGT_MODE_ENABLED())
return 0;
+ if (!IS_TGT_MODE_CAPABLE(ha)) {
+ ql_log(ql_log_warn, base_vha, 0xe070,
+ "This adapter does not support target mode.\n");
+ return 0;
+ }
+
ql_dbg(ql_dbg_tgt, base_vha, 0xe03b,
"Registering target for host %ld(%p)", base_vha->host_no, ha);
@@ -4666,7 +4529,6 @@ void
qlt_24xx_process_atio_queue(struct scsi_qla_host *vha)
{
struct qla_hw_data *ha = vha->hw;
- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
struct atio_from_isp *pkt;
int cnt, i;
@@ -4694,26 +4556,28 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha)
}
/* Adjust ring index */
- WRT_REG_DWORD(&reg->atio_q_out, ha->tgt.atio_ring_index);
+ WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index);
}
void
-qlt_24xx_config_rings(struct scsi_qla_host *vha, device_reg_t __iomem *reg)
+qlt_24xx_config_rings(struct scsi_qla_host *vha)
{
struct qla_hw_data *ha = vha->hw;
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
-/* FIXME: atio_q in/out for ha->mqenable=1..? */
- if (ha->mqenable) {
-#if 0
- WRT_REG_DWORD(&reg->isp25mq.atio_q_in, 0);
- WRT_REG_DWORD(&reg->isp25mq.atio_q_out, 0);
- RD_REG_DWORD(&reg->isp25mq.atio_q_out);
-#endif
- } else {
- /* Setup APTIO registers for target mode */
- WRT_REG_DWORD(&reg->isp24.atio_q_in, 0);
- WRT_REG_DWORD(&reg->isp24.atio_q_out, 0);
- RD_REG_DWORD(&reg->isp24.atio_q_out);
+ WRT_REG_DWORD(ISP_ATIO_Q_IN(vha), 0);
+ WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0);
+ RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
+
+ if (IS_ATIO_MSIX_CAPABLE(ha)) {
+ struct qla_msix_entry *msix = &ha->msix_entries[2];
+ struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb;
+
+ icb->msix_atio = cpu_to_le16(msix->entry);
+ ql_dbg(ql_dbg_init, vha, 0xf072,
+ "Registering ICB vector 0x%x for atio que.\n",
+ msix->entry);
}
}
@@ -4796,6 +4660,101 @@ qlt_24xx_config_nvram_stage2(struct scsi_qla_host *vha,
}
}
+void
+qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
+
+ if (qla_tgt_mode_enabled(vha)) {
+ if (!ha->tgt.saved_set) {
+ /* We save only once */
+ ha->tgt.saved_exchange_count = nv->exchange_count;
+ ha->tgt.saved_firmware_options_1 =
+ nv->firmware_options_1;
+ ha->tgt.saved_firmware_options_2 =
+ nv->firmware_options_2;
+ ha->tgt.saved_firmware_options_3 =
+ nv->firmware_options_3;
+ ha->tgt.saved_set = 1;
+ }
+
+ nv->exchange_count = __constant_cpu_to_le16(0xFFFF);
+
+ /* Enable target mode */
+ nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4);
+
+ /* Disable ini mode, if requested */
+ if (!qla_ini_mode_enabled(vha))
+ nv->firmware_options_1 |=
+ __constant_cpu_to_le32(BIT_5);
+
+ /* Disable Full Login after LIP */
+ nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13);
+ /* Enable initial LIP */
+ nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9);
+ /* Enable FC tapes support */
+ nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+ /* Disable Full Login after LIP */
+ nv->host_p &= __constant_cpu_to_le32(~BIT_10);
+ /* Enable target PRLI control */
+ nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_14);
+ } else {
+ if (ha->tgt.saved_set) {
+ nv->exchange_count = ha->tgt.saved_exchange_count;
+ nv->firmware_options_1 =
+ ha->tgt.saved_firmware_options_1;
+ nv->firmware_options_2 =
+ ha->tgt.saved_firmware_options_2;
+ nv->firmware_options_3 =
+ ha->tgt.saved_firmware_options_3;
+ }
+ return;
+ }
+
+ /* out-of-order frames reassembly */
+ nv->firmware_options_3 |= BIT_6|BIT_9;
+
+ if (ha->tgt.enable_class_2) {
+ if (vha->flags.init_done)
+ fc_host_supported_classes(vha->host) =
+ FC_COS_CLASS2 | FC_COS_CLASS3;
+
+ nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_8);
+ } else {
+ if (vha->flags.init_done)
+ fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
+
+ nv->firmware_options_2 &= ~__constant_cpu_to_le32(BIT_8);
+ }
+}
+
+void
+qlt_81xx_config_nvram_stage2(struct scsi_qla_host *vha,
+ struct init_cb_81xx *icb)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
+
+ if (ha->tgt.node_name_set) {
+ memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE);
+ icb->firmware_options_1 |= __constant_cpu_to_le32(BIT_14);
+ }
+}
+
+void
+qlt_83xx_iospace_config(struct qla_hw_data *ha)
+{
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
+
+ ha->msix_count += 1; /* For ATIO Q */
+}
+
int
qlt_24xx_process_response_error(struct scsi_qla_host *vha,
struct sts_entry_24xx *pkt)
@@ -4828,11 +4787,41 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
if (!QLA_TGT_MODE_ENABLED())
return;
+ if (ha->mqenable || IS_QLA83XX(ha)) {
+ ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
+ ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
+ } else {
+ ISP_ATIO_Q_IN(base_vha) = &ha->iobase->isp24.atio_q_in;
+ ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
+ }
+
mutex_init(&ha->tgt.tgt_mutex);
mutex_init(&ha->tgt.tgt_host_action_mutex);
qlt_clear_mode(base_vha);
}
+irqreturn_t
+qla83xx_msix_atio_q(int irq, void *dev_id)
+{
+ struct rsp_que *rsp;
+ scsi_qla_host_t *vha;
+ struct qla_hw_data *ha;
+ unsigned long flags;
+
+ rsp = (struct rsp_que *) dev_id;
+ ha = rsp->hw;
+ vha = pci_get_drvdata(ha->pdev);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ qlt_24xx_process_atio_queue(vha);
+ qla24xx_process_response_queue(vha, rsp);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
int
qlt_mem_alloc(struct qla_hw_data *ha)
{
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index bad7495..b33e411 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -60,8 +60,9 @@
* multi-complete should come to the tgt driver or be handled there by qla2xxx
*/
#define CTIO_COMPLETION_HANDLE_MARK BIT_29
-#if (CTIO_COMPLETION_HANDLE_MARK <= MAX_OUTSTANDING_COMMANDS)
-#error "CTIO_COMPLETION_HANDLE_MARK not larger than MAX_OUTSTANDING_COMMANDS"
+#if (CTIO_COMPLETION_HANDLE_MARK <= DEFAULT_OUTSTANDING_COMMANDS)
+#error "CTIO_COMPLETION_HANDLE_MARK not larger than "
+ "DEFAULT_OUTSTANDING_COMMANDS"
#endif
#define HANDLE_IS_CTIO_COMP(h) (h & CTIO_COMPLETION_HANDLE_MARK)
@@ -161,7 +162,7 @@ struct imm_ntfy_from_isp {
uint16_t srr_rx_id;
uint16_t status;
uint8_t status_subcode;
- uint8_t reserved_3;
+ uint8_t fw_handle;
uint32_t exchange_address;
uint32_t srr_rel_offs;
uint16_t srr_ui;
@@ -217,7 +218,7 @@ struct nack_to_isp {
uint16_t srr_rx_id;
uint16_t status;
uint8_t status_subcode;
- uint8_t reserved_3;
+ uint8_t fw_handle;
uint32_t exchange_address;
uint32_t srr_rel_offs;
uint16_t srr_ui;
@@ -948,6 +949,7 @@ extern void qlt_update_vp_map(struct scsi_qla_host *, int);
* is not set. Right now, ha value is ignored.
*/
#define QLA_TGT_MODE_ENABLED() (ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED)
+extern int ql2x_ini_mode;
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
{
@@ -978,19 +980,21 @@ extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
-extern void qlt_ctio_completion(struct scsi_qla_host *, uint32_t);
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
extern void qlt_enable_vha(struct scsi_qla_host *);
extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
extern void qlt_rff_id(struct scsi_qla_host *, struct ct_sns_req *);
extern void qlt_init_atio_q_entries(struct scsi_qla_host *);
extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *);
-extern void qlt_24xx_config_rings(struct scsi_qla_host *,
- device_reg_t __iomem *);
+extern void qlt_24xx_config_rings(struct scsi_qla_host *);
extern void qlt_24xx_config_nvram_stage1(struct scsi_qla_host *,
struct nvram_24xx *);
extern void qlt_24xx_config_nvram_stage2(struct scsi_qla_host *,
struct init_cb_24xx *);
+extern void qlt_81xx_config_nvram_stage2(struct scsi_qla_host *,
+ struct init_cb_81xx *);
+extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *,
+ struct nvram_81xx *);
extern int qlt_24xx_process_response_error(struct scsi_qla_host *,
struct sts_entry_24xx *);
extern void qlt_modify_vp_config(struct scsi_qla_host *,
@@ -1000,5 +1004,7 @@ extern int qlt_mem_alloc(struct qla_hw_data *);
extern void qlt_mem_free(struct qla_hw_data *);
extern void qlt_stop_phase1(struct qla_tgt *);
extern void qlt_stop_phase2(struct qla_tgt *);
+extern irqreturn_t qla83xx_msix_atio_q(int, void *);
+extern void qlt_83xx_iospace_config(struct qla_hw_data *);
#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 49697ca..6c66d22 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -1,15 +1,15 @@
/*
* QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2012 QLogic Corporation
+ * Copyright (c) 2003-2013 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.04.00.08-k"
+#define QLA2XXX_VERSION "8.05.00.03-k"
#define QLA_DRIVER_MAJOR_VER 8
-#define QLA_DRIVER_MINOR_VER 4
+#define QLA_DRIVER_MINOR_VER 5
#define QLA_DRIVER_PATCH_VER 0
#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index d182c96..a318092 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -688,8 +688,12 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
* For FCP_READ with CHECK_CONDITION status, clear cmd->bufflen
* for qla_tgt_xmit_response LLD code
*/
+ if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+ se_cmd->se_cmd_flags &= ~SCF_OVERFLOW_BIT;
+ se_cmd->residual_count = 0;
+ }
se_cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
- se_cmd->residual_count = se_cmd->data_length;
+ se_cmd->residual_count += se_cmd->data_length;
cmd->bufflen = 0;
}
@@ -699,7 +703,7 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
return qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status);
}
-static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
+static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
{
struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd,
@@ -731,8 +735,6 @@ static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
* CTIO response packet.
*/
qlt_xmit_tm_rsp(mcmd);
-
- return 0;
}
/* Local pointer to allocated TCM configfs fabric module */
@@ -795,12 +797,14 @@ static void tcm_qla2xxx_put_session(struct se_session *se_sess)
static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess)
{
- tcm_qla2xxx_put_session(sess->se_sess);
+ assert_spin_locked(&sess->vha->hw->hardware_lock);
+ kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session);
}
static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
{
- tcm_qla2xxx_shutdown_session(sess->se_sess);
+ assert_spin_locked(&sess->vha->hw->hardware_lock);
+ target_sess_cmd_list_set_waiting(sess->se_sess);
}
static struct se_node_acl *tcm_qla2xxx_make_nodeacl(
@@ -1370,7 +1374,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
dump_stack();
return;
}
- target_wait_for_sess_cmds(se_sess, 0);
+ target_wait_for_sess_cmds(se_sess);
transport_deregister_session_configfs(sess->se_sess);
transport_deregister_session(sess->se_sess);
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c
index 6e9af20..d607eb8 100644
--- a/drivers/scsi/qla4xxx/ql4_83xx.c
+++ b/drivers/scsi/qla4xxx/ql4_83xx.c
@@ -538,7 +538,7 @@ struct device_info {
int port_num;
};
-static int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha)
+int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha)
{
uint32_t drv_active;
uint32_t dev_part, dev_part1, dev_part2;
@@ -1351,31 +1351,58 @@ exit_start_fw:
/*----------------------Interrupt Related functions ---------------------*/
-void qla4_83xx_disable_intrs(struct scsi_qla_host *ha)
+static void qla4_83xx_disable_iocb_intrs(struct scsi_qla_host *ha)
+{
+ if (test_and_clear_bit(AF_83XX_IOCB_INTR_ON, &ha->flags))
+ qla4_8xxx_intr_disable(ha);
+}
+
+static void qla4_83xx_disable_mbox_intrs(struct scsi_qla_host *ha)
{
uint32_t mb_int, ret;
- if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags))
- qla4_8xxx_mbx_intr_disable(ha);
+ if (test_and_clear_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) {
+ ret = readl(&ha->qla4_83xx_reg->mbox_int);
+ mb_int = ret & ~INT_ENABLE_FW_MB;
+ writel(mb_int, &ha->qla4_83xx_reg->mbox_int);
+ writel(1, &ha->qla4_83xx_reg->leg_int_mask);
+ }
+}
- ret = readl(&ha->qla4_83xx_reg->mbox_int);
- mb_int = ret & ~INT_ENABLE_FW_MB;
- writel(mb_int, &ha->qla4_83xx_reg->mbox_int);
- writel(1, &ha->qla4_83xx_reg->leg_int_mask);
+void qla4_83xx_disable_intrs(struct scsi_qla_host *ha)
+{
+ qla4_83xx_disable_mbox_intrs(ha);
+ qla4_83xx_disable_iocb_intrs(ha);
}
-void qla4_83xx_enable_intrs(struct scsi_qla_host *ha)
+static void qla4_83xx_enable_iocb_intrs(struct scsi_qla_host *ha)
+{
+ if (!test_bit(AF_83XX_IOCB_INTR_ON, &ha->flags)) {
+ qla4_8xxx_intr_enable(ha);
+ set_bit(AF_83XX_IOCB_INTR_ON, &ha->flags);
+ }
+}
+
+void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha)
{
uint32_t mb_int;
- qla4_8xxx_mbx_intr_enable(ha);
- mb_int = INT_ENABLE_FW_MB;
- writel(mb_int, &ha->qla4_83xx_reg->mbox_int);
- writel(0, &ha->qla4_83xx_reg->leg_int_mask);
+ if (!test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) {
+ mb_int = INT_ENABLE_FW_MB;
+ writel(mb_int, &ha->qla4_83xx_reg->mbox_int);
+ writel(0, &ha->qla4_83xx_reg->leg_int_mask);
+ set_bit(AF_83XX_MBOX_INTR_ON, &ha->flags);
+ }
+}
+
- set_bit(AF_INTERRUPTS_ON, &ha->flags);
+void qla4_83xx_enable_intrs(struct scsi_qla_host *ha)
+{
+ qla4_83xx_enable_mbox_intrs(ha);
+ qla4_83xx_enable_iocb_intrs(ha);
}
+
void qla4_83xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
int incount)
{
@@ -1602,9 +1629,37 @@ static void __qla4_83xx_disable_pause(struct scsi_qla_host *ha)
ql4_printk(KERN_INFO, ha, "Disabled pause frames successfully.\n");
}
+/**
+ * qla4_83xx_eport_init - Initialize EPort.
+ * @ha: Pointer to host adapter structure.
+ *
+ * If EPort hardware is in reset state before disabling pause, there would be
+ * serious hardware wedging issues. To prevent this perform eport init everytime
+ * before disabling pause frames.
+ **/
+static void qla4_83xx_eport_init(struct scsi_qla_host *ha)
+{
+ /* Clear the 8 registers */
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_REG, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT0, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT1, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT2, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT3, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_SRE_SHIM, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_EPG_SHIM, 0x0);
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_ETHER_PCS, 0x0);
+
+ /* Write any value to Reset Control register */
+ qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_CONTROL, 0xFF);
+
+ ql4_printk(KERN_INFO, ha, "EPORT is out of reset.\n");
+}
+
void qla4_83xx_disable_pause(struct scsi_qla_host *ha)
{
ha->isp_ops->idc_lock(ha);
+ /* Before disabling pause frames, ensure that eport is not in reset */
+ qla4_83xx_eport_init(ha);
qla4_83xx_dump_pause_control_regs(ha);
__qla4_83xx_disable_pause(ha);
ha->isp_ops->idc_unlock(ha);
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h
index 6a00f90..fab237f 100644
--- a/drivers/scsi/qla4xxx/ql4_83xx.h
+++ b/drivers/scsi/qla4xxx/ql4_83xx.h
@@ -55,6 +55,16 @@
#define QLA83XX_SET_PAUSE_VAL 0x0
#define QLA83XX_SET_TC_MAX_CELL_VAL 0x03FF03FF
+#define QLA83XX_RESET_CONTROL 0x28084E50
+#define QLA83XX_RESET_REG 0x28084E60
+#define QLA83XX_RESET_PORT0 0x28084E70
+#define QLA83XX_RESET_PORT1 0x28084E80
+#define QLA83XX_RESET_PORT2 0x28084E90
+#define QLA83XX_RESET_PORT3 0x28084EA0
+#define QLA83XX_RESET_SRE_SHIM 0x28084EB0
+#define QLA83XX_RESET_EPG_SHIM 0x28084EC0
+#define QLA83XX_RESET_ETHER_PCS 0x28084ED0
+
/* qla_83xx_reg_tbl registers */
#define QLA83XX_PEG_HALT_STATUS1 0x34A8
#define QLA83XX_PEG_HALT_STATUS2 0x34AC
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c
index 76819b7..19ee55a 100644
--- a/drivers/scsi/qla4xxx/ql4_attr.c
+++ b/drivers/scsi/qla4xxx/ql4_attr.c
@@ -74,16 +74,22 @@ qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj,
}
break;
case 2:
- /* Reset HBA */
+ /* Reset HBA and collect FW dump */
ha->isp_ops->idc_lock(ha);
dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
if (dev_state == QLA8XXX_DEV_READY) {
- ql4_printk(KERN_INFO, ha,
- "%s: Setting Need reset, reset_owner is 0x%x.\n",
- __func__, ha->func_num);
+ ql4_printk(KERN_INFO, ha, "%s: Setting Need reset\n",
+ __func__);
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,
QLA8XXX_DEV_NEED_RESET);
- set_bit(AF_8XXX_RST_OWNER, &ha->flags);
+ if (is_qla8022(ha) ||
+ (is_qla8032(ha) &&
+ qla4_83xx_can_perform_reset(ha))) {
+ set_bit(AF_8XXX_RST_OWNER, &ha->flags);
+ set_bit(AF_FW_RECOVERY, &ha->flags);
+ ql4_printk(KERN_INFO, ha, "%s: Reset owner is 0x%x\n",
+ __func__, ha->func_num);
+ }
} else
ql4_printk(KERN_INFO, ha,
"%s: Reset not performed as device state is 0x%x\n",
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h
index 5b0afc1..51c365b 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.h
+++ b/drivers/scsi/qla4xxx/ql4_dbg.h
@@ -12,6 +12,7 @@
/* #define QL_DEBUG_LEVEL_3 */ /* Output function tracing */
/* #define QL_DEBUG_LEVEL_4 */
/* #define QL_DEBUG_LEVEL_5 */
+/* #define QL_DEBUG_LEVEL_7 */
/* #define QL_DEBUG_LEVEL_9 */
#define QL_DEBUG_LEVEL_2 /* ALways enable error messagess */
@@ -48,6 +49,12 @@
#define DEBUG5(x) do {} while (0);
#endif /* */
+#if defined(QL_DEBUG_LEVEL_7)
+#define DEBUG7(x) do {x; } while (0)
+#else /* */
+#define DEBUG7(x) do {} while (0)
+#endif /* */
+
#if defined(QL_DEBUG_LEVEL_9)
#define DEBUG9(x) do {x;} while (0);
#else /* */
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 329d553..ddf16a8 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -136,6 +136,7 @@
#define RESPONSE_QUEUE_DEPTH 64
#define QUEUE_SIZE 64
#define DMA_BUFFER_SIZE 512
+#define IOCB_HIWAT_CUSHION 4
/*
* Misc
@@ -158,6 +159,22 @@
#define LSDW(x) ((u32)((u64)(x)))
#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
+#define DEV_DB_NON_PERSISTENT 0
+#define DEV_DB_PERSISTENT 1
+
+#define COPY_ISID(dst_isid, src_isid) { \
+ int i, j; \
+ for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \
+ dst_isid[i++] = src_isid[j--]; \
+}
+
+#define SET_BITVAL(o, n, v) { \
+ if (o) \
+ n |= v; \
+ else \
+ n &= ~v; \
+}
+
/*
* Retry & Timeout Values
*/
@@ -180,6 +197,7 @@
#define DISABLE_ACB_TOV 30
#define IP_CONFIG_TOV 30
#define LOGIN_TOV 12
+#define BOOT_LOGIN_RESP_TOV 60
#define MAX_RESET_HA_RETRIES 2
#define FW_ALIVE_WAIT_TOV 3
@@ -314,6 +332,7 @@ struct ql4_tuple_ddb {
* DDB flags.
*/
#define DF_RELOGIN 0 /* Relogin to device */
+#define DF_BOOT_TGT 1 /* Boot target entry */
#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */
#define DF_FO_MASKED 3
@@ -360,6 +379,8 @@ struct ql82xx_hw_data {
uint32_t flt_iscsi_param;
uint32_t flt_region_chap;
uint32_t flt_chap_size;
+ uint32_t flt_region_ddb;
+ uint32_t flt_ddb_size;
};
struct qla4_8xxx_legacy_intr_set {
@@ -498,9 +519,11 @@ struct scsi_qla_host {
#define AF_INIT_DONE 1 /* 0x00000002 */
#define AF_MBOX_COMMAND 2 /* 0x00000004 */
#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */
+#define AF_ST_DISCOVERY_IN_PROGRESS 4 /* 0x00000010 */
#define AF_INTERRUPTS_ON 6 /* 0x00000040 */
#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */
#define AF_LINK_UP 8 /* 0x00000100 */
+#define AF_LOOPBACK 9 /* 0x00000200 */
#define AF_IRQ_ATTACHED 10 /* 0x00000400 */
#define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */
#define AF_HA_REMOVAL 12 /* 0x00001000 */
@@ -516,6 +539,8 @@ struct scsi_qla_host {
#define AF_8XXX_RST_OWNER 25 /* 0x02000000 */
#define AF_82XX_DUMP_READING 26 /* 0x04000000 */
#define AF_83XX_NO_FW_DUMP 27 /* 0x08000000 */
+#define AF_83XX_IOCB_INTR_ON 28 /* 0x10000000 */
+#define AF_83XX_MBOX_INTR_ON 29 /* 0x20000000 */
unsigned long dpc_flags;
@@ -537,6 +562,7 @@ struct scsi_qla_host {
uint32_t tot_ddbs;
uint16_t iocb_cnt;
+ uint16_t iocb_hiwat;
/* SRB cache. */
#define SRB_MIN_REQ 128
@@ -838,7 +864,8 @@ static inline int is_aer_supported(struct scsi_qla_host *ha)
static inline int adapter_up(struct scsi_qla_host *ha)
{
return (test_bit(AF_ONLINE, &ha->flags) != 0) &&
- (test_bit(AF_LINK_UP, &ha->flags) != 0);
+ (test_bit(AF_LINK_UP, &ha->flags) != 0) &&
+ (!test_bit(AF_LOOPBACK, &ha->flags));
}
static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost)
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 1c47950..c7b8892 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -288,6 +288,8 @@ union external_hw_config_reg {
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
#define FA_FLASH_ISCSI_CHAP 0x540000
#define FA_FLASH_CHAP_SIZE 0xC0000
+#define FA_FLASH_ISCSI_DDB 0x420000
+#define FA_FLASH_DDB_SIZE 0x080000
/* Flash Description Table */
struct qla_fdt_layout {
@@ -348,6 +350,7 @@ struct qla_flt_header {
#define FLT_REG_BOOT_CODE_82 0x78
#define FLT_REG_ISCSI_PARAM 0x65
#define FLT_REG_ISCSI_CHAP 0x63
+#define FLT_REG_ISCSI_DDB 0x6A
struct qla_flt_region {
uint32_t code;
@@ -490,12 +493,16 @@ struct qla_flt_region {
#define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027
#define MBOX_ASTS_RESPONSE_QUEUE_FULL 0x8028
#define MBOX_ASTS_IP_ADDR_STATE_CHANGED 0x8029
+#define MBOX_ASTS_IPV6_DEFAULT_ROUTER_CHANGED 0x802A
#define MBOX_ASTS_IPV6_PREFIX_EXPIRED 0x802B
#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED 0x802C
#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D
#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD 0x802E
+#define MBOX_ASTS_INITIALIZATION_FAILED 0x8031
+#define MBOX_ASTS_SYSTEM_WARNING_EVENT 0x8036
#define MBOX_ASTS_IDC_COMPLETE 0x8100
-#define MBOX_ASTS_IDC_NOTIFY 0x8101
+#define MBOX_ASTS_IDC_REQUEST_NOTIFICATION 0x8101
+#define MBOX_ASTS_DCBX_CONF_CHANGE 0x8110
#define MBOX_ASTS_TXSCVR_INSERTED 0x8130
#define MBOX_ASTS_TXSCVR_REMOVED 0x8131
@@ -522,6 +529,10 @@ struct qla_flt_region {
#define FLASH_OPT_COMMIT 2
#define FLASH_OPT_RMW_COMMIT 3
+/* Loopback type */
+#define ENABLE_INTERNAL_LOOPBACK 0x04
+#define ENABLE_EXTERNAL_LOOPBACK 0x08
+
/*************************************************************************/
/* Host Adapter Initialization Control Block (from host) */
@@ -775,12 +786,41 @@ struct dev_db_entry {
#define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */
#define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */
+#define OPT_IS_FW_ASSIGNED_IPV6 11
+#define OPT_IPV6_DEVICE 8
+#define OPT_AUTO_SENDTGTS_DISABLE 6
+#define OPT_DISC_SESSION 4
+#define OPT_ENTRY_STATE 3
uint16_t exec_throttle; /* 02-03 */
uint16_t exec_count; /* 04-05 */
uint16_t res0; /* 06-07 */
uint16_t iscsi_options; /* 08-09 */
+#define ISCSIOPT_HEADER_DIGEST_EN 13
+#define ISCSIOPT_DATA_DIGEST_EN 12
+#define ISCSIOPT_IMMEDIATE_DATA_EN 11
+#define ISCSIOPT_INITIAL_R2T_EN 10
+#define ISCSIOPT_DATA_SEQ_IN_ORDER 9
+#define ISCSIOPT_DATA_PDU_IN_ORDER 8
+#define ISCSIOPT_CHAP_AUTH_EN 7
+#define ISCSIOPT_SNACK_REQ_EN 6
+#define ISCSIOPT_DISCOVERY_LOGOUT_EN 5
+#define ISCSIOPT_BIDI_CHAP_EN 4
+#define ISCSIOPT_DISCOVERY_AUTH_OPTIONAL 3
+#define ISCSIOPT_ERL1 1
+#define ISCSIOPT_ERL0 0
+
uint16_t tcp_options; /* 0A-0B */
+#define TCPOPT_TIMESTAMP_STAT 6
+#define TCPOPT_NAGLE_DISABLE 5
+#define TCPOPT_WSF_DISABLE 4
+#define TCPOPT_TIMER_SCALE3 3
+#define TCPOPT_TIMER_SCALE2 2
+#define TCPOPT_TIMER_SCALE1 1
+#define TCPOPT_TIMESTAMP_EN 0
+
uint16_t ip_options; /* 0C-0D */
+#define IPOPT_FRAGMENT_DISABLE 4
+
uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */
#define BYTE_UNITS 512
uint32_t res1; /* 10-13 */
@@ -812,6 +852,8 @@ struct dev_db_entry {
* much RAM */
uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */
uint8_t res5[0x10]; /* 1B0-1BF */
+#define DDB_NO_LINK 0xFFFF
+#define DDB_ISNS 0xFFFD
uint16_t ddb_link; /* 1C0-1C1 */
uint16_t chap_tbl_idx; /* 1C2-1C3 */
uint16_t tgt_portal_grp; /* 1C4-1C5 */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 57a5a3c..4a42800 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -191,6 +191,9 @@ int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options,
int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,
uint32_t status, uint32_t pid,
uint32_t data_size, uint8_t *data);
+int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index);
/* BSG Functions */
int qla4xxx_bsg_request(struct bsg_job *bsg_job);
@@ -224,8 +227,6 @@ void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha,
int qla4_83xx_isp_reset(struct scsi_qla_host *ha);
void qla4_83xx_queue_iocb(struct scsi_qla_host *ha);
void qla4_83xx_complete_iocb(struct scsi_qla_host *ha);
-uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha);
-uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha);
uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr);
void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val);
int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr,
@@ -253,12 +254,18 @@ void qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha);
void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha);
int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha);
void qla4_8xxx_get_minidump(struct scsi_qla_host *ha);
-int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha);
-int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha);
+int qla4_8xxx_intr_disable(struct scsi_qla_host *ha);
+int qla4_8xxx_intr_enable(struct scsi_qla_host *ha);
int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param);
int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha);
int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha);
void qla4_83xx_disable_pause(struct scsi_qla_host *ha);
+void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha);
+int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha);
+int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
+ dma_addr_t dma_addr);
+int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
+ char *password, uint16_t chap_index);
extern int ql4xextended_error_logging;
extern int ql4xdontresethba;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 1aca1b4..8fc8548 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -195,12 +195,10 @@ exit_get_sys_info_no_free:
* @ha: pointer to host adapter structure.
*
**/
-static int qla4xxx_init_local_data(struct scsi_qla_host *ha)
+static void qla4xxx_init_local_data(struct scsi_qla_host *ha)
{
/* Initialize aen queue */
ha->aen_q_count = MAX_AEN_ENTRIES;
-
- return qla4xxx_get_firmware_status(ha);
}
static uint8_t
@@ -935,14 +933,23 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
if (ha->isp_ops->start_firmware(ha) == QLA_ERROR)
goto exit_init_hba;
+ /*
+ * For ISP83XX, mailbox and IOCB interrupts are enabled separately.
+ * Mailbox interrupts must be enabled prior to issuing any mailbox
+ * command in order to prevent the possibility of losing interrupts
+ * while switching from polling to interrupt mode. IOCB interrupts are
+ * enabled via isp_ops->enable_intrs.
+ */
+ if (is_qla8032(ha))
+ qla4_83xx_enable_mbox_intrs(ha);
+
if (qla4xxx_about_firmware(ha) == QLA_ERROR)
goto exit_init_hba;
if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR)
goto exit_init_hba;
- if (qla4xxx_init_local_data(ha) == QLA_ERROR)
- goto exit_init_hba;
+ qla4xxx_init_local_data(ha);
status = qla4xxx_init_firmware(ha);
if (status == QLA_ERROR)
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index f48f37a..fad71ed 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -316,7 +316,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
goto queuing_error;
/* total iocbs active */
- if ((ha->iocb_cnt + req_cnt) >= REQUEST_QUEUE_DEPTH)
+ if ((ha->iocb_cnt + req_cnt) >= ha->iocb_hiwat)
goto queuing_error;
/* Build command packet */
@@ -507,6 +507,7 @@ static int qla4xxx_send_mbox_iocb(struct scsi_qla_host *ha, struct mrb *mrb,
mrb->mbox_cmd = in_mbox[0];
wmb();
+ ha->iocb_cnt += mrb->iocb_cnt;
ha->isp_ops->queue_iocb(ha);
exit_mbox_iocb:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 15ea814..482287f 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -396,7 +396,6 @@ static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha,
task_data = task->dd_data;
memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status));
- ha->req_q_count += task_data->iocb_req_cnt;
ha->iocb_cnt -= task_data->iocb_req_cnt;
queue_work(ha->task_wq, &task_data->task_work);
}
@@ -416,7 +415,6 @@ static struct mrb *qla4xxx_del_mrb_from_active_array(struct scsi_qla_host *ha,
return mrb;
/* update counters */
- ha->req_q_count += mrb->iocb_cnt;
ha->iocb_cnt -= mrb->iocb_cnt;
return mrb;
@@ -582,6 +580,33 @@ exit_prq_error:
}
/**
+ * qla4_83xx_loopback_in_progress: Is loopback in progress?
+ * @ha: Pointer to host adapter structure.
+ * @ret: 1 = loopback in progress, 0 = loopback not in progress
+ **/
+static int qla4_83xx_loopback_in_progress(struct scsi_qla_host *ha)
+{
+ int rval = 1;
+
+ if (is_qla8032(ha)) {
+ if ((ha->idc_info.info2 & ENABLE_INTERNAL_LOOPBACK) ||
+ (ha->idc_info.info2 & ENABLE_EXTERNAL_LOOPBACK)) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Loopback diagnostics in progress\n",
+ __func__));
+ rval = 1;
+ } else {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Loopback diagnostics not in progress\n",
+ __func__));
+ rval = 0;
+ }
+ }
+
+ return rval;
+}
+
+/**
* qla4xxx_isr_decode_mailbox - decodes mailbox status
* @ha: Pointer to host adapter structure.
* @mailbox_status: Mailbox status.
@@ -676,8 +701,10 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
case MBOX_ASTS_LINK_DOWN:
clear_bit(AF_LINK_UP, &ha->flags);
- if (test_bit(AF_INIT_DONE, &ha->flags))
+ if (test_bit(AF_INIT_DONE, &ha->flags)) {
set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
+ qla4xxx_wake_dpc(ha);
+ }
ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__);
qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKDOWN,
@@ -806,7 +833,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
" removed\n", ha->host_no, mbox_sts[0]));
break;
- case MBOX_ASTS_IDC_NOTIFY:
+ case MBOX_ASTS_IDC_REQUEST_NOTIFICATION:
{
uint32_t opcode;
if (is_qla8032(ha)) {
@@ -840,9 +867,51 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
DEBUG2(ql4_printk(KERN_INFO, ha,
"scsi:%ld: AEN %04x IDC Complete notification\n",
ha->host_no, mbox_sts[0]));
+
+ if (qla4_83xx_loopback_in_progress(ha))
+ set_bit(AF_LOOPBACK, &ha->flags);
+ else
+ clear_bit(AF_LOOPBACK, &ha->flags);
}
break;
+ case MBOX_ASTS_IPV6_DEFAULT_ROUTER_CHANGED:
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
+ ha->host_no, mbox_sts[0], mbox_sts[1],
+ mbox_sts[2], mbox_sts[3], mbox_sts[4],
+ mbox_sts[5]));
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "scsi%ld: AEN %04x Received IPv6 default router changed notification\n",
+ ha->host_no, mbox_sts[0]));
+ break;
+
+ case MBOX_ASTS_INITIALIZATION_FAILED:
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "scsi%ld: AEN %04x, mbox_sts[3]=%08x\n",
+ ha->host_no, mbox_sts[0],
+ mbox_sts[3]));
+ break;
+
+ case MBOX_ASTS_SYSTEM_WARNING_EVENT:
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
+ ha->host_no, mbox_sts[0], mbox_sts[1],
+ mbox_sts[2], mbox_sts[3], mbox_sts[4],
+ mbox_sts[5]));
+ break;
+
+ case MBOX_ASTS_DCBX_CONF_CHANGE:
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
+ ha->host_no, mbox_sts[0], mbox_sts[1],
+ mbox_sts[2], mbox_sts[3], mbox_sts[4],
+ mbox_sts[5]));
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "scsi%ld: AEN %04x Received DCBX configuration changed notification\n",
+ ha->host_no, mbox_sts[0]));
+ break;
+
default:
DEBUG2(printk(KERN_WARNING
"scsi%ld: AEN %04x UNKNOWN\n",
@@ -1065,8 +1134,8 @@ irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id)
status = qla4_82xx_rd_32(ha, ISR_INT_STATE_REG);
if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) {
- DEBUG2(ql4_printk(KERN_INFO, ha,
- "%s legacy Int not triggered\n", __func__));
+ DEBUG7(ql4_printk(KERN_INFO, ha,
+ "%s legacy Int not triggered\n", __func__));
return IRQ_NONE;
}
@@ -1124,17 +1193,18 @@ irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id)
/* Legacy interrupt is valid if bit31 of leg_int_ptr is set */
if (!(leg_int_ptr & LEG_INT_PTR_B31)) {
- ql4_printk(KERN_ERR, ha,
- "%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n",
- __func__);
+ DEBUG7(ql4_printk(KERN_ERR, ha,
+ "%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n",
+ __func__));
return IRQ_NONE;
}
/* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */
if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit) {
- ql4_printk(KERN_ERR, ha,
- "%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n",
- __func__, (leg_int_ptr & PF_BITS_MASK), ha->pf_bit);
+ DEBUG7(ql4_printk(KERN_ERR, ha,
+ "%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n",
+ __func__, (leg_int_ptr & PF_BITS_MASK),
+ ha->pf_bit));
return IRQ_NONE;
}
@@ -1437,11 +1507,14 @@ irq_not_attached:
void qla4xxx_free_irqs(struct scsi_qla_host *ha)
{
- if (test_bit(AF_MSIX_ENABLED, &ha->flags))
- qla4_8xxx_disable_msix(ha);
- else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) {
- free_irq(ha->pdev->irq, ha);
- pci_disable_msi(ha->pdev);
- } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags))
- free_irq(ha->pdev->irq, ha);
+ if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) {
+ if (test_bit(AF_MSIX_ENABLED, &ha->flags)) {
+ qla4_8xxx_disable_msix(ha);
+ } else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) {
+ free_irq(ha->pdev->irq, ha);
+ pci_disable_msi(ha->pdev);
+ } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags)) {
+ free_irq(ha->pdev->irq, ha);
+ }
+ }
}
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 3d41034..a501bea 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -44,6 +44,30 @@ void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int out_count)
}
/**
+ * qla4xxx_is_intr_poll_mode – Are we allowed to poll for interrupts?
+ * @ha: Pointer to host adapter structure.
+ * @ret: 1=polling mode, 0=non-polling mode
+ **/
+static int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha)
+{
+ int rval = 1;
+
+ if (is_qla8032(ha)) {
+ if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
+ test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags))
+ rval = 0;
+ } else {
+ if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
+ test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
+ test_bit(AF_ONLINE, &ha->flags) &&
+ !test_bit(AF_HA_REMOVAL, &ha->flags))
+ rval = 0;
+ }
+
+ return rval;
+}
+
+/**
* qla4xxx_mailbox_command - issues mailbox commands
* @ha: Pointer to host adapter structure.
* @inCount: number of mailbox registers to load.
@@ -153,33 +177,28 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
/*
* Wait for completion: Poll or completion queue
*/
- if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
- test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
- test_bit(AF_ONLINE, &ha->flags) &&
- !test_bit(AF_HA_REMOVAL, &ha->flags)) {
- /* Do not poll for completion. Use completion queue */
- set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
- wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
- clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
- } else {
+ if (qla4xxx_is_intr_poll_mode(ha)) {
/* Poll for command to complete */
wait_count = jiffies + MBOX_TOV * HZ;
while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
if (time_after_eq(jiffies, wait_count))
break;
-
/*
* Service the interrupt.
* The ISR will save the mailbox status registers
* to a temporary storage location in the adapter
* structure.
*/
-
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops->process_mailbox_interrupt(ha, outCount);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
msleep(10);
}
+ } else {
+ /* Do not poll for completion. Use completion queue */
+ set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
+ wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
+ clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
}
/* Check for mailbox timeout. */
@@ -678,8 +697,24 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
return QLA_ERROR;
}
- ql4_printk(KERN_INFO, ha, "%ld firmware IOCBs available (%d).\n",
- ha->host_no, mbox_sts[2]);
+ /* High-water mark of IOCBs */
+ ha->iocb_hiwat = mbox_sts[2];
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: firmware IOCBs available = %d\n", __func__,
+ ha->iocb_hiwat));
+
+ if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
+ ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
+
+ /* Ideally, we should not enter this code, as the # of firmware
+ * IOCBs is hard-coded in the firmware. We set a default
+ * iocb_hiwat here just in case */
+ if (ha->iocb_hiwat == 0) {
+ ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4;
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "%s: Setting IOCB's to = %d\n", __func__,
+ ha->iocb_hiwat));
+ }
return QLA_SUCCESS;
}
@@ -1094,6 +1129,7 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
+ uint32_t scsi_lun[2];
int status = QLA_SUCCESS;
DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
@@ -1105,10 +1141,16 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
*/
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_sts));
+ int_to_scsilun(lun, (struct scsi_lun *) scsi_lun);
mbox_cmd[0] = MBOX_CMD_LUN_RESET;
mbox_cmd[1] = ddb_entry->fw_ddb_index;
- mbox_cmd[2] = lun << 8;
+ /* FW expects LUN bytes 0-3 in Incoming Mailbox 2
+ * (LUN byte 0 is LSByte, byte 3 is MSByte) */
+ mbox_cmd[2] = cpu_to_le32(scsi_lun[0]);
+ /* FW expects LUN bytes 4-7 in Incoming Mailbox 3
+ * (LUN byte 4 is LSByte, byte 7 is MSByte) */
+ mbox_cmd[3] = cpu_to_le32(scsi_lun[1]);
mbox_cmd[5] = 0x01; /* Immediate Command Enable */
qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
@@ -1246,8 +1288,8 @@ exit_about_fw:
return status;
}
-static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
- dma_addr_t dma_addr)
+int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
+ dma_addr_t dma_addr)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -1375,6 +1417,55 @@ exit_bootdb_failed:
return status;
}
+int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
+{
+ uint32_t dev_db_start_offset;
+ uint32_t dev_db_end_offset;
+ int status = QLA_ERROR;
+
+ memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
+
+ if (is_qla40XX(ha)) {
+ dev_db_start_offset = FLASH_OFFSET_DB_INFO;
+ dev_db_end_offset = FLASH_OFFSET_DB_END;
+ } else {
+ dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +
+ (ha->hw.flt_region_ddb << 2);
+ /* flt_ddb_size is DDB table size for both ports
+ * so divide it by 2 to calculate the offset for second port
+ */
+ if (ha->port_num == 1)
+ dev_db_start_offset += (ha->hw.flt_ddb_size / 2);
+
+ dev_db_end_offset = dev_db_start_offset +
+ (ha->hw.flt_ddb_size / 2);
+ }
+
+ dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
+
+ if (dev_db_start_offset > dev_db_end_offset) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s:Invalid DDB index %d", __func__,
+ ddb_index));
+ goto exit_fdb_failed;
+ }
+
+ if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
+ sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n",
+ ha->host_no, __func__);
+ goto exit_fdb_failed;
+ }
+
+ if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
+ status = QLA_SUCCESS;
+
+exit_fdb_failed:
+ return status;
+}
+
int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
uint16_t idx)
{
@@ -1385,10 +1476,8 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
dma_addr_t chap_dma;
chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
- if (chap_table == NULL) {
- ret = -ENOMEM;
- goto exit_get_chap;
- }
+ if (chap_table == NULL)
+ return -ENOMEM;
chap_size = sizeof(struct ql4_chap_table);
memset(chap_table, 0, chap_size);
@@ -1470,6 +1559,62 @@ exit_set_chap:
return ret;
}
+
+int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
+ char *password, uint16_t chap_index)
+{
+ int rval = QLA_ERROR;
+ struct ql4_chap_table *chap_table = NULL;
+ int max_chap_entries;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ rval = QLA_ERROR;
+ goto exit_uni_chap;
+ }
+
+ if (!username || !password) {
+ ql4_printk(KERN_ERR, ha, "No memory for username & secret\n");
+ rval = QLA_ERROR;
+ goto exit_uni_chap;
+ }
+
+ if (is_qla80XX(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (chap_index > max_chap_entries) {
+ ql4_printk(KERN_ERR, ha, "Invalid Chap index\n");
+ rval = QLA_ERROR;
+ goto exit_uni_chap;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index;
+ if (chap_table->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ rval = QLA_ERROR;
+ goto exit_unlock_uni_chap;
+ }
+
+ if (!(chap_table->flags & BIT_6)) {
+ ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n");
+ rval = QLA_ERROR;
+ goto exit_unlock_uni_chap;
+ }
+
+ strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
+ strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
+
+ rval = QLA_SUCCESS;
+
+exit_unlock_uni_chap:
+ mutex_unlock(&ha->chap_sem);
+exit_uni_chap:
+ return rval;
+}
+
/**
* qla4xxx_get_chap_index - Get chap index given username and secret
* @ha: pointer to adapter structure
@@ -1491,7 +1636,7 @@ int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
int max_chap_entries = 0;
struct ql4_chap_table *chap_table;
- if (is_qla8022(ha))
+ if (is_qla80XX(ha))
max_chap_entries = (ha->hw.flt_chap_size / 2) /
sizeof(struct ql4_chap_table);
else
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 499a92d..eaf00c1 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -2089,7 +2089,7 @@ static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha,
if (r_addr & 0xf) {
DEBUG2(ql4_printk(KERN_INFO, ha,
- "[%s]: Read addr 0x%x not 16 bytes alligned\n",
+ "[%s]: Read addr 0x%x not 16 bytes aligned\n",
__func__, r_addr));
return QLA_ERROR;
}
@@ -2986,7 +2986,7 @@ int qla4_8xxx_load_risc(struct scsi_qla_host *ha)
retval = qla4_8xxx_device_state_handler(ha);
- if (retval == QLA_SUCCESS && !test_bit(AF_INIT_DONE, &ha->flags))
+ if (retval == QLA_SUCCESS && !test_bit(AF_IRQ_ATTACHED, &ha->flags))
retval = qla4xxx_request_irqs(ha);
return retval;
@@ -3154,6 +3154,10 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
hw->flt_region_chap = start;
hw->flt_chap_size = le32_to_cpu(region->size);
break;
+ case FLT_REG_ISCSI_DDB:
+ hw->flt_region_ddb = start;
+ hw->flt_ddb_size = le32_to_cpu(region->size);
+ break;
}
}
goto done;
@@ -3166,14 +3170,19 @@ no_flash_data:
hw->flt_region_boot = FA_BOOT_CODE_ADDR_82;
hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82;
hw->flt_region_fw = FA_RISC_CODE_ADDR_82;
- hw->flt_region_chap = FA_FLASH_ISCSI_CHAP;
+ hw->flt_region_chap = FA_FLASH_ISCSI_CHAP >> 2;
hw->flt_chap_size = FA_FLASH_CHAP_SIZE;
+ hw->flt_region_ddb = FA_FLASH_ISCSI_DDB >> 2;
+ hw->flt_ddb_size = FA_FLASH_DDB_SIZE;
done:
- DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x "
- "boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt,
- hw->flt_region_fdt, hw->flt_region_boot, hw->flt_region_bootload,
- hw->flt_region_fw));
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "FLT[%s]: flt=0x%x fdt=0x%x boot=0x%x bootload=0x%x fw=0x%x chap=0x%x chap_size=0x%x ddb=0x%x ddb_size=0x%x\n",
+ loc, hw->flt_region_flt, hw->flt_region_fdt,
+ hw->flt_region_boot, hw->flt_region_bootload,
+ hw->flt_region_fw, hw->flt_region_chap,
+ hw->flt_chap_size, hw->flt_region_ddb,
+ hw->flt_ddb_size));
}
static void
@@ -3427,11 +3436,11 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
}
/* Make sure we receive the minimum required data to cache internally */
- if (mbox_sts[4] < offsetof(struct mbx_sys_info, reserved)) {
+ if ((is_qla8032(ha) ? mbox_sts[3] : mbox_sts[4]) <
+ offsetof(struct mbx_sys_info, reserved)) {
DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive"
" error (%x)\n", ha->host_no, __func__, mbox_sts[4]));
goto exit_validate_mac82;
-
}
/* Save M.A.C. address & serial_number */
@@ -3463,7 +3472,7 @@ exit_validate_mac82:
/* Interrupt handling helpers. */
-int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha)
+int qla4_8xxx_intr_enable(struct scsi_qla_host *ha)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -3484,7 +3493,7 @@ int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha)
return QLA_SUCCESS;
}
-int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha)
+int qla4_8xxx_intr_disable(struct scsi_qla_host *ha)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -3509,7 +3518,7 @@ int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha)
void
qla4_82xx_enable_intrs(struct scsi_qla_host *ha)
{
- qla4_8xxx_mbx_intr_enable(ha);
+ qla4_8xxx_intr_enable(ha);
spin_lock_irq(&ha->hardware_lock);
/* BIT 10 - reset */
@@ -3522,7 +3531,7 @@ void
qla4_82xx_disable_intrs(struct scsi_qla_host *ha)
{
if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags))
- qla4_8xxx_mbx_intr_disable(ha);
+ qla4_8xxx_intr_disable(ha);
spin_lock_irq(&ha->hardware_lock);
/* BIT 10 - set */
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index fbc546e..b246b3c 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -166,6 +166,26 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
int reason);
+/*
+ * iSCSI Flash DDB sysfs entry points
+ */
+static int
+qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn,
+ void *data, int len);
+static int
+qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
+ int param, char *buf);
+static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,
+ int len);
+static int
+qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess);
+static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn);
+static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn);
+static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess);
+
static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
QLA82XX_LEGACY_INTR_CONFIG;
@@ -232,6 +252,13 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
.send_ping = qla4xxx_send_ping,
.get_chap = qla4xxx_get_chap_list,
.delete_chap = qla4xxx_delete_chap,
+ .get_flashnode_param = qla4xxx_sysfs_ddb_get_param,
+ .set_flashnode_param = qla4xxx_sysfs_ddb_set_param,
+ .new_flashnode = qla4xxx_sysfs_ddb_add,
+ .del_flashnode = qla4xxx_sysfs_ddb_delete,
+ .login_flashnode = qla4xxx_sysfs_ddb_login,
+ .logout_flashnode = qla4xxx_sysfs_ddb_logout,
+ .logout_flashnode_sid = qla4xxx_sysfs_ddb_logout_sid,
};
static struct scsi_transport_template *qla4xxx_scsi_transport;
@@ -376,6 +403,68 @@ static umode_t qla4_attr_is_visible(int param_type, int param)
default:
return 0;
}
+ case ISCSI_FLASHNODE_PARAM:
+ switch (param) {
+ case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6:
+ case ISCSI_FLASHNODE_PORTAL_TYPE:
+ case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE:
+ case ISCSI_FLASHNODE_DISCOVERY_SESS:
+ case ISCSI_FLASHNODE_ENTRY_EN:
+ case ISCSI_FLASHNODE_HDR_DGST_EN:
+ case ISCSI_FLASHNODE_DATA_DGST_EN:
+ case ISCSI_FLASHNODE_IMM_DATA_EN:
+ case ISCSI_FLASHNODE_INITIAL_R2T_EN:
+ case ISCSI_FLASHNODE_DATASEQ_INORDER:
+ case ISCSI_FLASHNODE_PDU_INORDER:
+ case ISCSI_FLASHNODE_CHAP_AUTH_EN:
+ case ISCSI_FLASHNODE_SNACK_REQ_EN:
+ case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN:
+ case ISCSI_FLASHNODE_BIDI_CHAP_EN:
+ case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL:
+ case ISCSI_FLASHNODE_ERL:
+ case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT:
+ case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE:
+ case ISCSI_FLASHNODE_TCP_WSF_DISABLE:
+ case ISCSI_FLASHNODE_TCP_TIMER_SCALE:
+ case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN:
+ case ISCSI_FLASHNODE_IP_FRAG_DISABLE:
+ case ISCSI_FLASHNODE_MAX_RECV_DLENGTH:
+ case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH:
+ case ISCSI_FLASHNODE_FIRST_BURST:
+ case ISCSI_FLASHNODE_DEF_TIME2WAIT:
+ case ISCSI_FLASHNODE_DEF_TIME2RETAIN:
+ case ISCSI_FLASHNODE_MAX_R2T:
+ case ISCSI_FLASHNODE_KEEPALIVE_TMO:
+ case ISCSI_FLASHNODE_ISID:
+ case ISCSI_FLASHNODE_TSID:
+ case ISCSI_FLASHNODE_PORT:
+ case ISCSI_FLASHNODE_MAX_BURST:
+ case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO:
+ case ISCSI_FLASHNODE_IPADDR:
+ case ISCSI_FLASHNODE_ALIAS:
+ case ISCSI_FLASHNODE_REDIRECT_IPADDR:
+ case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE:
+ case ISCSI_FLASHNODE_LOCAL_PORT:
+ case ISCSI_FLASHNODE_IPV4_TOS:
+ case ISCSI_FLASHNODE_IPV6_TC:
+ case ISCSI_FLASHNODE_IPV6_FLOW_LABEL:
+ case ISCSI_FLASHNODE_NAME:
+ case ISCSI_FLASHNODE_TPGT:
+ case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:
+ case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX:
+ case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE:
+ case ISCSI_FLASHNODE_TCP_XMIT_WSF:
+ case ISCSI_FLASHNODE_TCP_RECV_WSF:
+ case ISCSI_FLASHNODE_CHAP_OUT_IDX:
+ case ISCSI_FLASHNODE_USERNAME:
+ case ISCSI_FLASHNODE_PASSWORD:
+ case ISCSI_FLASHNODE_STATSN:
+ case ISCSI_FLASHNODE_EXP_STATSN:
+ case ISCSI_FLASHNODE_IS_BOOT_TGT:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
}
return 0;
@@ -391,7 +480,7 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
int valid_chap_entries = 0;
int ret = 0, i;
- if (is_qla8022(ha))
+ if (is_qla80XX(ha))
max_chap_entries = (ha->hw.flt_chap_size / 2) /
sizeof(struct ql4_chap_table);
else
@@ -495,7 +584,7 @@ static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx)
memset(chap_table, 0, sizeof(struct ql4_chap_table));
- if (is_qla8022(ha))
+ if (is_qla80XX(ha))
max_chap_entries = (ha->hw.flt_chap_size / 2) /
sizeof(struct ql4_chap_table);
else
@@ -1337,18 +1426,18 @@ static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,
sess->password_in, BIDI_CHAP,
&idx);
if (rval)
- return -EINVAL;
-
- len = sprintf(buf, "%hu\n", idx);
+ len = sprintf(buf, "\n");
+ else
+ len = sprintf(buf, "%hu\n", idx);
break;
case ISCSI_PARAM_CHAP_OUT_IDX:
rval = qla4xxx_get_chap_index(ha, sess->username,
sess->password, LOCAL_CHAP,
&idx);
if (rval)
- return -EINVAL;
-
- len = sprintf(buf, "%hu\n", idx);
+ len = sprintf(buf, "\n");
+ else
+ len = sprintf(buf, "%hu\n", idx);
break;
default:
return iscsi_session_get_param(cls_sess, param, buf);
@@ -1922,6 +2011,252 @@ static int qla4xxx_task_xmit(struct iscsi_task *task)
return -ENOSYS;
}
+static int qla4xxx_copy_from_fwddb_param(struct iscsi_bus_flash_session *sess,
+ struct iscsi_bus_flash_conn *conn,
+ struct dev_db_entry *fw_ddb_entry)
+{
+ unsigned long options = 0;
+ int rc = 0;
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options);
+ if (test_bit(OPT_IPV6_DEVICE, &options)) {
+ rc = iscsi_switch_str_param(&sess->portal_type,
+ PORTAL_TYPE_IPV6);
+ if (rc)
+ goto exit_copy;
+ } else {
+ rc = iscsi_switch_str_param(&sess->portal_type,
+ PORTAL_TYPE_IPV4);
+ if (rc)
+ goto exit_copy;
+ }
+
+ sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE,
+ &options);
+ sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options);
+ sess->entry_state = test_bit(OPT_ENTRY_STATE, &options);
+
+ options = le16_to_cpu(fw_ddb_entry->iscsi_options);
+ conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options);
+ conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options);
+ sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options);
+ sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options);
+ sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER,
+ &options);
+ sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options);
+ sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options);
+ conn->snack_req_en = test_bit(ISCSIOPT_SNACK_REQ_EN, &options);
+ sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN,
+ &options);
+ sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options);
+ sess->discovery_auth_optional =
+ test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options);
+ if (test_bit(ISCSIOPT_ERL1, &options))
+ sess->erl |= BIT_1;
+ if (test_bit(ISCSIOPT_ERL0, &options))
+ sess->erl |= BIT_0;
+
+ options = le16_to_cpu(fw_ddb_entry->tcp_options);
+ conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options);
+ conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options);
+ conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options);
+ if (test_bit(TCPOPT_TIMER_SCALE3, &options))
+ conn->tcp_timer_scale |= BIT_3;
+ if (test_bit(TCPOPT_TIMER_SCALE2, &options))
+ conn->tcp_timer_scale |= BIT_2;
+ if (test_bit(TCPOPT_TIMER_SCALE1, &options))
+ conn->tcp_timer_scale |= BIT_1;
+
+ conn->tcp_timer_scale >>= 1;
+ conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options);
+
+ options = le16_to_cpu(fw_ddb_entry->ip_options);
+ conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options);
+
+ conn->max_recv_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
+ conn->max_xmit_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
+ sess->first_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
+ sess->max_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
+ sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
+ sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
+ sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
+ sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+ conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss);
+ conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf;
+ conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf;
+ conn->ipv6_flow_label = le16_to_cpu(fw_ddb_entry->ipv6_flow_lbl);
+ conn->keepalive_timeout = le16_to_cpu(fw_ddb_entry->ka_timeout);
+ conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port);
+ conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn);
+ conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn);
+ sess->discovery_parent_idx = le16_to_cpu(fw_ddb_entry->ddb_link);
+ sess->discovery_parent_type = le16_to_cpu(fw_ddb_entry->ddb_link);
+ sess->chap_out_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
+ sess->tsid = le16_to_cpu(fw_ddb_entry->tsid);
+
+ sess->default_taskmgmt_timeout =
+ le16_to_cpu(fw_ddb_entry->def_timeout);
+ conn->port = le16_to_cpu(fw_ddb_entry->port);
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ conn->ipaddress = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL);
+ if (!conn->ipaddress) {
+ rc = -ENOMEM;
+ goto exit_copy;
+ }
+
+ conn->redirect_ipaddr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL);
+ if (!conn->redirect_ipaddr) {
+ rc = -ENOMEM;
+ goto exit_copy;
+ }
+
+ memcpy(conn->ipaddress, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);
+ memcpy(conn->redirect_ipaddr, fw_ddb_entry->tgt_addr, IPv6_ADDR_LEN);
+
+ if (test_bit(OPT_IPV6_DEVICE, &options)) {
+ conn->ipv6_traffic_class = fw_ddb_entry->ipv4_tos;
+
+ conn->link_local_ipv6_addr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL);
+ if (!conn->link_local_ipv6_addr) {
+ rc = -ENOMEM;
+ goto exit_copy;
+ }
+
+ memcpy(conn->link_local_ipv6_addr,
+ fw_ddb_entry->link_local_ipv6_addr, IPv6_ADDR_LEN);
+ } else {
+ conn->ipv4_tos = fw_ddb_entry->ipv4_tos;
+ }
+
+ if (fw_ddb_entry->iscsi_name[0]) {
+ rc = iscsi_switch_str_param(&sess->targetname,
+ (char *)fw_ddb_entry->iscsi_name);
+ if (rc)
+ goto exit_copy;
+ }
+
+ if (fw_ddb_entry->iscsi_alias[0]) {
+ rc = iscsi_switch_str_param(&sess->targetalias,
+ (char *)fw_ddb_entry->iscsi_alias);
+ if (rc)
+ goto exit_copy;
+ }
+
+ COPY_ISID(sess->isid, fw_ddb_entry->isid);
+
+exit_copy:
+ return rc;
+}
+
+static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess,
+ struct iscsi_bus_flash_conn *conn,
+ struct dev_db_entry *fw_ddb_entry)
+{
+ uint16_t options;
+ int rc = 0;
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ SET_BITVAL(conn->is_fw_assigned_ipv6, options, BIT_11);
+ if (!strncmp(sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ options |= BIT_8;
+ else
+ options &= ~BIT_8;
+
+ SET_BITVAL(sess->auto_snd_tgt_disable, options, BIT_6);
+ SET_BITVAL(sess->discovery_sess, options, BIT_4);
+ SET_BITVAL(sess->entry_state, options, BIT_3);
+ fw_ddb_entry->options = cpu_to_le16(options);
+
+ options = le16_to_cpu(fw_ddb_entry->iscsi_options);
+ SET_BITVAL(conn->hdrdgst_en, options, BIT_13);
+ SET_BITVAL(conn->datadgst_en, options, BIT_12);
+ SET_BITVAL(sess->imm_data_en, options, BIT_11);
+ SET_BITVAL(sess->initial_r2t_en, options, BIT_10);
+ SET_BITVAL(sess->dataseq_inorder_en, options, BIT_9);
+ SET_BITVAL(sess->pdu_inorder_en, options, BIT_8);
+ SET_BITVAL(sess->chap_auth_en, options, BIT_7);
+ SET_BITVAL(conn->snack_req_en, options, BIT_6);
+ SET_BITVAL(sess->discovery_logout_en, options, BIT_5);
+ SET_BITVAL(sess->bidi_chap_en, options, BIT_4);
+ SET_BITVAL(sess->discovery_auth_optional, options, BIT_3);
+ SET_BITVAL(sess->erl & BIT_1, options, BIT_1);
+ SET_BITVAL(sess->erl & BIT_0, options, BIT_0);
+ fw_ddb_entry->iscsi_options = cpu_to_le16(options);
+
+ options = le16_to_cpu(fw_ddb_entry->tcp_options);
+ SET_BITVAL(conn->tcp_timestamp_stat, options, BIT_6);
+ SET_BITVAL(conn->tcp_nagle_disable, options, BIT_5);
+ SET_BITVAL(conn->tcp_wsf_disable, options, BIT_4);
+ SET_BITVAL(conn->tcp_timer_scale & BIT_2, options, BIT_3);
+ SET_BITVAL(conn->tcp_timer_scale & BIT_1, options, BIT_2);
+ SET_BITVAL(conn->tcp_timer_scale & BIT_0, options, BIT_1);
+ SET_BITVAL(conn->tcp_timestamp_en, options, BIT_0);
+ fw_ddb_entry->tcp_options = cpu_to_le16(options);
+
+ options = le16_to_cpu(fw_ddb_entry->ip_options);
+ SET_BITVAL(conn->fragment_disable, options, BIT_4);
+ fw_ddb_entry->ip_options = cpu_to_le16(options);
+
+ fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
+ fw_ddb_entry->iscsi_max_rcv_data_seg_len =
+ cpu_to_le16(conn->max_recv_dlength / BYTE_UNITS);
+ fw_ddb_entry->iscsi_max_snd_data_seg_len =
+ cpu_to_le16(conn->max_xmit_dlength / BYTE_UNITS);
+ fw_ddb_entry->iscsi_first_burst_len =
+ cpu_to_le16(sess->first_burst / BYTE_UNITS);
+ fw_ddb_entry->iscsi_max_burst_len = cpu_to_le16(sess->max_burst /
+ BYTE_UNITS);
+ fw_ddb_entry->iscsi_def_time2wait = cpu_to_le16(sess->time2wait);
+ fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain);
+ fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt);
+ fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size);
+ fw_ddb_entry->tcp_xmt_wsf = (uint8_t) cpu_to_le32(conn->tcp_xmit_wsf);
+ fw_ddb_entry->tcp_rcv_wsf = (uint8_t) cpu_to_le32(conn->tcp_recv_wsf);
+ fw_ddb_entry->ipv4_tos = conn->ipv4_tos;
+ fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label);
+ fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout);
+ fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port);
+ fw_ddb_entry->stat_sn = cpu_to_le32(conn->statsn);
+ fw_ddb_entry->exp_stat_sn = cpu_to_le32(conn->exp_statsn);
+ fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_type);
+ fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx);
+ fw_ddb_entry->tsid = cpu_to_le16(sess->tsid);
+ fw_ddb_entry->port = cpu_to_le16(conn->port);
+ fw_ddb_entry->def_timeout =
+ cpu_to_le16(sess->default_taskmgmt_timeout);
+
+ if (conn->ipaddress)
+ memcpy(fw_ddb_entry->ip_addr, conn->ipaddress,
+ sizeof(fw_ddb_entry->ip_addr));
+
+ if (conn->redirect_ipaddr)
+ memcpy(fw_ddb_entry->tgt_addr, conn->redirect_ipaddr,
+ sizeof(fw_ddb_entry->tgt_addr));
+
+ if (conn->link_local_ipv6_addr)
+ memcpy(fw_ddb_entry->link_local_ipv6_addr,
+ conn->link_local_ipv6_addr,
+ sizeof(fw_ddb_entry->link_local_ipv6_addr));
+
+ if (sess->targetname)
+ memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
+ sizeof(fw_ddb_entry->iscsi_name));
+
+ if (sess->targetalias)
+ memcpy(fw_ddb_entry->iscsi_alias, sess->targetalias,
+ sizeof(fw_ddb_entry->iscsi_alias));
+
+ COPY_ISID(fw_ddb_entry->isid, sess->isid);
+
+ return rc;
+}
+
static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,
struct dev_db_entry *fw_ddb_entry,
struct iscsi_cls_session *cls_sess,
@@ -2242,6 +2577,7 @@ static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
!test_bit(AF_ONLINE, &ha->flags) ||
!test_bit(AF_LINK_UP, &ha->flags) ||
+ test_bit(AF_LOOPBACK, &ha->flags) ||
test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))
goto qc_host_busy;
@@ -2542,6 +2878,7 @@ static void qla4_8xxx_process_fw_error(struct scsi_qla_host *ha)
void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
{
uint32_t dev_state;
+ uint32_t idc_ctrl;
/* don't poll if reset is going on */
if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
@@ -2560,10 +2897,23 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
qla4xxx_wake_dpc(ha);
} else if (dev_state == QLA8XXX_DEV_NEED_RESET &&
!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
+
+ ql4_printk(KERN_INFO, ha, "%s: HW State: NEED RESET!\n",
+ __func__);
+
+ if (is_qla8032(ha)) {
+ idc_ctrl = qla4_83xx_rd_reg(ha,
+ QLA83XX_IDC_DRV_CTRL);
+ if (!(idc_ctrl & GRACEFUL_RESET_BIT1)) {
+ ql4_printk(KERN_INFO, ha, "%s: Graceful reset bit is not set\n",
+ __func__);
+ qla4xxx_mailbox_premature_completion(
+ ha);
+ }
+ }
+
if (is_qla8032(ha) ||
(is_qla8022(ha) && !ql4xdontresethba)) {
- ql4_printk(KERN_INFO, ha, "%s: HW State: "
- "NEED RESET!\n", __func__);
set_bit(DPC_RESET_HA, &ha->dpc_flags);
qla4xxx_wake_dpc(ha);
}
@@ -2978,6 +3328,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
if (status == QLA_SUCCESS) {
if (!test_bit(AF_FW_RECOVERY, &ha->flags))
qla4xxx_cmd_wait(ha);
+
ha->isp_ops->disable_intrs(ha);
qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
qla4xxx_abort_active_cmds(ha, DID_RESET << 16);
@@ -3479,7 +3830,8 @@ dpc_post_reset_ha:
}
/* ---- link change? --- */
- if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
+ if (!test_bit(AF_LOOPBACK, &ha->flags) &&
+ test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
if (!test_bit(AF_LINK_UP, &ha->flags)) {
/* ---- link down? --- */
qla4xxx_mark_all_devices_missing(ha);
@@ -3508,10 +3860,8 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
{
qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
- if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) {
- /* Turn-off interrupts on the card. */
- ha->isp_ops->disable_intrs(ha);
- }
+ /* Turn-off interrupts on the card. */
+ ha->isp_ops->disable_intrs(ha);
if (is_qla40XX(ha)) {
writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
@@ -3547,8 +3897,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
}
/* Detach interrupts */
- if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
- qla4xxx_free_irqs(ha);
+ qla4xxx_free_irqs(ha);
/* free extra memory */
qla4xxx_mem_free(ha);
@@ -3737,8 +4086,8 @@ static struct isp_operations qla4_83xx_isp_ops = {
.reset_firmware = qla4_8xxx_stop_firmware,
.queue_iocb = qla4_83xx_queue_iocb,
.complete_iocb = qla4_83xx_complete_iocb,
- .rd_shdw_req_q_out = qla4_83xx_rd_shdw_req_q_out,
- .rd_shdw_rsp_q_in = qla4_83xx_rd_shdw_rsp_q_in,
+ .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out,
+ .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in,
.get_sys_info = qla4_8xxx_get_sys_info,
.rd_reg_direct = qla4_83xx_rd_reg,
.wr_reg_direct = qla4_83xx_wr_reg,
@@ -3761,11 +4110,6 @@ uint16_t qla4_82xx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out));
}
-uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
-{
- return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->req_q_out));
-}
-
uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
{
return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in);
@@ -3776,11 +4120,6 @@ uint16_t qla4_82xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in));
}
-uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
-{
- return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->rsp_q_in));
-}
-
static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)
{
struct scsi_qla_host *ha = data;
@@ -4005,7 +4344,7 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
if (val & BIT_7)
ddb_index[1] = (val & 0x7f);
- } else if (is_qla8022(ha)) {
+ } else if (is_qla80XX(ha)) {
buf = dma_alloc_coherent(&ha->pdev->dev, size,
&buf_dma, GFP_KERNEL);
if (!buf) {
@@ -4083,7 +4422,7 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
int max_chap_entries = 0;
struct ql4_chap_table *chap_table;
- if (is_qla8022(ha))
+ if (is_qla80XX(ha))
max_chap_entries = (ha->hw.flt_chap_size / 2) /
sizeof(struct ql4_chap_table);
else
@@ -4687,7 +5026,8 @@ static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
struct iscsi_endpoint *ep;
struct sockaddr_in *addr;
struct sockaddr_in6 *addr6;
- struct sockaddr *dst_addr;
+ struct sockaddr *t_addr;
+ struct sockaddr_storage *dst_addr;
char *ip;
/* TODO: need to destroy on unload iscsi_endpoint*/
@@ -4696,21 +5036,23 @@ static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
return NULL;
if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
- dst_addr->sa_family = AF_INET6;
+ t_addr = (struct sockaddr *)dst_addr;
+ t_addr->sa_family = AF_INET6;
addr6 = (struct sockaddr_in6 *)dst_addr;
ip = (char *)&addr6->sin6_addr;
memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);
addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port));
} else {
- dst_addr->sa_family = AF_INET;
+ t_addr = (struct sockaddr *)dst_addr;
+ t_addr->sa_family = AF_INET;
addr = (struct sockaddr_in *)dst_addr;
ip = (char *)&addr->sin_addr;
memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN);
addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port));
}
- ep = qla4xxx_ep_connect(ha->host, dst_addr, 0);
+ ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0);
vfree(dst_addr);
return ep;
}
@@ -4725,7 +5067,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
}
static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry)
+ struct ddb_entry *ddb_entry,
+ uint16_t idx)
{
uint16_t def_timeout;
@@ -4745,6 +5088,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
def_timeout : LOGIN_TOV;
ddb_entry->default_time2wait =
le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
+
+ if (ql4xdisablesysfsboot &&
+ (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx))
+ set_bit(DF_BOOT_TGT, &ddb_entry->flags);
}
static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
@@ -4881,7 +5228,7 @@ static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
struct dev_db_entry *fw_ddb_entry,
- int is_reset)
+ int is_reset, uint16_t idx)
{
struct iscsi_cls_session *cls_sess;
struct iscsi_session *sess;
@@ -4919,7 +5266,7 @@ static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
sizeof(struct dev_db_entry));
- qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
+ qla4xxx_setup_flash_ddb_entry(ha, ddb_entry, idx);
cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
@@ -5036,7 +5383,7 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
goto continue_next_nt;
}
- ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
+ ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx);
if (ret == QLA_ERROR)
goto exit_nt_list;
@@ -5050,6 +5397,1327 @@ exit_nt_list:
dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
}
+static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha,
+ struct list_head *list_nt)
+{
+ struct dev_db_entry *fw_ddb_entry;
+ dma_addr_t fw_ddb_dma;
+ int max_ddbs;
+ int fw_idx_size;
+ int ret;
+ uint32_t idx = 0, next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+ uint16_t conn_id = 0;
+ struct qla_ddb_index *nt_ddb_idx;
+
+ fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
+ &fw_ddb_dma);
+ if (fw_ddb_entry == NULL) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
+ goto exit_new_nt_list;
+ }
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
+ fw_idx_size = sizeof(struct qla_ddb_index);
+
+ for (idx = 0; idx < max_ddbs; idx = next_idx) {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
+ NULL, &next_idx, &state,
+ &conn_err, NULL, &conn_id);
+ if (ret == QLA_ERROR)
+ break;
+
+ /* Check if NT, then add it to list */
+ if (strlen((char *)fw_ddb_entry->iscsi_name) == 0)
+ goto continue_next_new_nt;
+
+ if (!(state == DDB_DS_NO_CONNECTION_ACTIVE))
+ goto continue_next_new_nt;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Adding DDB to session = 0x%x\n", idx));
+
+ nt_ddb_idx = vmalloc(fw_idx_size);
+ if (!nt_ddb_idx)
+ break;
+
+ nt_ddb_idx->fw_ddb_idx = idx;
+
+ ret = qla4xxx_is_session_exists(ha, fw_ddb_entry);
+ if (ret == QLA_SUCCESS) {
+ /* free nt_ddb_idx and do not add to list_nt */
+ vfree(nt_ddb_idx);
+ goto continue_next_new_nt;
+ }
+
+ list_add_tail(&nt_ddb_idx->list, list_nt);
+
+ ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER,
+ idx);
+ if (ret == QLA_ERROR)
+ goto exit_new_nt_list;
+
+continue_next_new_nt:
+ if (next_idx == 0)
+ break;
+ }
+
+exit_new_nt_list:
+ if (fw_ddb_entry)
+ dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+}
+
+/**
+ * qla4xxx_sysfs_ddb_is_non_persistent - check for non-persistence of ddb entry
+ * @dev: dev associated with the sysfs entry
+ * @data: pointer to flashnode session object
+ *
+ * Returns:
+ * 1: if flashnode entry is non-persistent
+ * 0: if flashnode entry is persistent
+ **/
+static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data)
+{
+ struct iscsi_bus_flash_session *fnode_sess;
+
+ if (!iscsi_flashnode_bus_match(dev, NULL))
+ return 0;
+
+ fnode_sess = iscsi_dev_to_flash_session(dev);
+
+ return (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT);
+}
+
+/**
+ * qla4xxx_sysfs_ddb_tgt_create - Create sysfs entry for target
+ * @ha: pointer to host
+ * @fw_ddb_entry: flash ddb data
+ * @idx: target index
+ * @user: if set then this call is made from userland else from kernel
+ *
+ * Returns:
+ * On sucess: QLA_SUCCESS
+ * On failure: QLA_ERROR
+ *
+ * This create separate sysfs entries for session and connection attributes of
+ * the given fw ddb entry.
+ * If this is invoked as a result of a userspace call then the entry is marked
+ * as nonpersistent using flash_state field.
+ **/
+static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ uint16_t *idx, int user)
+{
+ struct iscsi_bus_flash_session *fnode_sess = NULL;
+ struct iscsi_bus_flash_conn *fnode_conn = NULL;
+ int rc = QLA_ERROR;
+
+ fnode_sess = iscsi_create_flashnode_sess(ha->host, *idx,
+ &qla4xxx_iscsi_transport, 0);
+ if (!fnode_sess) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to create session sysfs entry for flashnode %d of host%lu\n",
+ __func__, *idx, ha->host_no);
+ goto exit_tgt_create;
+ }
+
+ fnode_conn = iscsi_create_flashnode_conn(ha->host, fnode_sess,
+ &qla4xxx_iscsi_transport, 0);
+ if (!fnode_conn) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to create conn sysfs entry for flashnode %d of host%lu\n",
+ __func__, *idx, ha->host_no);
+ goto free_sess;
+ }
+
+ if (user) {
+ fnode_sess->flash_state = DEV_DB_NON_PERSISTENT;
+ } else {
+ fnode_sess->flash_state = DEV_DB_PERSISTENT;
+
+ if (*idx == ha->pri_ddb_idx || *idx == ha->sec_ddb_idx)
+ fnode_sess->is_boot_target = 1;
+ else
+ fnode_sess->is_boot_target = 0;
+ }
+
+ rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,
+ fw_ddb_entry);
+
+ ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
+ __func__, fnode_sess->dev.kobj.name);
+
+ ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
+ __func__, fnode_conn->dev.kobj.name);
+
+ return QLA_SUCCESS;
+
+free_sess:
+ iscsi_destroy_flashnode_sess(fnode_sess);
+
+exit_tgt_create:
+ return QLA_ERROR;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_add - Add new ddb entry in flash
+ * @shost: pointer to host
+ * @buf: type of ddb entry (ipv4/ipv6)
+ * @len: length of buf
+ *
+ * This creates new ddb entry in the flash by finding first free index and
+ * storing default ddb there. And then create sysfs entry for the new ddb entry.
+ **/
+static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,
+ int len)
+{
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ struct device *dev;
+ uint16_t idx = 0;
+ uint16_t max_ddbs = 0;
+ uint32_t options = 0;
+ uint32_t rval = QLA_ERROR;
+
+ if (strncasecmp(PORTAL_TYPE_IPV4, buf, 4) &&
+ strncasecmp(PORTAL_TYPE_IPV6, buf, 4)) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Invalid portal type\n",
+ __func__));
+ goto exit_ddb_add;
+ }
+
+ max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :
+ MAX_DEV_DB_ENTRIES;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ goto exit_ddb_add;
+ }
+
+ dev = iscsi_find_flashnode_sess(ha->host, NULL,
+ qla4xxx_sysfs_ddb_is_non_persistent);
+ if (dev) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: A non-persistent entry %s found\n",
+ __func__, dev->kobj.name);
+ put_device(dev);
+ goto exit_ddb_add;
+ }
+
+ for (idx = 0; idx < max_ddbs; idx++) {
+ if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry,
+ fw_ddb_entry_dma, idx))
+ break;
+ }
+
+ if (idx == max_ddbs)
+ goto exit_ddb_add;
+
+ if (!strncasecmp("ipv6", buf, 4))
+ options |= IPV6_DEFAULT_DDB_ENTRY;
+
+ rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
+ if (rval == QLA_ERROR)
+ goto exit_ddb_add;
+
+ rval = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 1);
+
+exit_ddb_add:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+ if (rval == QLA_SUCCESS)
+ return idx;
+ else
+ return -EIO;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_apply - write the target ddb contents to Flash
+ * @fnode_sess: pointer to session attrs of flash ddb entry
+ * @fnode_conn: pointer to connection attrs of flash ddb entry
+ *
+ * This writes the contents of target ddb buffer to Flash with a valid cookie
+ * value in order to make the ddb entry persistent.
+ **/
+static int qla4xxx_sysfs_ddb_apply(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn)
+{
+ struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ uint32_t options = 0;
+ int rval = 0;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ rval = -ENOMEM;
+ goto exit_ddb_apply;
+ }
+
+ if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ options |= IPV6_DEFAULT_DDB_ENTRY;
+
+ rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
+ if (rval == QLA_ERROR)
+ goto exit_ddb_apply;
+
+ dev_db_start_offset += (fnode_sess->target_id *
+ sizeof(*fw_ddb_entry));
+
+ qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry);
+ fw_ddb_entry->cookie = DDB_VALID_COOKIE;
+
+ rval = qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
+ sizeof(*fw_ddb_entry), FLASH_OPT_RMW_COMMIT);
+
+ if (rval == QLA_SUCCESS) {
+ fnode_sess->flash_state = DEV_DB_PERSISTENT;
+ ql4_printk(KERN_INFO, ha,
+ "%s: flash node %u of host %lu written to flash\n",
+ __func__, fnode_sess->target_id, ha->host_no);
+ } else {
+ rval = -EIO;
+ ql4_printk(KERN_ERR, ha,
+ "%s: Error while writing flash node %u of host %lu to flash\n",
+ __func__, fnode_sess->target_id, ha->host_no);
+ }
+
+exit_ddb_apply:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+ return rval;
+}
+
+static ssize_t qla4xxx_sysfs_ddb_conn_open(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ uint16_t idx)
+{
+ struct dev_db_entry *ddb_entry = NULL;
+ dma_addr_t ddb_entry_dma;
+ unsigned long wtime;
+ uint32_t mbx_sts = 0;
+ uint32_t state = 0, conn_err = 0;
+ uint16_t tmo = 0;
+ int ret = 0;
+
+ ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*ddb_entry),
+ &ddb_entry_dma, GFP_KERNEL);
+ if (!ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ return QLA_ERROR;
+ }
+
+ memcpy(ddb_entry, fw_ddb_entry, sizeof(*ddb_entry));
+
+ ret = qla4xxx_set_ddb_entry(ha, idx, ddb_entry_dma, &mbx_sts);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to set ddb entry for index %d\n",
+ __func__, idx));
+ goto exit_ddb_conn_open;
+ }
+
+ qla4xxx_conn_open(ha, idx);
+
+ /* To ensure that sendtargets is done, wait for at least 12 secs */
+ tmo = ((ha->def_timeout > LOGIN_TOV) &&
+ (ha->def_timeout < LOGIN_TOV * 10) ?
+ ha->def_timeout : LOGIN_TOV);
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Default time to wait for login to ddb %d\n", tmo));
+
+ wtime = jiffies + (HZ * tmo);
+ do {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL,
+ NULL, &state, &conn_err, NULL,
+ NULL);
+ if (ret == QLA_ERROR)
+ continue;
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED)
+ break;
+
+ schedule_timeout_uninterruptible(HZ / 10);
+ } while (time_after(wtime, jiffies));
+
+exit_ddb_conn_open:
+ if (ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*ddb_entry),
+ ddb_entry, ddb_entry_dma);
+ return ret;
+}
+
+static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry)
+{
+ struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
+ struct list_head list_nt;
+ uint16_t ddb_index;
+ int ret = 0;
+
+ if (test_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags)) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s: A discovery already in progress!\n", __func__);
+ return QLA_ERROR;
+ }
+
+ INIT_LIST_HEAD(&list_nt);
+
+ set_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags);
+
+ ret = qla4xxx_get_ddb_index(ha, &ddb_index);
+ if (ret == QLA_ERROR)
+ goto exit_login_st_clr_bit;
+
+ ret = qla4xxx_sysfs_ddb_conn_open(ha, fw_ddb_entry, ddb_index);
+ if (ret == QLA_ERROR)
+ goto exit_login_st;
+
+ qla4xxx_build_new_nt_list(ha, &list_nt);
+
+ list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) {
+ list_del_init(&ddb_idx->list);
+ qla4xxx_clear_ddb_entry(ha, ddb_idx->fw_ddb_idx);
+ vfree(ddb_idx);
+ }
+
+exit_login_st:
+ if (qla4xxx_clear_ddb_entry(ha, ddb_index) == QLA_ERROR) {
+ ql4_printk(KERN_ERR, ha,
+ "Unable to clear DDB index = 0x%x\n", ddb_index);
+ }
+
+ clear_bit(ddb_index, ha->ddb_idx_map);
+
+exit_login_st_clr_bit:
+ clear_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags);
+ return ret;
+}
+
+static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ uint16_t idx)
+{
+ int ret = QLA_ERROR;
+
+ ret = qla4xxx_is_session_exists(ha, fw_ddb_entry);
+ if (ret != QLA_SUCCESS)
+ ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER,
+ idx);
+ else
+ ret = -EPERM;
+
+ return ret;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_login - Login to the specified target
+ * @fnode_sess: pointer to session attrs of flash ddb entry
+ * @fnode_conn: pointer to connection attrs of flash ddb entry
+ *
+ * This logs in to the specified target
+ **/
+static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn)
+{
+ struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ uint32_t options = 0;
+ int ret = 0;
+
+ if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Target info is not persistent\n", __func__);
+ ret = -EIO;
+ goto exit_ddb_login;
+ }
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ ret = -ENOMEM;
+ goto exit_ddb_login;
+ }
+
+ if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ options |= IPV6_DEFAULT_DDB_ENTRY;
+
+ ret = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
+ if (ret == QLA_ERROR)
+ goto exit_ddb_login;
+
+ qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry);
+ fw_ddb_entry->cookie = DDB_VALID_COOKIE;
+
+ if (strlen((char *)fw_ddb_entry->iscsi_name) == 0)
+ ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry);
+ else
+ ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry,
+ fnode_sess->target_id);
+
+ if (ret > 0)
+ ret = -EIO;
+
+exit_ddb_login:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+ return ret;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_logout_sid - Logout session for the specified target
+ * @cls_sess: pointer to session to be logged out
+ *
+ * This performs session log out from the specified target
+ **/
+static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry = NULL;
+ struct scsi_qla_host *ha;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ unsigned long flags;
+ unsigned long wtime;
+ uint32_t ddb_state;
+ int options;
+ int ret = 0;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ if (ddb_entry->ddb_type != FLASH_DDB) {
+ ql4_printk(KERN_ERR, ha, "%s: Not a flash node session\n",
+ __func__);
+ ret = -ENXIO;
+ goto exit_ddb_logout;
+ }
+
+ if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Logout from boot target entry is not permitted.\n",
+ __func__);
+ ret = -EPERM;
+ goto exit_ddb_logout;
+ }
+
+ options = LOGOUT_OPTION_CLOSE_SESSION;
+ if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR) {
+ ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);
+ ret = -EIO;
+ goto exit_ddb_logout;
+ }
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ ret = -ENOMEM;
+ goto exit_ddb_logout;
+ }
+
+ wtime = jiffies + (HZ * LOGOUT_TOV);
+ do {
+ ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index,
+ fw_ddb_entry, fw_ddb_entry_dma,
+ NULL, NULL, &ddb_state, NULL,
+ NULL, NULL);
+ if (ret == QLA_ERROR)
+ goto ddb_logout_clr_sess;
+
+ if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) ||
+ (ddb_state == DDB_DS_SESSION_FAILED))
+ goto ddb_logout_clr_sess;
+
+ schedule_timeout_uninterruptible(HZ);
+ } while ((time_after(wtime, jiffies)));
+
+ddb_logout_clr_sess:
+ qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
+ /*
+ * we have decremented the reference count of the driver
+ * when we setup the session to have the driver unload
+ * to be seamless without actually destroying the
+ * session
+ **/
+ try_module_get(qla4xxx_iscsi_transport.owner);
+ iscsi_destroy_endpoint(ddb_entry->conn->ep);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ qla4xxx_free_ddb(ha, ddb_entry);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ iscsi_session_teardown(ddb_entry->sess);
+
+ ret = QLA_SUCCESS;
+
+exit_ddb_logout:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+ return ret;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_logout - Logout from the specified target
+ * @fnode_sess: pointer to session attrs of flash ddb entry
+ * @fnode_conn: pointer to connection attrs of flash ddb entry
+ *
+ * This performs log out from the specified target
+ **/
+static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn)
+{
+ struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ struct ql4_tuple_ddb *flash_tddb = NULL;
+ struct ql4_tuple_ddb *tmp_tddb = NULL;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ struct ddb_entry *ddb_entry = NULL;
+ dma_addr_t fw_ddb_dma;
+ uint32_t next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+ uint16_t conn_id = 0;
+ int idx, index;
+ int status, ret = 0;
+
+ fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
+ &fw_ddb_dma);
+ if (fw_ddb_entry == NULL) {
+ ql4_printk(KERN_ERR, ha, "%s:Out of memory\n", __func__);
+ ret = -ENOMEM;
+ goto exit_ddb_logout;
+ }
+
+ flash_tddb = vzalloc(sizeof(*flash_tddb));
+ if (!flash_tddb) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s:Memory Allocation failed.\n", __func__);
+ ret = -ENOMEM;
+ goto exit_ddb_logout;
+ }
+
+ tmp_tddb = vzalloc(sizeof(*tmp_tddb));
+ if (!tmp_tddb) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s:Memory Allocation failed.\n", __func__);
+ ret = -ENOMEM;
+ goto exit_ddb_logout;
+ }
+
+ if (!fnode_sess->targetname) {
+ ql4_printk(KERN_ERR, ha,
+ "%s:Cannot logout from SendTarget entry\n",
+ __func__);
+ ret = -EPERM;
+ goto exit_ddb_logout;
+ }
+
+ if (fnode_sess->is_boot_target) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Logout from boot target entry is not permitted.\n",
+ __func__);
+ ret = -EPERM;
+ goto exit_ddb_logout;
+ }
+
+ strncpy(flash_tddb->iscsi_name, fnode_sess->targetname,
+ ISCSI_NAME_SIZE);
+
+ if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ sprintf(flash_tddb->ip_addr, "%pI6", fnode_conn->ipaddress);
+ else
+ sprintf(flash_tddb->ip_addr, "%pI4", fnode_conn->ipaddress);
+
+ flash_tddb->tpgt = fnode_sess->tpgt;
+ flash_tddb->port = fnode_conn->port;
+
+ COPY_ISID(flash_tddb->isid, fnode_sess->isid);
+
+ for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
+ if (ddb_entry == NULL)
+ continue;
+
+ if (ddb_entry->ddb_type != FLASH_DDB)
+ continue;
+
+ index = ddb_entry->sess->target_id;
+ status = qla4xxx_get_fwddb_entry(ha, index, fw_ddb_entry,
+ fw_ddb_dma, NULL, &next_idx,
+ &state, &conn_err, NULL,
+ &conn_id);
+ if (status == QLA_ERROR) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ qla4xxx_convert_param_ddb(fw_ddb_entry, tmp_tddb, NULL);
+
+ status = qla4xxx_compare_tuple_ddb(ha, flash_tddb, tmp_tddb,
+ true);
+ if (status == QLA_SUCCESS) {
+ ret = qla4xxx_sysfs_ddb_logout_sid(ddb_entry->sess);
+ break;
+ }
+ }
+
+ if (idx == MAX_DDB_ENTRIES)
+ ret = -ESRCH;
+
+exit_ddb_logout:
+ if (flash_tddb)
+ vfree(flash_tddb);
+ if (tmp_tddb)
+ vfree(tmp_tddb);
+ if (fw_ddb_entry)
+ dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+
+ return ret;
+}
+
+static int
+qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
+ int param, char *buf)
+{
+ struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ struct iscsi_bus_flash_conn *fnode_conn;
+ struct ql4_chap_table chap_tbl;
+ struct device *dev;
+ int parent_type, parent_index = 0xffff;
+ int rc = 0;
+
+ dev = iscsi_find_flashnode_conn(fnode_sess);
+ if (!dev)
+ return -EIO;
+
+ fnode_conn = iscsi_dev_to_flash_conn(dev);
+
+ switch (param) {
+ case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6:
+ rc = sprintf(buf, "%u\n", fnode_conn->is_fw_assigned_ipv6);
+ break;
+ case ISCSI_FLASHNODE_PORTAL_TYPE:
+ rc = sprintf(buf, "%s\n", fnode_sess->portal_type);
+ break;
+ case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE:
+ rc = sprintf(buf, "%u\n", fnode_sess->auto_snd_tgt_disable);
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_SESS:
+ rc = sprintf(buf, "%u\n", fnode_sess->discovery_sess);
+ break;
+ case ISCSI_FLASHNODE_ENTRY_EN:
+ rc = sprintf(buf, "%u\n", fnode_sess->entry_state);
+ break;
+ case ISCSI_FLASHNODE_HDR_DGST_EN:
+ rc = sprintf(buf, "%u\n", fnode_conn->hdrdgst_en);
+ break;
+ case ISCSI_FLASHNODE_DATA_DGST_EN:
+ rc = sprintf(buf, "%u\n", fnode_conn->datadgst_en);
+ break;
+ case ISCSI_FLASHNODE_IMM_DATA_EN:
+ rc = sprintf(buf, "%u\n", fnode_sess->imm_data_en);
+ break;
+ case ISCSI_FLASHNODE_INITIAL_R2T_EN:
+ rc = sprintf(buf, "%u\n", fnode_sess->initial_r2t_en);
+ break;
+ case ISCSI_FLASHNODE_DATASEQ_INORDER:
+ rc = sprintf(buf, "%u\n", fnode_sess->dataseq_inorder_en);
+ break;
+ case ISCSI_FLASHNODE_PDU_INORDER:
+ rc = sprintf(buf, "%u\n", fnode_sess->pdu_inorder_en);
+ break;
+ case ISCSI_FLASHNODE_CHAP_AUTH_EN:
+ rc = sprintf(buf, "%u\n", fnode_sess->chap_auth_en);
+ break;
+ case ISCSI_FLASHNODE_SNACK_REQ_EN:
+ rc = sprintf(buf, "%u\n", fnode_conn->snack_req_en);
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN:
+ rc = sprintf(buf, "%u\n", fnode_sess->discovery_logout_en);
+ break;
+ case ISCSI_FLASHNODE_BIDI_CHAP_EN:
+ rc = sprintf(buf, "%u\n", fnode_sess->bidi_chap_en);
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL:
+ rc = sprintf(buf, "%u\n", fnode_sess->discovery_auth_optional);
+ break;
+ case ISCSI_FLASHNODE_ERL:
+ rc = sprintf(buf, "%u\n", fnode_sess->erl);
+ break;
+ case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_stat);
+ break;
+ case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_nagle_disable);
+ break;
+ case ISCSI_FLASHNODE_TCP_WSF_DISABLE:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_wsf_disable);
+ break;
+ case ISCSI_FLASHNODE_TCP_TIMER_SCALE:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_timer_scale);
+ break;
+ case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_en);
+ break;
+ case ISCSI_FLASHNODE_IP_FRAG_DISABLE:
+ rc = sprintf(buf, "%u\n", fnode_conn->fragment_disable);
+ break;
+ case ISCSI_FLASHNODE_MAX_RECV_DLENGTH:
+ rc = sprintf(buf, "%u\n", fnode_conn->max_recv_dlength);
+ break;
+ case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH:
+ rc = sprintf(buf, "%u\n", fnode_conn->max_xmit_dlength);
+ break;
+ case ISCSI_FLASHNODE_FIRST_BURST:
+ rc = sprintf(buf, "%u\n", fnode_sess->first_burst);
+ break;
+ case ISCSI_FLASHNODE_DEF_TIME2WAIT:
+ rc = sprintf(buf, "%u\n", fnode_sess->time2wait);
+ break;
+ case ISCSI_FLASHNODE_DEF_TIME2RETAIN:
+ rc = sprintf(buf, "%u\n", fnode_sess->time2retain);
+ break;
+ case ISCSI_FLASHNODE_MAX_R2T:
+ rc = sprintf(buf, "%u\n", fnode_sess->max_r2t);
+ break;
+ case ISCSI_FLASHNODE_KEEPALIVE_TMO:
+ rc = sprintf(buf, "%u\n", fnode_conn->keepalive_timeout);
+ break;
+ case ISCSI_FLASHNODE_ISID:
+ rc = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n",
+ fnode_sess->isid[0], fnode_sess->isid[1],
+ fnode_sess->isid[2], fnode_sess->isid[3],
+ fnode_sess->isid[4], fnode_sess->isid[5]);
+ break;
+ case ISCSI_FLASHNODE_TSID:
+ rc = sprintf(buf, "%u\n", fnode_sess->tsid);
+ break;
+ case ISCSI_FLASHNODE_PORT:
+ rc = sprintf(buf, "%d\n", fnode_conn->port);
+ break;
+ case ISCSI_FLASHNODE_MAX_BURST:
+ rc = sprintf(buf, "%u\n", fnode_sess->max_burst);
+ break;
+ case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO:
+ rc = sprintf(buf, "%u\n",
+ fnode_sess->default_taskmgmt_timeout);
+ break;
+ case ISCSI_FLASHNODE_IPADDR:
+ if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ rc = sprintf(buf, "%pI6\n", fnode_conn->ipaddress);
+ else
+ rc = sprintf(buf, "%pI4\n", fnode_conn->ipaddress);
+ break;
+ case ISCSI_FLASHNODE_ALIAS:
+ if (fnode_sess->targetalias)
+ rc = sprintf(buf, "%s\n", fnode_sess->targetalias);
+ else
+ rc = sprintf(buf, "\n");
+ break;
+ case ISCSI_FLASHNODE_REDIRECT_IPADDR:
+ if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ rc = sprintf(buf, "%pI6\n",
+ fnode_conn->redirect_ipaddr);
+ else
+ rc = sprintf(buf, "%pI4\n",
+ fnode_conn->redirect_ipaddr);
+ break;
+ case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE:
+ rc = sprintf(buf, "%u\n", fnode_conn->max_segment_size);
+ break;
+ case ISCSI_FLASHNODE_LOCAL_PORT:
+ rc = sprintf(buf, "%u\n", fnode_conn->local_port);
+ break;
+ case ISCSI_FLASHNODE_IPV4_TOS:
+ rc = sprintf(buf, "%u\n", fnode_conn->ipv4_tos);
+ break;
+ case ISCSI_FLASHNODE_IPV6_TC:
+ if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ rc = sprintf(buf, "%u\n",
+ fnode_conn->ipv6_traffic_class);
+ else
+ rc = sprintf(buf, "\n");
+ break;
+ case ISCSI_FLASHNODE_IPV6_FLOW_LABEL:
+ rc = sprintf(buf, "%u\n", fnode_conn->ipv6_flow_label);
+ break;
+ case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:
+ if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
+ rc = sprintf(buf, "%pI6\n",
+ fnode_conn->link_local_ipv6_addr);
+ else
+ rc = sprintf(buf, "\n");
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX:
+ if (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES)
+ parent_index = fnode_sess->discovery_parent_idx;
+
+ rc = sprintf(buf, "%u\n", parent_index);
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE:
+ if (fnode_sess->discovery_parent_type == DDB_ISNS)
+ parent_type = ISCSI_DISC_PARENT_ISNS;
+ else if (fnode_sess->discovery_parent_type == DDB_NO_LINK)
+ parent_type = ISCSI_DISC_PARENT_UNKNOWN;
+ else if (fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES)
+ parent_type = ISCSI_DISC_PARENT_SENDTGT;
+ else
+ parent_type = ISCSI_DISC_PARENT_UNKNOWN;
+
+ rc = sprintf(buf, "%s\n",
+ iscsi_get_discovery_parent_name(parent_type));
+ break;
+ case ISCSI_FLASHNODE_NAME:
+ if (fnode_sess->targetname)
+ rc = sprintf(buf, "%s\n", fnode_sess->targetname);
+ else
+ rc = sprintf(buf, "\n");
+ break;
+ case ISCSI_FLASHNODE_TPGT:
+ rc = sprintf(buf, "%u\n", fnode_sess->tpgt);
+ break;
+ case ISCSI_FLASHNODE_TCP_XMIT_WSF:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_xmit_wsf);
+ break;
+ case ISCSI_FLASHNODE_TCP_RECV_WSF:
+ rc = sprintf(buf, "%u\n", fnode_conn->tcp_recv_wsf);
+ break;
+ case ISCSI_FLASHNODE_CHAP_OUT_IDX:
+ rc = sprintf(buf, "%u\n", fnode_sess->chap_out_idx);
+ break;
+ case ISCSI_FLASHNODE_USERNAME:
+ if (fnode_sess->chap_auth_en) {
+ qla4xxx_get_uni_chap_at_index(ha,
+ chap_tbl.name,
+ chap_tbl.secret,
+ fnode_sess->chap_out_idx);
+ rc = sprintf(buf, "%s\n", chap_tbl.name);
+ } else {
+ rc = sprintf(buf, "\n");
+ }
+ break;
+ case ISCSI_FLASHNODE_PASSWORD:
+ if (fnode_sess->chap_auth_en) {
+ qla4xxx_get_uni_chap_at_index(ha,
+ chap_tbl.name,
+ chap_tbl.secret,
+ fnode_sess->chap_out_idx);
+ rc = sprintf(buf, "%s\n", chap_tbl.secret);
+ } else {
+ rc = sprintf(buf, "\n");
+ }
+ break;
+ case ISCSI_FLASHNODE_STATSN:
+ rc = sprintf(buf, "%u\n", fnode_conn->statsn);
+ break;
+ case ISCSI_FLASHNODE_EXP_STATSN:
+ rc = sprintf(buf, "%u\n", fnode_conn->exp_statsn);
+ break;
+ case ISCSI_FLASHNODE_IS_BOOT_TGT:
+ rc = sprintf(buf, "%u\n", fnode_sess->is_boot_target);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ put_device(dev);
+ return rc;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_set_param - Set parameter for firmware DDB entry
+ * @fnode_sess: pointer to session attrs of flash ddb entry
+ * @fnode_conn: pointer to connection attrs of flash ddb entry
+ * @data: Parameters and their values to update
+ * @len: len of data
+ *
+ * This sets the parameter of flash ddb entry and writes them to flash
+ **/
+static int
+qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_bus_flash_conn *fnode_conn,
+ void *data, int len)
+{
+ struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int rc = QLA_ERROR;
+ uint32_t rem = len;
+
+ nla_for_each_attr(attr, data, len, rem) {
+ fnode_param = nla_data(attr);
+
+ switch (fnode_param->param) {
+ case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6:
+ fnode_conn->is_fw_assigned_ipv6 = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_PORTAL_TYPE:
+ memcpy(fnode_sess->portal_type, fnode_param->value,
+ strlen(fnode_sess->portal_type));
+ break;
+ case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE:
+ fnode_sess->auto_snd_tgt_disable =
+ fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_SESS:
+ fnode_sess->discovery_sess = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_ENTRY_EN:
+ fnode_sess->entry_state = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_HDR_DGST_EN:
+ fnode_conn->hdrdgst_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_DATA_DGST_EN:
+ fnode_conn->datadgst_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_IMM_DATA_EN:
+ fnode_sess->imm_data_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_INITIAL_R2T_EN:
+ fnode_sess->initial_r2t_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_DATASEQ_INORDER:
+ fnode_sess->dataseq_inorder_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_PDU_INORDER:
+ fnode_sess->pdu_inorder_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_CHAP_AUTH_EN:
+ fnode_sess->chap_auth_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_SNACK_REQ_EN:
+ fnode_conn->snack_req_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN:
+ fnode_sess->discovery_logout_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_BIDI_CHAP_EN:
+ fnode_sess->bidi_chap_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL:
+ fnode_sess->discovery_auth_optional =
+ fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_ERL:
+ fnode_sess->erl = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT:
+ fnode_conn->tcp_timestamp_stat = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE:
+ fnode_conn->tcp_nagle_disable = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_TCP_WSF_DISABLE:
+ fnode_conn->tcp_wsf_disable = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_TCP_TIMER_SCALE:
+ fnode_conn->tcp_timer_scale = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN:
+ fnode_conn->tcp_timestamp_en = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_IP_FRAG_DISABLE:
+ fnode_conn->fragment_disable = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_MAX_RECV_DLENGTH:
+ fnode_conn->max_recv_dlength =
+ *(unsigned *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH:
+ fnode_conn->max_xmit_dlength =
+ *(unsigned *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_FIRST_BURST:
+ fnode_sess->first_burst =
+ *(unsigned *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_DEF_TIME2WAIT:
+ fnode_sess->time2wait = *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_DEF_TIME2RETAIN:
+ fnode_sess->time2retain =
+ *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_MAX_R2T:
+ fnode_sess->max_r2t =
+ *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_KEEPALIVE_TMO:
+ fnode_conn->keepalive_timeout =
+ *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_ISID:
+ memcpy(fnode_sess->isid, fnode_param->value,
+ sizeof(fnode_sess->isid));
+ break;
+ case ISCSI_FLASHNODE_TSID:
+ fnode_sess->tsid = *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_PORT:
+ fnode_conn->port = *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_MAX_BURST:
+ fnode_sess->max_burst = *(unsigned *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO:
+ fnode_sess->default_taskmgmt_timeout =
+ *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_IPADDR:
+ memcpy(fnode_conn->ipaddress, fnode_param->value,
+ IPv6_ADDR_LEN);
+ break;
+ case ISCSI_FLASHNODE_ALIAS:
+ rc = iscsi_switch_str_param(&fnode_sess->targetalias,
+ (char *)fnode_param->value);
+ break;
+ case ISCSI_FLASHNODE_REDIRECT_IPADDR:
+ memcpy(fnode_conn->redirect_ipaddr, fnode_param->value,
+ IPv6_ADDR_LEN);
+ break;
+ case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE:
+ fnode_conn->max_segment_size =
+ *(unsigned *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_LOCAL_PORT:
+ fnode_conn->local_port =
+ *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_IPV4_TOS:
+ fnode_conn->ipv4_tos = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_IPV6_TC:
+ fnode_conn->ipv6_traffic_class = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_IPV6_FLOW_LABEL:
+ fnode_conn->ipv6_flow_label = fnode_param->value[0];
+ break;
+ case ISCSI_FLASHNODE_NAME:
+ rc = iscsi_switch_str_param(&fnode_sess->targetname,
+ (char *)fnode_param->value);
+ break;
+ case ISCSI_FLASHNODE_TPGT:
+ fnode_sess->tpgt = *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:
+ memcpy(fnode_conn->link_local_ipv6_addr,
+ fnode_param->value, IPv6_ADDR_LEN);
+ break;
+ case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE:
+ fnode_sess->discovery_parent_type =
+ *(uint16_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_TCP_XMIT_WSF:
+ fnode_conn->tcp_xmit_wsf =
+ *(uint8_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_TCP_RECV_WSF:
+ fnode_conn->tcp_recv_wsf =
+ *(uint8_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_STATSN:
+ fnode_conn->statsn = *(uint32_t *)fnode_param->value;
+ break;
+ case ISCSI_FLASHNODE_EXP_STATSN:
+ fnode_conn->exp_statsn =
+ *(uint32_t *)fnode_param->value;
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha,
+ "%s: No such sysfs attribute\n", __func__);
+ rc = -ENOSYS;
+ goto exit_set_param;
+ }
+ }
+
+ rc = qla4xxx_sysfs_ddb_apply(fnode_sess, fnode_conn);
+
+exit_set_param:
+ return rc;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_delete - Delete firmware DDB entry
+ * @fnode_sess: pointer to session attrs of flash ddb entry
+ *
+ * This invalidates the flash ddb entry at the given index
+ **/
+static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess)
+{
+ struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ uint32_t dev_db_start_offset;
+ uint32_t dev_db_end_offset;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ uint16_t *ddb_cookie = NULL;
+ size_t ddb_size = 0;
+ void *pddb = NULL;
+ int target_id;
+ int rc = 0;
+
+ if (fnode_sess->is_boot_target) {
+ rc = -EPERM;
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Deletion of boot target entry is not permitted.\n",
+ __func__));
+ goto exit_ddb_del;
+ }
+
+ if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT)
+ goto sysfs_ddb_del;
+
+ if (is_qla40XX(ha)) {
+ dev_db_start_offset = FLASH_OFFSET_DB_INFO;
+ dev_db_end_offset = FLASH_OFFSET_DB_END;
+ dev_db_start_offset += (fnode_sess->target_id *
+ sizeof(*fw_ddb_entry));
+ ddb_size = sizeof(*fw_ddb_entry);
+ } else {
+ dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +
+ (ha->hw.flt_region_ddb << 2);
+ /* flt_ddb_size is DDB table size for both ports
+ * so divide it by 2 to calculate the offset for second port
+ */
+ if (ha->port_num == 1)
+ dev_db_start_offset += (ha->hw.flt_ddb_size / 2);
+
+ dev_db_end_offset = dev_db_start_offset +
+ (ha->hw.flt_ddb_size / 2);
+
+ dev_db_start_offset += (fnode_sess->target_id *
+ sizeof(*fw_ddb_entry));
+ dev_db_start_offset += offsetof(struct dev_db_entry, cookie);
+
+ ddb_size = sizeof(*ddb_cookie);
+ }
+
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: start offset=%u, end offset=%u\n",
+ __func__, dev_db_start_offset, dev_db_end_offset));
+
+ if (dev_db_start_offset > dev_db_end_offset) {
+ rc = -EIO;
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s:Invalid DDB index %u\n",
+ __func__, fnode_sess->target_id));
+ goto exit_ddb_del;
+ }
+
+ pddb = dma_alloc_coherent(&ha->pdev->dev, ddb_size,
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!pddb) {
+ rc = -ENOMEM;
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ goto exit_ddb_del;
+ }
+
+ if (is_qla40XX(ha)) {
+ fw_ddb_entry = pddb;
+ memset(fw_ddb_entry, 0, ddb_size);
+ ddb_cookie = &fw_ddb_entry->cookie;
+ } else {
+ ddb_cookie = pddb;
+ }
+
+ /* invalidate the cookie */
+ *ddb_cookie = 0xFFEE;
+ qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
+ ddb_size, FLASH_OPT_RMW_COMMIT);
+
+sysfs_ddb_del:
+ target_id = fnode_sess->target_id;
+ iscsi_destroy_flashnode_sess(fnode_sess);
+ ql4_printk(KERN_INFO, ha,
+ "%s: session and conn entries for flashnode %u of host %lu deleted\n",
+ __func__, target_id, ha->host_no);
+exit_ddb_del:
+ if (pddb)
+ dma_free_coherent(&ha->pdev->dev, ddb_size, pddb,
+ fw_ddb_entry_dma);
+ return rc;
+}
+
+/**
+ * qla4xxx_sysfs_ddb_export - Create sysfs entries for firmware DDBs
+ * @ha: pointer to adapter structure
+ *
+ * Export the firmware DDB for all send targets and normal targets to sysfs.
+ **/
+static int qla4xxx_sysfs_ddb_export(struct scsi_qla_host *ha)
+{
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ uint16_t max_ddbs;
+ uint16_t idx = 0;
+ int ret = QLA_SUCCESS;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ return -ENOMEM;
+ }
+
+ max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :
+ MAX_DEV_DB_ENTRIES;
+
+ for (idx = 0; idx < max_ddbs; idx++) {
+ if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, fw_ddb_entry_dma,
+ idx))
+ continue;
+
+ ret = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 0);
+ if (ret) {
+ ret = -EIO;
+ break;
+ }
+ }
+
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
+ fw_ddb_entry_dma);
+
+ return ret;
+}
+
+static void qla4xxx_sysfs_ddb_remove(struct scsi_qla_host *ha)
+{
+ iscsi_destroy_all_flashnode(ha->host);
+}
+
/**
* qla4xxx_build_ddb_list - Build ddb list and setup sessions
* @ha: pointer to adapter structure
@@ -5116,6 +6784,78 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
}
/**
+ * qla4xxx_wait_login_resp_boot_tgt - Wait for iSCSI boot target login
+ * response.
+ * @ha: pointer to adapter structure
+ *
+ * When the boot entry is normal iSCSI target then DF_BOOT_TGT flag will be
+ * set in DDB and we will wait for login response of boot targets during
+ * probe.
+ **/
+static void qla4xxx_wait_login_resp_boot_tgt(struct scsi_qla_host *ha)
+{
+ struct ddb_entry *ddb_entry;
+ struct dev_db_entry *fw_ddb_entry = NULL;
+ dma_addr_t fw_ddb_entry_dma;
+ unsigned long wtime;
+ uint32_t ddb_state;
+ int max_ddbs, idx, ret;
+
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ goto exit_login_resp;
+ }
+
+ wtime = jiffies + (HZ * BOOT_LOGIN_RESP_TOV);
+
+ for (idx = 0; idx < max_ddbs; idx++) {
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
+ if (ddb_entry == NULL)
+ continue;
+
+ if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: DDB index [%d]\n", __func__,
+ ddb_entry->fw_ddb_index));
+ do {
+ ret = qla4xxx_get_fwddb_entry(ha,
+ ddb_entry->fw_ddb_index,
+ fw_ddb_entry, fw_ddb_entry_dma,
+ NULL, NULL, &ddb_state, NULL,
+ NULL, NULL);
+ if (ret == QLA_ERROR)
+ goto exit_login_resp;
+
+ if ((ddb_state == DDB_DS_SESSION_ACTIVE) ||
+ (ddb_state == DDB_DS_SESSION_FAILED))
+ break;
+
+ schedule_timeout_uninterruptible(HZ);
+
+ } while ((time_after(wtime, jiffies)));
+
+ if (!time_after(wtime, jiffies)) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Login response wait timer expired\n",
+ __func__));
+ goto exit_login_resp;
+ }
+ }
+ }
+
+exit_login_resp:
+ if (fw_ddb_entry)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+}
+
+/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
* @pci_device_id: pointer to pci_device entry
@@ -5124,8 +6864,8 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
* It returns zero if successful. It also initializes all data necessary for
* the driver.
**/
-static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int qla4xxx_probe_adapter(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int ret = -ENODEV, status;
struct Scsi_Host *host;
@@ -5261,8 +7001,11 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
/* Dont retry adapter initialization if IRQ allocation failed */
- if (!test_bit(AF_IRQ_ATTACHED, &ha->flags))
+ if (is_qla80XX(ha) && !test_bit(AF_IRQ_ATTACHED, &ha->flags)) {
+ ql4_printk(KERN_WARNING, ha, "%s: Skipping retry of adapter initialization\n",
+ __func__);
goto skip_retry_init;
+ }
while ((!test_bit(AF_ONLINE, &ha->flags)) &&
init_retry_count++ < MAX_INIT_RETRIES) {
@@ -5270,7 +7013,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (is_qla80XX(ha)) {
ha->isp_ops->idc_lock(ha);
dev_state = qla4_8xxx_rd_direct(ha,
- QLA82XX_CRB_DEV_STATE);
+ QLA8XXX_CRB_DEV_STATE);
ha->isp_ops->idc_unlock(ha);
if (dev_state == QLA8XXX_DEV_FAILED) {
ql4_printk(KERN_WARNING, ha, "%s: don't retry "
@@ -5317,8 +7060,8 @@ skip_retry_init:
}
INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
- sprintf(buf, "qla4xxx_%lu_task", ha->host_no);
- ha->task_wq = alloc_workqueue(buf, WQ_MEM_RECLAIM, 1);
+ ha->task_wq = alloc_workqueue("qla4xxx_%lu_task", WQ_MEM_RECLAIM, 1,
+ ha->host_no);
if (!ha->task_wq) {
ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n");
ret = -ENODEV;
@@ -5365,9 +7108,14 @@ skip_retry_init:
ql4_printk(KERN_ERR, ha,
"%s: No iSCSI boot target configured\n", __func__);
+ if (qla4xxx_sysfs_ddb_export(ha))
+ ql4_printk(KERN_ERR, ha,
+ "%s: Error exporting ddb to sysfs\n", __func__);
+
/* Perform the build ddb list and login to each */
qla4xxx_build_ddb_list(ha, INIT_ADAPTER);
iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb);
+ qla4xxx_wait_login_resp_boot_tgt(ha);
qla4xxx_create_chap_list(ha);
@@ -5464,7 +7212,7 @@ static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha)
* qla4xxx_remove_adapter - callback function to remove adapter.
* @pci_dev: PCI device pointer
**/
-static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
+static void qla4xxx_remove_adapter(struct pci_dev *pdev)
{
struct scsi_qla_host *ha;
@@ -5489,6 +7237,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
qla4xxx_destroy_fw_ddb_session(ha);
qla4_8xxx_free_sysfs_attr(ha);
+ qla4xxx_sysfs_ddb_remove(ha);
scsi_remove_host(ha->host);
qla4xxx_free_adapter(ha);
@@ -5588,7 +7337,6 @@ struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
/* update counters */
if (srb->flags & SRB_DMA_VALID) {
- ha->req_q_count += srb->iocb_cnt;
ha->iocb_cnt -= srb->iocb_cnt;
if (srb->cmd)
srb->cmd->host_scribble =
@@ -6000,6 +7748,7 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
{
struct scsi_qla_host *ha = to_qla_host(shost);
int rval = QLA_SUCCESS;
+ uint32_t idc_ctrl;
if (ql4xdontresethba) {
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n",
@@ -6008,14 +7757,6 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
goto exit_host_reset;
}
- rval = qla4xxx_wait_for_hba_online(ha);
- if (rval != QLA_SUCCESS) {
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unable to reset host "
- "adapter\n", __func__));
- rval = -EIO;
- goto exit_host_reset;
- }
-
if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
goto recover_adapter;
@@ -6038,6 +7779,14 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
}
recover_adapter:
+ /* For ISP83XX set graceful reset bit in IDC_DRV_CTRL if
+ * reset is issued by application */
+ if (is_qla8032(ha) && test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
+ idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);
+ qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL,
+ (idc_ctrl | GRACEFUL_RESET_BIT1));
+ }
+
rval = qla4xxx_recover_adapter(ha);
if (rval != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n",
@@ -6115,7 +7864,6 @@ qla4xxx_pci_mmio_enabled(struct pci_dev *pdev)
static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
{
uint32_t rval = QLA_ERROR;
- uint32_t ret = 0;
int fn;
struct pci_dev *other_pdev = NULL;
@@ -6201,16 +7949,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, 0);
qla4_8xxx_set_drv_active(ha);
ha->isp_ops->idc_unlock(ha);
- ret = qla4xxx_request_irqs(ha);
- if (ret) {
- ql4_printk(KERN_WARNING, ha, "Failed to "
- "reserve interrupt %d already in use.\n",
- ha->pdev->irq);
- rval = QLA_ERROR;
- } else {
- ha->isp_ops->enable_intrs(ha);
- rval = QLA_SUCCESS;
- }
+ ha->isp_ops->enable_intrs(ha);
}
} else {
ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not "
@@ -6220,18 +7959,9 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
QLA8XXX_DEV_READY)) {
clear_bit(AF_FW_RECOVERY, &ha->flags);
rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
- if (rval == QLA_SUCCESS) {
- ret = qla4xxx_request_irqs(ha);
- if (ret) {
- ql4_printk(KERN_WARNING, ha, "Failed to"
- " reserve interrupt %d already in"
- " use.\n", ha->pdev->irq);
- rval = QLA_ERROR;
- } else {
- ha->isp_ops->enable_intrs(ha);
- rval = QLA_SUCCESS;
- }
- }
+ if (rval == QLA_SUCCESS)
+ ha->isp_ops->enable_intrs(ha);
+
ha->isp_ops->idc_lock(ha);
qla4_8xxx_set_drv_active(ha);
ha->isp_ops->idc_unlock(ha);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index f6df2ea..fe873cf 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.03.00-k1"
+#define QLA4XXX_DRIVER_VERSION "5.03.00-k9"
diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
index 1e874f1..13d628b 100644
--- a/drivers/scsi/qlogicfas.c
+++ b/drivers/scsi/qlogicfas.c
@@ -142,7 +142,7 @@ module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(iobase, "I/O address");
MODULE_PARM_DESC(irq, "IRQ");
-static int __devinit qlogicfas_detect(struct scsi_host_template *sht)
+static int qlogicfas_detect(struct scsi_host_template *sht)
{
struct Scsi_Host *shost;
struct qlogicfas408_priv *priv;
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 71fddbc..6d48d30 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -461,7 +461,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
#define PTI_RESET_LIMIT 400
-static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
+static int qlogicpti_load_firmware(struct qlogicpti *qpti)
{
const struct firmware *fw;
const char fwname[] = "qlogic/isp1000.bin";
@@ -670,7 +670,7 @@ static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
static irqreturn_t qpti_intr(int irq, void *dev_id);
-static void __devinit qpti_chain_add(struct qlogicpti *qpti)
+static void qpti_chain_add(struct qlogicpti *qpti)
{
spin_lock_irq(&qptichain_lock);
if (qptichain != NULL) {
@@ -686,7 +686,7 @@ static void __devinit qpti_chain_add(struct qlogicpti *qpti)
spin_unlock_irq(&qptichain_lock);
}
-static void __devexit qpti_chain_del(struct qlogicpti *qpti)
+static void qpti_chain_del(struct qlogicpti *qpti)
{
spin_lock_irq(&qptichain_lock);
if (qptichain == qpti) {
@@ -701,7 +701,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti)
spin_unlock_irq(&qptichain_lock);
}
-static int __devinit qpti_map_regs(struct qlogicpti *qpti)
+static int qpti_map_regs(struct qlogicpti *qpti)
{
struct platform_device *op = qpti->op;
@@ -724,7 +724,7 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti)
return 0;
}
-static int __devinit qpti_register_irq(struct qlogicpti *qpti)
+static int qpti_register_irq(struct qlogicpti *qpti)
{
struct platform_device *op = qpti->op;
@@ -749,7 +749,7 @@ fail:
return -1;
}
-static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti)
+static void qpti_get_scsi_id(struct qlogicpti *qpti)
{
struct platform_device *op = qpti->op;
struct device_node *dp;
@@ -803,7 +803,7 @@ static void qpti_get_clock(struct qlogicpti *qpti)
/* The request and response queues must each be aligned
* on a page boundary.
*/
-static int __devinit qpti_map_queues(struct qlogicpti *qpti)
+static int qpti_map_queues(struct qlogicpti *qpti)
{
struct platform_device *op = qpti->op;
@@ -1292,7 +1292,7 @@ static struct scsi_host_template qpti_template = {
};
static const struct of_device_id qpti_match[];
-static int __devinit qpti_sbus_probe(struct platform_device *op)
+static int qpti_sbus_probe(struct platform_device *op)
{
struct device_node *dp = op->dev.of_node;
struct Scsi_Host *host;
@@ -1402,7 +1402,7 @@ fail_unlink:
return -ENODEV;
}
-static int __devexit qpti_sbus_remove(struct platform_device *op)
+static int qpti_sbus_remove(struct platform_device *op)
{
struct qlogicpti *qpti = dev_get_drvdata(&op->dev);
@@ -1459,7 +1459,7 @@ static struct platform_driver qpti_sbus_driver = {
.of_match_table = qpti_match,
},
.probe = qpti_sbus_probe,
- .remove = __devexit_p(qpti_sbus_remove),
+ .remove = qpti_sbus_remove,
};
static int __init qpti_init(void)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2c0d0ec..3b1ea34 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1070,8 +1070,8 @@ EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
* @opcode: opcode for command to look up
*
* Uses the REPORT SUPPORTED OPERATION CODES to look up the given
- * opcode. Returns 0 if RSOC fails or if the command opcode is
- * unsupported. Returns 1 if the device claims to support the command.
+ * opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is
+ * unsupported and 1 if the device claims to support the command.
*/
int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
unsigned int len, unsigned char opcode)
@@ -1081,7 +1081,7 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
int result;
if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
- return 0;
+ return -EINVAL;
memset(cmd, 0, 16);
cmd[0] = MAINTENANCE_IN;
@@ -1097,7 +1097,7 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
if (result && scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST &&
(sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
- return 0;
+ return -EINVAL;
if ((buffer[1] & 3) == 3) /* Command supported */
return 1;
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5cda11c..cb4fefa 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -258,7 +258,7 @@ struct sdebug_queued_cmd {
static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
static unsigned char * fake_storep; /* ramdisk storage */
-static unsigned char *dif_storep; /* protection info */
+static struct sd_dif_tuple *dif_storep; /* protection info */
static void *map_storep; /* provisioning map */
static unsigned long map_size;
@@ -277,11 +277,6 @@ static char sdebug_proc_name[] = "scsi_debug";
static struct bus_type pseudo_lld_bus;
-static inline sector_t dif_offset(sector_t sector)
-{
- return sector << 3;
-}
-
static struct device_driver sdebug_driverfs_driver = {
.name = sdebug_proc_name,
.bus = &pseudo_lld_bus,
@@ -439,10 +434,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
arr, arr_len);
- if (sdb->resid)
- sdb->resid -= act_len;
- else
- sdb->resid = scsi_bufflen(scp) - act_len;
+ sdb->resid = scsi_bufflen(scp) - act_len;
return 0;
}
@@ -1693,28 +1685,96 @@ static int check_device_access_params(struct sdebug_dev_info *devi,
return 0;
}
+/* Returns number of bytes copied or -1 if error. */
static int do_device_access(struct scsi_cmnd *scmd,
struct sdebug_dev_info *devi,
unsigned long long lba, unsigned int num, int write)
{
int ret;
unsigned long long block, rest = 0;
- int (*func)(struct scsi_cmnd *, unsigned char *, int);
+ struct scsi_data_buffer *sdb;
+ enum dma_data_direction dir;
+ size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
+ off_t);
+
+ if (write) {
+ sdb = scsi_out(scmd);
+ dir = DMA_TO_DEVICE;
+ func = sg_pcopy_to_buffer;
+ } else {
+ sdb = scsi_in(scmd);
+ dir = DMA_FROM_DEVICE;
+ func = sg_pcopy_from_buffer;
+ }
- func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
+ if (!sdb->length)
+ return 0;
+ if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
+ return -1;
block = do_div(lba, sdebug_store_sectors);
if (block + num > sdebug_store_sectors)
rest = block + num - sdebug_store_sectors;
- ret = func(scmd, fake_storep + (block * scsi_debug_sector_size),
- (num - rest) * scsi_debug_sector_size);
- if (!ret && rest)
- ret = func(scmd, fake_storep, rest * scsi_debug_sector_size);
+ ret = func(sdb->table.sgl, sdb->table.nents,
+ fake_storep + (block * scsi_debug_sector_size),
+ (num - rest) * scsi_debug_sector_size, 0);
+ if (ret != (num - rest) * scsi_debug_sector_size)
+ return ret;
+
+ if (rest) {
+ ret += func(sdb->table.sgl, sdb->table.nents,
+ fake_storep, rest * scsi_debug_sector_size,
+ (num - rest) * scsi_debug_sector_size);
+ }
return ret;
}
+static u16 dif_compute_csum(const void *buf, int len)
+{
+ u16 csum;
+
+ switch (scsi_debug_guard) {
+ case 1:
+ csum = ip_compute_csum(buf, len);
+ break;
+ case 0:
+ csum = cpu_to_be16(crc_t10dif(buf, len));
+ break;
+ }
+ return csum;
+}
+
+static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
+ sector_t sector, u32 ei_lba)
+{
+ u16 csum = dif_compute_csum(data, scsi_debug_sector_size);
+
+ if (sdt->guard_tag != csum) {
+ pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
+ __func__,
+ (unsigned long)sector,
+ be16_to_cpu(sdt->guard_tag),
+ be16_to_cpu(csum));
+ return 0x01;
+ }
+ if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
+ be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
+ pr_err("%s: REF check failed on sector %lu\n",
+ __func__, (unsigned long)sector);
+ return 0x03;
+ }
+ if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+ be32_to_cpu(sdt->ref_tag) != ei_lba) {
+ pr_err("%s: REF check failed on sector %lu\n",
+ __func__, (unsigned long)sector);
+ dif_errors++;
+ return 0x03;
+ }
+ return 0;
+}
+
static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
unsigned int sectors, u32 ei_lba)
{
@@ -1727,71 +1787,38 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
start_sec = do_div(tmp_sec, sdebug_store_sectors);
- sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec));
+ sdt = dif_storep + start_sec;
for (i = 0 ; i < sectors ; i++) {
- u16 csum;
+ int ret;
if (sdt[i].app_tag == 0xffff)
continue;
sector = start_sec + i;
- switch (scsi_debug_guard) {
- case 1:
- csum = ip_compute_csum(fake_storep +
- sector * scsi_debug_sector_size,
- scsi_debug_sector_size);
- break;
- case 0:
- csum = crc_t10dif(fake_storep +
- sector * scsi_debug_sector_size,
- scsi_debug_sector_size);
- csum = cpu_to_be16(csum);
- break;
- default:
- BUG();
- }
-
- if (sdt[i].guard_tag != csum) {
- printk(KERN_ERR "%s: GUARD check failed on sector %lu" \
- " rcvd 0x%04x, data 0x%04x\n", __func__,
- (unsigned long)sector,
- be16_to_cpu(sdt[i].guard_tag),
- be16_to_cpu(csum));
- dif_errors++;
- return 0x01;
- }
-
- if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
- be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) {
- printk(KERN_ERR "%s: REF check failed on sector %lu\n",
- __func__, (unsigned long)sector);
+ ret = dif_verify(&sdt[i],
+ fake_storep + sector * scsi_debug_sector_size,
+ sector, ei_lba);
+ if (ret) {
dif_errors++;
- return 0x03;
- }
-
- if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
- be32_to_cpu(sdt[i].ref_tag) != ei_lba) {
- printk(KERN_ERR "%s: REF check failed on sector %lu\n",
- __func__, (unsigned long)sector);
- dif_errors++;
- return 0x03;
+ return ret;
}
ei_lba++;
}
- resid = sectors * 8; /* Bytes of protection data to copy into sgl */
+ /* Bytes of protection data to copy into sgl */
+ resid = sectors * sizeof(*dif_storep);
sector = start_sec;
scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) {
int len = min(psgl->length, resid);
paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
- memcpy(paddr, dif_storep + dif_offset(sector), len);
+ memcpy(paddr, dif_storep + sector, len);
- sector += len >> 3;
+ sector += len / sizeof(*dif_storep);
if (sector >= sdebug_store_sectors) {
/* Force wrap */
tmp_sec = sector;
@@ -1849,7 +1876,12 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
read_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 0);
read_unlock_irqrestore(&atomic_rw, iflags);
- return ret;
+ if (ret == -1)
+ return DID_ERROR << 16;
+
+ scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret;
+
+ return 0;
}
void dump_sector(unsigned char *buf, int len)
@@ -1884,22 +1916,21 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
sector_t tmp_sec = start_sec;
sector_t sector;
int ppage_offset;
- unsigned short csum;
sector = do_div(tmp_sec, sdebug_store_sectors);
BUG_ON(scsi_sg_count(SCpnt) == 0);
BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
- paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
ppage_offset = 0;
/* For each data page */
scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) {
daddr = kmap_atomic(sg_page(dsgl)) + dsgl->offset;
+ paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
/* For each sector-sized chunk in data page */
- for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) {
+ for (j = 0; j < dsgl->length; j += scsi_debug_sector_size) {
/* If we're at the end of the current
* protection page advance to the next one
@@ -1915,51 +1946,9 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
sdt = paddr + ppage_offset;
- switch (scsi_debug_guard) {
- case 1:
- csum = ip_compute_csum(daddr,
- scsi_debug_sector_size);
- break;
- case 0:
- csum = cpu_to_be16(crc_t10dif(daddr,
- scsi_debug_sector_size));
- break;
- default:
- BUG();
- ret = 0;
- goto out;
- }
-
- if (sdt->guard_tag != csum) {
- printk(KERN_ERR
- "%s: GUARD check failed on sector %lu " \
- "rcvd 0x%04x, calculated 0x%04x\n",
- __func__, (unsigned long)sector,
- be16_to_cpu(sdt->guard_tag),
- be16_to_cpu(csum));
- ret = 0x01;
- dump_sector(daddr, scsi_debug_sector_size);
- goto out;
- }
-
- if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
- be32_to_cpu(sdt->ref_tag)
- != (start_sec & 0xffffffff)) {
- printk(KERN_ERR
- "%s: REF check failed on sector %lu\n",
- __func__, (unsigned long)sector);
- ret = 0x03;
- dump_sector(daddr, scsi_debug_sector_size);
- goto out;
- }
-
- if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
- be32_to_cpu(sdt->ref_tag) != ei_lba) {
- printk(KERN_ERR
- "%s: REF check failed on sector %lu\n",
- __func__, (unsigned long)sector);
- ret = 0x03;
- dump_sector(daddr, scsi_debug_sector_size);
+ ret = dif_verify(sdt, daddr + j, start_sec, ei_lba);
+ if (ret) {
+ dump_sector(daddr + j, scsi_debug_sector_size);
goto out;
}
@@ -1968,7 +1957,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
* correctness we need to verify each sector
* before writing it to "stable" storage
*/
- memcpy(dif_storep + dif_offset(sector), sdt, 8);
+ memcpy(dif_storep + sector, sdt, sizeof(*sdt));
sector++;
@@ -1977,44 +1966,57 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
start_sec++;
ei_lba++;
- daddr += scsi_debug_sector_size;
ppage_offset += sizeof(struct sd_dif_tuple);
}
+ kunmap_atomic(paddr);
kunmap_atomic(daddr);
}
- kunmap_atomic(paddr);
-
dix_writes++;
return 0;
out:
dif_errors++;
- kunmap_atomic(daddr);
kunmap_atomic(paddr);
+ kunmap_atomic(daddr);
return ret;
}
-static unsigned int map_state(sector_t lba, unsigned int *num)
+static unsigned long lba_to_map_index(sector_t lba)
+{
+ if (scsi_debug_unmap_alignment) {
+ lba += scsi_debug_unmap_granularity -
+ scsi_debug_unmap_alignment;
+ }
+ do_div(lba, scsi_debug_unmap_granularity);
+
+ return lba;
+}
+
+static sector_t map_index_to_lba(unsigned long index)
{
- unsigned int granularity, alignment, mapped;
- sector_t block, next, end;
+ return index * scsi_debug_unmap_granularity -
+ scsi_debug_unmap_alignment;
+}
- granularity = scsi_debug_unmap_granularity;
- alignment = granularity - scsi_debug_unmap_alignment;
- block = lba + alignment;
- do_div(block, granularity);
+static unsigned int map_state(sector_t lba, unsigned int *num)
+{
+ sector_t end;
+ unsigned int mapped;
+ unsigned long index;
+ unsigned long next;
- mapped = test_bit(block, map_storep);
+ index = lba_to_map_index(lba);
+ mapped = test_bit(index, map_storep);
if (mapped)
- next = find_next_zero_bit(map_storep, map_size, block);
+ next = find_next_zero_bit(map_storep, map_size, index);
else
- next = find_next_bit(map_storep, map_size, block);
+ next = find_next_bit(map_storep, map_size, index);
- end = next * granularity - scsi_debug_unmap_alignment;
+ end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
*num = end - lba;
return mapped;
@@ -2022,47 +2024,42 @@ static unsigned int map_state(sector_t lba, unsigned int *num)
static void map_region(sector_t lba, unsigned int len)
{
- unsigned int granularity, alignment;
sector_t end = lba + len;
- granularity = scsi_debug_unmap_granularity;
- alignment = granularity - scsi_debug_unmap_alignment;
-
while (lba < end) {
- sector_t block, rem;
-
- block = lba + alignment;
- rem = do_div(block, granularity);
+ unsigned long index = lba_to_map_index(lba);
- if (block < map_size)
- set_bit(block, map_storep);
+ if (index < map_size)
+ set_bit(index, map_storep);
- lba += granularity - rem;
+ lba = map_index_to_lba(index + 1);
}
}
static void unmap_region(sector_t lba, unsigned int len)
{
- unsigned int granularity, alignment;
sector_t end = lba + len;
- granularity = scsi_debug_unmap_granularity;
- alignment = granularity - scsi_debug_unmap_alignment;
-
while (lba < end) {
- sector_t block, rem;
-
- block = lba + alignment;
- rem = do_div(block, granularity);
+ unsigned long index = lba_to_map_index(lba);
- if (rem == 0 && lba + granularity < end && block < map_size) {
- clear_bit(block, map_storep);
- if (scsi_debug_lbprz)
+ if (lba == map_index_to_lba(index) &&
+ lba + scsi_debug_unmap_granularity <= end &&
+ index < map_size) {
+ clear_bit(index, map_storep);
+ if (scsi_debug_lbprz) {
memset(fake_storep +
- block * scsi_debug_sector_size, 0,
- scsi_debug_sector_size);
+ lba * scsi_debug_sector_size, 0,
+ scsi_debug_sector_size *
+ scsi_debug_unmap_granularity);
+ }
+ if (dif_storep) {
+ memset(dif_storep + lba, 0xff,
+ sizeof(*dif_storep) *
+ scsi_debug_unmap_granularity);
+ }
}
- lba += granularity - rem;
+ lba = map_index_to_lba(index + 1);
}
}
@@ -2089,7 +2086,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
write_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 1);
- if (scsi_debug_unmap_granularity)
+ if (scsi_debug_lbp())
map_region(lba, num);
write_unlock_irqrestore(&atomic_rw, iflags);
if (-1 == ret)
@@ -2122,7 +2119,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
write_lock_irqsave(&atomic_rw, iflags);
- if (unmap && scsi_debug_unmap_granularity) {
+ if (unmap && scsi_debug_lbp()) {
unmap_region(lba, num);
goto out;
}
@@ -2146,7 +2143,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
fake_storep + (lba * scsi_debug_sector_size),
scsi_debug_sector_size);
- if (scsi_debug_unmap_granularity)
+ if (scsi_debug_lbp())
map_region(lba, num);
out:
write_unlock_irqrestore(&atomic_rw, iflags);
@@ -2823,31 +2820,27 @@ static const char * scsi_debug_info(struct Scsi_Host * shp)
/* scsi_debug_proc_info
* Used if the driver currently has no own support for /proc/scsi
*/
-static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
{
- int len, pos, begin;
- int orig_length;
-
- orig_length = length;
+ char arr[16];
+ int opts;
+ int minLen = length > 15 ? 15 : length;
- if (inout == 1) {
- char arr[16];
- int minLen = length > 15 ? 15 : length;
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ memcpy(arr, buffer, minLen);
+ arr[minLen] = '\0';
+ if (1 != sscanf(arr, "%d", &opts))
+ return -EINVAL;
+ scsi_debug_opts = opts;
+ if (scsi_debug_every_nth != 0)
+ scsi_debug_cmnd_count = 0;
+ return length;
+}
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- memcpy(arr, buffer, minLen);
- arr[minLen] = '\0';
- if (1 != sscanf(arr, "%d", &pos))
- return -EINVAL;
- scsi_debug_opts = pos;
- if (scsi_debug_every_nth != 0)
- scsi_debug_cmnd_count = 0;
- return length;
- }
- begin = 0;
- pos = len = sprintf(buffer, "scsi_debug adapter driver, version "
+static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
+{
+ seq_printf(m, "scsi_debug adapter driver, version "
"%s [%s]\n"
"num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
"every_nth=%d(curr:%d)\n"
@@ -2862,15 +2855,7 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta
scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
num_host_resets, dix_reads, dix_writes, dif_errors);
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- *start = buffer + (offset - begin); /* Start of wanted data */
- len -= (offset - begin);
- if (len > length)
- len = length;
- return len;
+ return 0;
}
static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf)
@@ -3381,7 +3366,7 @@ static int __init scsi_debug_init(void)
if (scsi_debug_num_parts > 0)
sdebug_build_parts(fake_storep, sz);
- if (scsi_debug_dif) {
+ if (scsi_debug_dix) {
int dif_size;
dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
@@ -3401,8 +3386,6 @@ static int __init scsi_debug_init(void)
/* Logical Block Provisioning */
if (scsi_debug_lbp()) {
- unsigned int map_bytes;
-
scsi_debug_unmap_max_blocks =
clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
@@ -3413,16 +3396,16 @@ static int __init scsi_debug_init(void)
clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
if (scsi_debug_unmap_alignment &&
- scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
+ scsi_debug_unmap_granularity <=
+ scsi_debug_unmap_alignment) {
printk(KERN_ERR
- "%s: ERR: unmap_granularity < unmap_alignment\n",
+ "%s: ERR: unmap_granularity <= unmap_alignment\n",
__func__);
return -EINVAL;
}
- map_size = (sdebug_store_sectors / scsi_debug_unmap_granularity);
- map_bytes = map_size >> 3;
- map_storep = vmalloc(map_bytes);
+ map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
+ map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
map_size);
@@ -3433,7 +3416,7 @@ static int __init scsi_debug_init(void)
goto free_vm;
}
- memset(map_storep, 0x0, map_bytes);
+ bitmap_zero(map_storep, map_size);
/* Map first 1KB for partition table */
if (scsi_debug_num_parts)
@@ -3957,7 +3940,8 @@ write:
static DEF_SCSI_QCMD(scsi_debug_queuecommand)
static struct scsi_host_template sdebug_driver_template = {
- .proc_info = scsi_debug_proc_info,
+ .show_info = scsi_debug_show_info,
+ .write_info = scsi_debug_write_info,
.proc_name = sdebug_proc_name,
.name = "SCSI DEBUG",
.info = scsi_debug_info,
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 43fca91..f969aca 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -228,6 +228,7 @@ static struct {
{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
{"SEAGATE", "ST34555N", "0930", BLIST_NOTQ}, /* Chokes on tagged INQUIRY */
{"SEAGATE", "ST3390N", "9546", BLIST_NOTQ},
+ {"SEAGATE", "ST900MM0006", NULL, BLIST_SKIP_VPD_PAGES},
{"SGI", "RAID3", "*", BLIST_SPARSELUN},
{"SGI", "RAID5", "*", BLIST_SPARSELUN},
{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c1b05a8..2150596 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -44,8 +45,6 @@
static void scsi_eh_done(struct scsi_cmnd *scmd);
-#define SENSE_TIMEOUT (10*HZ)
-
/*
* These should *probably* be handled by the host itself.
* Since it is allowed to sleep, it probably should.
@@ -537,7 +536,7 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
/**
* scsi_try_host_reset - ask host adapter to reset itself
- * @scmd: SCSI cmd to send hsot reset.
+ * @scmd: SCSI cmd to send host reset.
*/
static int scsi_try_host_reset(struct scsi_cmnd *scmd)
{
@@ -791,32 +790,48 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
struct scsi_device *sdev = scmd->device;
struct Scsi_Host *shost = sdev->host;
DECLARE_COMPLETION_ONSTACK(done);
- unsigned long timeleft;
+ unsigned long timeleft = timeout;
struct scsi_eh_save ses;
+ const unsigned long stall_for = msecs_to_jiffies(100);
int rtn;
+retry:
scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes);
shost->eh_action = &done;
scsi_log_send(scmd);
scmd->scsi_done = scsi_eh_done;
- shost->hostt->queuecommand(shost, scmd);
-
- timeleft = wait_for_completion_timeout(&done, timeout);
+ rtn = shost->hostt->queuecommand(shost, scmd);
+ if (rtn) {
+ if (timeleft > stall_for) {
+ scsi_eh_restore_cmnd(scmd, &ses);
+ timeleft -= stall_for;
+ msleep(jiffies_to_msecs(stall_for));
+ goto retry;
+ }
+ /* signal not to enter either branch of the if () below */
+ timeleft = 0;
+ rtn = NEEDS_RETRY;
+ } else {
+ timeleft = wait_for_completion_timeout(&done, timeout);
+ }
shost->eh_action = NULL;
- scsi_log_completion(scmd, SUCCESS);
+ scsi_log_completion(scmd, rtn);
SCSI_LOG_ERROR_RECOVERY(3,
printk("%s: scmd: %p, timeleft: %ld\n",
__func__, scmd, timeleft));
/*
- * If there is time left scsi_eh_done got called, and we will
- * examine the actual status codes to see whether the command
- * actually did complete normally, else tell the host to forget
- * about this command.
+ * If there is time left scsi_eh_done got called, and we will examine
+ * the actual status codes to see whether the command actually did
+ * complete normally, else if we have a zero return and no time left,
+ * the command must still be pending, so abort it and return FAILED.
+ * If we never actually managed to issue the command, because
+ * ->queuecommand() kept returning non zero, use the rtn = FAILED
+ * value above (so don't execute either branch of the if)
*/
if (timeleft) {
rtn = scsi_eh_completed_normally(scmd);
@@ -837,7 +852,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
rtn = FAILED;
break;
}
- } else {
+ } else if (!rtn) {
scsi_abort_eh_cmnd(scmd);
rtn = FAILED;
}
@@ -864,7 +879,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
*/
static int scsi_request_sense(struct scsi_cmnd *scmd)
{
- return scsi_send_eh_cmnd(scmd, NULL, 0, SENSE_TIMEOUT, ~0);
+ return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0);
}
/**
@@ -965,7 +980,8 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
int retry_cnt = 1, rtn;
retry_tur:
- rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0);
+ rtn = scsi_send_eh_cmnd(scmd, tur_command, 6,
+ scmd->device->eh_timeout, 0);
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
__func__, scmd, rtn));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f1bf5af..124392f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache;
#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
+static bool acpi_scsi_bus_match(struct device *dev)
+{
+ return dev->bus == &scsi_bus_type;
+}
+
int scsi_register_acpi_bus_type(struct acpi_bus_type *bus)
{
- bus->bus = &scsi_bus_type;
+ bus->match = acpi_scsi_bus_match;
return register_acpi_bus_type(bus);
}
EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type);
@@ -271,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
}
EXPORT_SYMBOL(scsi_execute);
-
-int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen,
struct scsi_sense_hdr *sshdr, int timeout, int retries,
- int *resid)
+ int *resid, int flags)
{
char *sense = NULL;
int result;
@@ -286,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
return DRIVER_ERROR << 24;
}
result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
- sense, timeout, retries, 0, resid);
+ sense, timeout, retries, flags, resid);
if (sshdr)
scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
kfree(sense);
return result;
}
-EXPORT_SYMBOL(scsi_execute_req);
+EXPORT_SYMBOL(scsi_execute_req_flags);
/*
* Function: scsi_init_cmd_errh()
@@ -430,6 +434,8 @@ static void scsi_run_queue(struct request_queue *q)
list_splice_init(&shost->starved_list, &starved_list);
while (!list_empty(&starved_list)) {
+ struct request_queue *slq;
+
/*
* As long as shost is accepting commands and we have
* starved queues, call blk_run_queue. scsi_request_fn
@@ -452,11 +458,25 @@ static void scsi_run_queue(struct request_queue *q)
continue;
}
- spin_unlock(shost->host_lock);
- spin_lock(sdev->request_queue->queue_lock);
- __blk_run_queue(sdev->request_queue);
- spin_unlock(sdev->request_queue->queue_lock);
- spin_lock(shost->host_lock);
+ /*
+ * Once we drop the host lock, a racing scsi_remove_device()
+ * call may remove the sdev from the starved list and destroy
+ * it and the queue. Mitigate by taking a reference to the
+ * queue and never touching the sdev again after we drop the
+ * host lock. Note: if __scsi_remove_device() invokes
+ * blk_cleanup_queue() before the queue is run from this
+ * function then blk_run_queue() will return immediately since
+ * blk_cleanup_queue() marks the queue with QUEUE_FLAG_DYING.
+ */
+ slq = sdev->request_queue;
+ if (!blk_get_queue(slq))
+ continue;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ blk_run_queue(slq);
+ blk_put_queue(slq);
+
+ spin_lock_irqsave(shost->host_lock, flags);
}
/* put any unprocessed entries back */
list_splice(&starved_list, &shost->starved_list);
@@ -2173,6 +2193,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
case SDEV_OFFLINE:
case SDEV_TRANSPORT_OFFLINE:
case SDEV_CANCEL:
+ case SDEV_CREATED_BLOCK:
break;
default:
goto illegal;
@@ -2617,3 +2638,17 @@ void scsi_kunmap_atomic_sg(void *virt)
kunmap_atomic(virt);
}
EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
+
+void sdev_disable_disk_events(struct scsi_device *sdev)
+{
+ atomic_inc(&sdev->disk_events_disable_depth);
+}
+EXPORT_SYMBOL(sdev_disable_disk_events);
+
+void sdev_enable_disk_events(struct scsi_device *sdev)
+{
+ if (WARN_ON_ONCE(atomic_read(&sdev->disk_events_disable_depth) <= 0))
+ return;
+ atomic_dec(&sdev->disk_events_disable_depth);
+}
+EXPORT_SYMBOL(sdev_enable_disk_events);
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index 65123a2..fe30ea9 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -50,7 +50,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
u32 rlen;
int err, tport;
- while (skb->len >= NLMSG_SPACE(0)) {
+ while (skb->len >= NLMSG_HDRLEN) {
err = 0;
nlh = nlmsg_hdr(skb);
@@ -70,7 +70,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
goto next_msg;
}
- hdr = NLMSG_DATA(nlh);
+ hdr = nlmsg_data(nlh);
if ((hdr->version != SCSI_NL_VERSION) ||
(hdr->magic != SCSI_NL_MAGIC)) {
err = -EPROTOTYPE;
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 8f6b12c..4c5aabe 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev)
#ifdef CONFIG_PM_RUNTIME
+static int sdev_blk_runtime_suspend(struct scsi_device *sdev,
+ int (*cb)(struct device *))
+{
+ int err;
+
+ err = blk_pre_runtime_suspend(sdev->request_queue);
+ if (err)
+ return err;
+ if (cb)
+ err = cb(&sdev->sdev_gendev);
+ blk_post_runtime_suspend(sdev->request_queue, err);
+
+ return err;
+}
+
+static int sdev_runtime_suspend(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
+ struct scsi_device *sdev = to_scsi_device(dev);
+ int err;
+
+ if (sdev->request_queue->dev)
+ return sdev_blk_runtime_suspend(sdev, cb);
+
+ err = scsi_dev_type_suspend(dev, cb);
+ if (err == -EAGAIN)
+ pm_schedule_suspend(dev, jiffies_to_msecs(
+ round_jiffies_up_relative(HZ/10)));
+ return err;
+}
+
static int scsi_runtime_suspend(struct device *dev)
{
int err = 0;
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
dev_dbg(dev, "scsi_runtime_suspend\n");
- if (scsi_is_sdev_device(dev)) {
- err = scsi_dev_type_suspend(dev,
- pm ? pm->runtime_suspend : NULL);
- if (err == -EAGAIN)
- pm_schedule_suspend(dev, jiffies_to_msecs(
- round_jiffies_up_relative(HZ/10)));
- }
+ if (scsi_is_sdev_device(dev))
+ err = sdev_runtime_suspend(dev);
/* Insert hooks here for targets, hosts, and transport classes */
return err;
}
-static int scsi_runtime_resume(struct device *dev)
+static int sdev_blk_runtime_resume(struct scsi_device *sdev,
+ int (*cb)(struct device *))
{
int err = 0;
+
+ blk_pre_runtime_resume(sdev->request_queue);
+ if (cb)
+ err = cb(&sdev->sdev_gendev);
+ blk_post_runtime_resume(sdev->request_queue, err);
+
+ return err;
+}
+
+static int sdev_runtime_resume(struct device *dev)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
+
+ if (sdev->request_queue->dev)
+ return sdev_blk_runtime_resume(sdev, cb);
+ else
+ return scsi_dev_type_resume(dev, cb);
+}
+
+static int scsi_runtime_resume(struct device *dev)
+{
+ int err = 0;
dev_dbg(dev, "scsi_runtime_resume\n");
if (scsi_is_sdev_device(dev))
- err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL);
+ err = sdev_runtime_resume(dev);
/* Insert hooks here for targets, hosts, and transport classes */
@@ -179,17 +229,20 @@ static int scsi_runtime_resume(struct device *dev)
static int scsi_runtime_idle(struct device *dev)
{
- int err;
-
dev_dbg(dev, "scsi_runtime_idle\n");
/* Insert hooks here for targets, hosts, and transport classes */
- if (scsi_is_sdev_device(dev))
- err = pm_schedule_suspend(dev, 100);
- else
- err = pm_runtime_suspend(dev);
- return err;
+ if (scsi_is_sdev_device(dev)) {
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (sdev->request_queue->dev) {
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_autosuspend(dev);
+ return -EBUSY;
+ }
+ }
+ return 0;
}
int scsi_autopm_get_device(struct scsi_device *sdev)
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index ad747dc..86f0c5d 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -45,58 +45,51 @@ static struct proc_dir_entry *proc_scsi;
/* Protect sht->present and sht->proc_dir */
static DEFINE_MUTEX(global_host_template_mutex);
-/**
- * proc_scsi_read - handle read from /proc by calling host's proc_info() command
- * @buffer: passed to proc_info
- * @start: passed to proc_info
- * @offset: passed to proc_info
- * @length: passed to proc_info
- * @eof: returns whether length read was less than requested
- * @data: pointer to a &struct Scsi_Host
- */
-
-static int proc_scsi_read(char *buffer, char **start, off_t offset,
- int length, int *eof, void *data)
-{
- struct Scsi_Host *shost = data;
- int n;
-
- n = shost->hostt->proc_info(shost, buffer, start, offset, length, 0);
- *eof = (n < length);
-
- return n;
-}
-
-/**
- * proc_scsi_write_proc - Handle write to /proc by calling host's proc_info()
- * @file: not used
- * @buf: source of data to write.
- * @count: number of bytes (at most PROC_BLOCK_SIZE) to write.
- * @data: pointer to &struct Scsi_Host
- */
-static int proc_scsi_write_proc(struct file *file, const char __user *buf,
- unsigned long count, void *data)
+static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- struct Scsi_Host *shost = data;
+ struct Scsi_Host *shost = PDE_DATA(file_inode(file));
ssize_t ret = -ENOMEM;
char *page;
- char *start;
if (count > PROC_BLOCK_SIZE)
return -EOVERFLOW;
+ if (!shost->hostt->write_info)
+ return -EINVAL;
+
page = (char *)__get_free_page(GFP_KERNEL);
if (page) {
ret = -EFAULT;
if (copy_from_user(page, buf, count))
goto out;
- ret = shost->hostt->proc_info(shost, page, &start, 0, count, 1);
+ ret = shost->hostt->write_info(shost, page, count);
}
out:
free_page((unsigned long)page);
return ret;
}
+static int proc_scsi_show(struct seq_file *m, void *v)
+{
+ struct Scsi_Host *shost = m->private;
+ return shost->hostt->show_info(m, shost);
+}
+
+static int proc_scsi_host_open(struct inode *inode, struct file *file)
+{
+ return single_open_size(file, proc_scsi_show, PDE_DATA(inode),
+ 4 * PAGE_SIZE);
+}
+
+static const struct file_operations proc_scsi_fops = {
+ .open = proc_scsi_host_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = proc_scsi_host_write
+};
+
/**
* scsi_proc_hostdir_add - Create directory in /proc for a scsi host
* @sht: owner of this directory
@@ -106,7 +99,7 @@ out:
void scsi_proc_hostdir_add(struct scsi_host_template *sht)
{
- if (!sht->proc_info)
+ if (!sht->show_info)
return;
mutex_lock(&global_host_template_mutex);
@@ -125,7 +118,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
*/
void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
{
- if (!sht->proc_info)
+ if (!sht->show_info)
return;
mutex_lock(&global_host_template_mutex);
@@ -151,16 +144,12 @@ void scsi_proc_host_add(struct Scsi_Host *shost)
return;
sprintf(name,"%d", shost->host_no);
- p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
- sht->proc_dir, proc_scsi_read, shost);
- if (!p) {
+ p = proc_create_data(name, S_IRUGO | S_IWUSR,
+ sht->proc_dir, &proc_scsi_fops, shost);
+ if (!p)
printk(KERN_ERR "%s: Failed to register host %d in"
"%s\n", __func__, shost->host_no,
sht->proc_name);
- return;
- }
-
- p->write_proc = proc_scsi_write_proc;
}
/**
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 3e58b22..307a811 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -924,6 +924,11 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
if (*bflags & BLIST_NO_DIF)
sdev->no_dif = 1;
+ sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT;
+
+ if (*bflags & BLIST_SKIP_VPD_PAGES)
+ sdev->skip_vpd_pages = 1;
+
transport_configure_device(&sdev->sdev_gendev);
if (sdev->host->hostt->slave_configure) {
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 931a7d9..7e50061 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -560,6 +560,35 @@ sdev_store_timeout (struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
static ssize_t
+sdev_show_eh_timeout(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev;
+ sdev = to_scsi_device(dev);
+ return snprintf(buf, 20, "%u\n", sdev->eh_timeout / HZ);
+}
+
+static ssize_t
+sdev_store_eh_timeout(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev;
+ unsigned int eh_timeout;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ sdev = to_scsi_device(dev);
+ err = kstrtouint(buf, 10, &eh_timeout);
+ if (err)
+ return err;
+ sdev->eh_timeout = eh_timeout * HZ;
+
+ return count;
+}
+static DEVICE_ATTR(eh_timeout, S_IRUGO | S_IWUSR, sdev_show_eh_timeout, sdev_store_eh_timeout);
+
+static ssize_t
store_rescan_field (struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -723,6 +752,7 @@ static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_delete.attr,
&dev_attr_state.attr,
&dev_attr_timeout.attr,
+ &dev_attr_eh_timeout.attr,
&dev_attr_iocounterbits.attr,
&dev_attr_iorequest_cnt.attr,
&dev_attr_iodone_cnt.attr,
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index e894ca7..4628fd5 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -35,7 +35,6 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_cmnd.h>
-#include <linux/netlink.h>
#include <net/netlink.h>
#include <scsi/scsi_netlink_fc.h>
#include <scsi/scsi_bsg_fc.h>
@@ -436,7 +435,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name),
"fc_wq_%d", shost->host_no);
- fc_host->work_q = alloc_workqueue(fc_host->work_q_name, 0, 0);
+ fc_host->work_q = alloc_workqueue("%s", 0, 0, fc_host->work_q_name);
if (!fc_host->work_q)
return -ENOMEM;
@@ -444,8 +443,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
snprintf(fc_host->devloss_work_q_name,
sizeof(fc_host->devloss_work_q_name),
"fc_dl_%d", shost->host_no);
- fc_host->devloss_work_q =
- alloc_workqueue(fc_host->devloss_work_q_name, 0, 0);
+ fc_host->devloss_work_q = alloc_workqueue("%s", 0, 0,
+ fc_host->devloss_work_q_name);
if (!fc_host->devloss_work_q) {
destroy_workqueue(fc_host->work_q);
fc_host->work_q = NULL;
@@ -534,7 +533,7 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
struct nlmsghdr *nlh;
struct fc_nl_event *event;
const char *name;
- u32 len, skblen;
+ u32 len;
int err;
if (!scsi_nl_sock) {
@@ -543,21 +542,19 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
}
len = FC_NL_MSGALIGN(sizeof(*event));
- skblen = NLMSG_SPACE(len);
- skb = alloc_skb(skblen, GFP_KERNEL);
+ skb = nlmsg_new(len, GFP_KERNEL);
if (!skb) {
err = -ENOBUFS;
goto send_fail;
}
- nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
- skblen - sizeof(*nlh), 0);
+ nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0);
if (!nlh) {
err = -ENOBUFS;
goto send_fail_skb;
}
- event = NLMSG_DATA(nlh);
+ event = nlmsg_data(nlh);
INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
FC_NL_ASYNC_EVENT, len);
@@ -604,7 +601,7 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
struct sk_buff *skb;
struct nlmsghdr *nlh;
struct fc_nl_event *event;
- u32 len, skblen;
+ u32 len;
int err;
if (!scsi_nl_sock) {
@@ -613,21 +610,19 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
}
len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
- skblen = NLMSG_SPACE(len);
- skb = alloc_skb(skblen, GFP_KERNEL);
+ skb = nlmsg_new(len, GFP_KERNEL);
if (!skb) {
err = -ENOBUFS;
goto send_vendor_fail;
}
- nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
- skblen - sizeof(*nlh), 0);
+ nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0);
if (!nlh) {
err = -ENOBUFS;
goto send_vendor_fail_skb;
}
- event = NLMSG_DATA(nlh);
+ event = nlmsg_data(nlh);
INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
FC_NL_ASYNC_EVENT, len);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 31969f2..abf7c40 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/bsg-lib.h>
#include <linux/idr.h>
+#include <linux/list.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
@@ -183,10 +184,10 @@ static struct attribute_group iscsi_endpoint_group = {
#define ISCSI_MAX_EPID -1
-static int iscsi_match_epid(struct device *dev, void *data)
+static int iscsi_match_epid(struct device *dev, const void *data)
{
struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
- uint64_t *epid = (uint64_t *) data;
+ const uint64_t *epid = data;
return *epid == ep->id;
}
@@ -460,6 +461,679 @@ void iscsi_destroy_iface(struct iscsi_iface *iface)
EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
/*
+ * Interface to display flash node params to sysfs
+ */
+
+#define ISCSI_FLASHNODE_ATTR(_prefix, _name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_prefix##_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+/* flash node session attrs show */
+#define iscsi_flashnode_sess_attr_show(type, name, param) \
+static ssize_t \
+show_##type##_##name(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct iscsi_bus_flash_session *fnode_sess = \
+ iscsi_dev_to_flash_session(dev);\
+ struct iscsi_transport *t = fnode_sess->transport; \
+ return t->get_flashnode_param(fnode_sess, param, buf); \
+} \
+
+
+#define iscsi_flashnode_sess_attr(type, name, param) \
+ iscsi_flashnode_sess_attr_show(type, name, param) \
+static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
+ show_##type##_##name, NULL);
+
+/* Flash node session attributes */
+
+iscsi_flashnode_sess_attr(fnode, auto_snd_tgt_disable,
+ ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE);
+iscsi_flashnode_sess_attr(fnode, discovery_session,
+ ISCSI_FLASHNODE_DISCOVERY_SESS);
+iscsi_flashnode_sess_attr(fnode, portal_type, ISCSI_FLASHNODE_PORTAL_TYPE);
+iscsi_flashnode_sess_attr(fnode, entry_enable, ISCSI_FLASHNODE_ENTRY_EN);
+iscsi_flashnode_sess_attr(fnode, immediate_data, ISCSI_FLASHNODE_IMM_DATA_EN);
+iscsi_flashnode_sess_attr(fnode, initial_r2t, ISCSI_FLASHNODE_INITIAL_R2T_EN);
+iscsi_flashnode_sess_attr(fnode, data_seq_in_order,
+ ISCSI_FLASHNODE_DATASEQ_INORDER);
+iscsi_flashnode_sess_attr(fnode, data_pdu_in_order,
+ ISCSI_FLASHNODE_PDU_INORDER);
+iscsi_flashnode_sess_attr(fnode, chap_auth, ISCSI_FLASHNODE_CHAP_AUTH_EN);
+iscsi_flashnode_sess_attr(fnode, discovery_logout,
+ ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN);
+iscsi_flashnode_sess_attr(fnode, bidi_chap, ISCSI_FLASHNODE_BIDI_CHAP_EN);
+iscsi_flashnode_sess_attr(fnode, discovery_auth_optional,
+ ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL);
+iscsi_flashnode_sess_attr(fnode, erl, ISCSI_FLASHNODE_ERL);
+iscsi_flashnode_sess_attr(fnode, first_burst_len, ISCSI_FLASHNODE_FIRST_BURST);
+iscsi_flashnode_sess_attr(fnode, def_time2wait, ISCSI_FLASHNODE_DEF_TIME2WAIT);
+iscsi_flashnode_sess_attr(fnode, def_time2retain,
+ ISCSI_FLASHNODE_DEF_TIME2RETAIN);
+iscsi_flashnode_sess_attr(fnode, max_outstanding_r2t, ISCSI_FLASHNODE_MAX_R2T);
+iscsi_flashnode_sess_attr(fnode, isid, ISCSI_FLASHNODE_ISID);
+iscsi_flashnode_sess_attr(fnode, tsid, ISCSI_FLASHNODE_TSID);
+iscsi_flashnode_sess_attr(fnode, max_burst_len, ISCSI_FLASHNODE_MAX_BURST);
+iscsi_flashnode_sess_attr(fnode, def_taskmgmt_tmo,
+ ISCSI_FLASHNODE_DEF_TASKMGMT_TMO);
+iscsi_flashnode_sess_attr(fnode, targetalias, ISCSI_FLASHNODE_ALIAS);
+iscsi_flashnode_sess_attr(fnode, targetname, ISCSI_FLASHNODE_NAME);
+iscsi_flashnode_sess_attr(fnode, tpgt, ISCSI_FLASHNODE_TPGT);
+iscsi_flashnode_sess_attr(fnode, discovery_parent_idx,
+ ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX);
+iscsi_flashnode_sess_attr(fnode, discovery_parent_type,
+ ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE);
+iscsi_flashnode_sess_attr(fnode, chap_in_idx, ISCSI_FLASHNODE_CHAP_IN_IDX);
+iscsi_flashnode_sess_attr(fnode, chap_out_idx, ISCSI_FLASHNODE_CHAP_OUT_IDX);
+iscsi_flashnode_sess_attr(fnode, username, ISCSI_FLASHNODE_USERNAME);
+iscsi_flashnode_sess_attr(fnode, username_in, ISCSI_FLASHNODE_USERNAME_IN);
+iscsi_flashnode_sess_attr(fnode, password, ISCSI_FLASHNODE_PASSWORD);
+iscsi_flashnode_sess_attr(fnode, password_in, ISCSI_FLASHNODE_PASSWORD_IN);
+iscsi_flashnode_sess_attr(fnode, is_boot_target, ISCSI_FLASHNODE_IS_BOOT_TGT);
+
+static struct attribute *iscsi_flashnode_sess_attrs[] = {
+ &dev_attr_fnode_auto_snd_tgt_disable.attr,
+ &dev_attr_fnode_discovery_session.attr,
+ &dev_attr_fnode_portal_type.attr,
+ &dev_attr_fnode_entry_enable.attr,
+ &dev_attr_fnode_immediate_data.attr,
+ &dev_attr_fnode_initial_r2t.attr,
+ &dev_attr_fnode_data_seq_in_order.attr,
+ &dev_attr_fnode_data_pdu_in_order.attr,
+ &dev_attr_fnode_chap_auth.attr,
+ &dev_attr_fnode_discovery_logout.attr,
+ &dev_attr_fnode_bidi_chap.attr,
+ &dev_attr_fnode_discovery_auth_optional.attr,
+ &dev_attr_fnode_erl.attr,
+ &dev_attr_fnode_first_burst_len.attr,
+ &dev_attr_fnode_def_time2wait.attr,
+ &dev_attr_fnode_def_time2retain.attr,
+ &dev_attr_fnode_max_outstanding_r2t.attr,
+ &dev_attr_fnode_isid.attr,
+ &dev_attr_fnode_tsid.attr,
+ &dev_attr_fnode_max_burst_len.attr,
+ &dev_attr_fnode_def_taskmgmt_tmo.attr,
+ &dev_attr_fnode_targetalias.attr,
+ &dev_attr_fnode_targetname.attr,
+ &dev_attr_fnode_tpgt.attr,
+ &dev_attr_fnode_discovery_parent_idx.attr,
+ &dev_attr_fnode_discovery_parent_type.attr,
+ &dev_attr_fnode_chap_in_idx.attr,
+ &dev_attr_fnode_chap_out_idx.attr,
+ &dev_attr_fnode_username.attr,
+ &dev_attr_fnode_username_in.attr,
+ &dev_attr_fnode_password.attr,
+ &dev_attr_fnode_password_in.attr,
+ &dev_attr_fnode_is_boot_target.attr,
+ NULL,
+};
+
+static umode_t iscsi_flashnode_sess_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int i)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct iscsi_bus_flash_session *fnode_sess =
+ iscsi_dev_to_flash_session(dev);
+ struct iscsi_transport *t = fnode_sess->transport;
+ int param;
+
+ if (attr == &dev_attr_fnode_auto_snd_tgt_disable.attr) {
+ param = ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE;
+ } else if (attr == &dev_attr_fnode_discovery_session.attr) {
+ param = ISCSI_FLASHNODE_DISCOVERY_SESS;
+ } else if (attr == &dev_attr_fnode_portal_type.attr) {
+ param = ISCSI_FLASHNODE_PORTAL_TYPE;
+ } else if (attr == &dev_attr_fnode_entry_enable.attr) {
+ param = ISCSI_FLASHNODE_ENTRY_EN;
+ } else if (attr == &dev_attr_fnode_immediate_data.attr) {
+ param = ISCSI_FLASHNODE_IMM_DATA_EN;
+ } else if (attr == &dev_attr_fnode_initial_r2t.attr) {
+ param = ISCSI_FLASHNODE_INITIAL_R2T_EN;
+ } else if (attr == &dev_attr_fnode_data_seq_in_order.attr) {
+ param = ISCSI_FLASHNODE_DATASEQ_INORDER;
+ } else if (attr == &dev_attr_fnode_data_pdu_in_order.attr) {
+ param = ISCSI_FLASHNODE_PDU_INORDER;
+ } else if (attr == &dev_attr_fnode_chap_auth.attr) {
+ param = ISCSI_FLASHNODE_CHAP_AUTH_EN;
+ } else if (attr == &dev_attr_fnode_discovery_logout.attr) {
+ param = ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN;
+ } else if (attr == &dev_attr_fnode_bidi_chap.attr) {
+ param = ISCSI_FLASHNODE_BIDI_CHAP_EN;
+ } else if (attr == &dev_attr_fnode_discovery_auth_optional.attr) {
+ param = ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL;
+ } else if (attr == &dev_attr_fnode_erl.attr) {
+ param = ISCSI_FLASHNODE_ERL;
+ } else if (attr == &dev_attr_fnode_first_burst_len.attr) {
+ param = ISCSI_FLASHNODE_FIRST_BURST;
+ } else if (attr == &dev_attr_fnode_def_time2wait.attr) {
+ param = ISCSI_FLASHNODE_DEF_TIME2WAIT;
+ } else if (attr == &dev_attr_fnode_def_time2retain.attr) {
+ param = ISCSI_FLASHNODE_DEF_TIME2RETAIN;
+ } else if (attr == &dev_attr_fnode_max_outstanding_r2t.attr) {
+ param = ISCSI_FLASHNODE_MAX_R2T;
+ } else if (attr == &dev_attr_fnode_isid.attr) {
+ param = ISCSI_FLASHNODE_ISID;
+ } else if (attr == &dev_attr_fnode_tsid.attr) {
+ param = ISCSI_FLASHNODE_TSID;
+ } else if (attr == &dev_attr_fnode_max_burst_len.attr) {
+ param = ISCSI_FLASHNODE_MAX_BURST;
+ } else if (attr == &dev_attr_fnode_def_taskmgmt_tmo.attr) {
+ param = ISCSI_FLASHNODE_DEF_TASKMGMT_TMO;
+ } else if (attr == &dev_attr_fnode_targetalias.attr) {
+ param = ISCSI_FLASHNODE_ALIAS;
+ } else if (attr == &dev_attr_fnode_targetname.attr) {
+ param = ISCSI_FLASHNODE_NAME;
+ } else if (attr == &dev_attr_fnode_tpgt.attr) {
+ param = ISCSI_FLASHNODE_TPGT;
+ } else if (attr == &dev_attr_fnode_discovery_parent_idx.attr) {
+ param = ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX;
+ } else if (attr == &dev_attr_fnode_discovery_parent_type.attr) {
+ param = ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE;
+ } else if (attr == &dev_attr_fnode_chap_in_idx.attr) {
+ param = ISCSI_FLASHNODE_CHAP_IN_IDX;
+ } else if (attr == &dev_attr_fnode_chap_out_idx.attr) {
+ param = ISCSI_FLASHNODE_CHAP_OUT_IDX;
+ } else if (attr == &dev_attr_fnode_username.attr) {
+ param = ISCSI_FLASHNODE_USERNAME;
+ } else if (attr == &dev_attr_fnode_username_in.attr) {
+ param = ISCSI_FLASHNODE_USERNAME_IN;
+ } else if (attr == &dev_attr_fnode_password.attr) {
+ param = ISCSI_FLASHNODE_PASSWORD;
+ } else if (attr == &dev_attr_fnode_password_in.attr) {
+ param = ISCSI_FLASHNODE_PASSWORD_IN;
+ } else if (attr == &dev_attr_fnode_is_boot_target.attr) {
+ param = ISCSI_FLASHNODE_IS_BOOT_TGT;
+ } else {
+ WARN_ONCE(1, "Invalid flashnode session attr");
+ return 0;
+ }
+
+ return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
+}
+
+static struct attribute_group iscsi_flashnode_sess_attr_group = {
+ .attrs = iscsi_flashnode_sess_attrs,
+ .is_visible = iscsi_flashnode_sess_attr_is_visible,
+};
+
+static const struct attribute_group *iscsi_flashnode_sess_attr_groups[] = {
+ &iscsi_flashnode_sess_attr_group,
+ NULL,
+};
+
+static void iscsi_flashnode_sess_release(struct device *dev)
+{
+ struct iscsi_bus_flash_session *fnode_sess =
+ iscsi_dev_to_flash_session(dev);
+
+ kfree(fnode_sess->targetname);
+ kfree(fnode_sess->targetalias);
+ kfree(fnode_sess->portal_type);
+ kfree(fnode_sess);
+}
+
+struct device_type iscsi_flashnode_sess_dev_type = {
+ .name = "iscsi_flashnode_sess_dev_type",
+ .groups = iscsi_flashnode_sess_attr_groups,
+ .release = iscsi_flashnode_sess_release,
+};
+
+/* flash node connection attrs show */
+#define iscsi_flashnode_conn_attr_show(type, name, param) \
+static ssize_t \
+show_##type##_##name(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);\
+ struct iscsi_bus_flash_session *fnode_sess = \
+ iscsi_flash_conn_to_flash_session(fnode_conn);\
+ struct iscsi_transport *t = fnode_conn->transport; \
+ return t->get_flashnode_param(fnode_sess, param, buf); \
+} \
+
+
+#define iscsi_flashnode_conn_attr(type, name, param) \
+ iscsi_flashnode_conn_attr_show(type, name, param) \
+static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
+ show_##type##_##name, NULL);
+
+/* Flash node connection attributes */
+
+iscsi_flashnode_conn_attr(fnode, is_fw_assigned_ipv6,
+ ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6);
+iscsi_flashnode_conn_attr(fnode, header_digest, ISCSI_FLASHNODE_HDR_DGST_EN);
+iscsi_flashnode_conn_attr(fnode, data_digest, ISCSI_FLASHNODE_DATA_DGST_EN);
+iscsi_flashnode_conn_attr(fnode, snack_req, ISCSI_FLASHNODE_SNACK_REQ_EN);
+iscsi_flashnode_conn_attr(fnode, tcp_timestamp_stat,
+ ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT);
+iscsi_flashnode_conn_attr(fnode, tcp_nagle_disable,
+ ISCSI_FLASHNODE_TCP_NAGLE_DISABLE);
+iscsi_flashnode_conn_attr(fnode, tcp_wsf_disable,
+ ISCSI_FLASHNODE_TCP_WSF_DISABLE);
+iscsi_flashnode_conn_attr(fnode, tcp_timer_scale,
+ ISCSI_FLASHNODE_TCP_TIMER_SCALE);
+iscsi_flashnode_conn_attr(fnode, tcp_timestamp_enable,
+ ISCSI_FLASHNODE_TCP_TIMESTAMP_EN);
+iscsi_flashnode_conn_attr(fnode, fragment_disable,
+ ISCSI_FLASHNODE_IP_FRAG_DISABLE);
+iscsi_flashnode_conn_attr(fnode, keepalive_tmo, ISCSI_FLASHNODE_KEEPALIVE_TMO);
+iscsi_flashnode_conn_attr(fnode, port, ISCSI_FLASHNODE_PORT);
+iscsi_flashnode_conn_attr(fnode, ipaddress, ISCSI_FLASHNODE_IPADDR);
+iscsi_flashnode_conn_attr(fnode, max_recv_dlength,
+ ISCSI_FLASHNODE_MAX_RECV_DLENGTH);
+iscsi_flashnode_conn_attr(fnode, max_xmit_dlength,
+ ISCSI_FLASHNODE_MAX_XMIT_DLENGTH);
+iscsi_flashnode_conn_attr(fnode, local_port, ISCSI_FLASHNODE_LOCAL_PORT);
+iscsi_flashnode_conn_attr(fnode, ipv4_tos, ISCSI_FLASHNODE_IPV4_TOS);
+iscsi_flashnode_conn_attr(fnode, ipv6_traffic_class, ISCSI_FLASHNODE_IPV6_TC);
+iscsi_flashnode_conn_attr(fnode, ipv6_flow_label,
+ ISCSI_FLASHNODE_IPV6_FLOW_LABEL);
+iscsi_flashnode_conn_attr(fnode, redirect_ipaddr,
+ ISCSI_FLASHNODE_REDIRECT_IPADDR);
+iscsi_flashnode_conn_attr(fnode, max_segment_size,
+ ISCSI_FLASHNODE_MAX_SEGMENT_SIZE);
+iscsi_flashnode_conn_attr(fnode, link_local_ipv6,
+ ISCSI_FLASHNODE_LINK_LOCAL_IPV6);
+iscsi_flashnode_conn_attr(fnode, tcp_xmit_wsf, ISCSI_FLASHNODE_TCP_XMIT_WSF);
+iscsi_flashnode_conn_attr(fnode, tcp_recv_wsf, ISCSI_FLASHNODE_TCP_RECV_WSF);
+iscsi_flashnode_conn_attr(fnode, statsn, ISCSI_FLASHNODE_STATSN);
+iscsi_flashnode_conn_attr(fnode, exp_statsn, ISCSI_FLASHNODE_EXP_STATSN);
+
+static struct attribute *iscsi_flashnode_conn_attrs[] = {
+ &dev_attr_fnode_is_fw_assigned_ipv6.attr,
+ &dev_attr_fnode_header_digest.attr,
+ &dev_attr_fnode_data_digest.attr,
+ &dev_attr_fnode_snack_req.attr,
+ &dev_attr_fnode_tcp_timestamp_stat.attr,
+ &dev_attr_fnode_tcp_nagle_disable.attr,
+ &dev_attr_fnode_tcp_wsf_disable.attr,
+ &dev_attr_fnode_tcp_timer_scale.attr,
+ &dev_attr_fnode_tcp_timestamp_enable.attr,
+ &dev_attr_fnode_fragment_disable.attr,
+ &dev_attr_fnode_max_recv_dlength.attr,
+ &dev_attr_fnode_max_xmit_dlength.attr,
+ &dev_attr_fnode_keepalive_tmo.attr,
+ &dev_attr_fnode_port.attr,
+ &dev_attr_fnode_ipaddress.attr,
+ &dev_attr_fnode_redirect_ipaddr.attr,
+ &dev_attr_fnode_max_segment_size.attr,
+ &dev_attr_fnode_local_port.attr,
+ &dev_attr_fnode_ipv4_tos.attr,
+ &dev_attr_fnode_ipv6_traffic_class.attr,
+ &dev_attr_fnode_ipv6_flow_label.attr,
+ &dev_attr_fnode_link_local_ipv6.attr,
+ &dev_attr_fnode_tcp_xmit_wsf.attr,
+ &dev_attr_fnode_tcp_recv_wsf.attr,
+ &dev_attr_fnode_statsn.attr,
+ &dev_attr_fnode_exp_statsn.attr,
+ NULL,
+};
+
+static umode_t iscsi_flashnode_conn_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int i)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
+ struct iscsi_transport *t = fnode_conn->transport;
+ int param;
+
+ if (attr == &dev_attr_fnode_is_fw_assigned_ipv6.attr) {
+ param = ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6;
+ } else if (attr == &dev_attr_fnode_header_digest.attr) {
+ param = ISCSI_FLASHNODE_HDR_DGST_EN;
+ } else if (attr == &dev_attr_fnode_data_digest.attr) {
+ param = ISCSI_FLASHNODE_DATA_DGST_EN;
+ } else if (attr == &dev_attr_fnode_snack_req.attr) {
+ param = ISCSI_FLASHNODE_SNACK_REQ_EN;
+ } else if (attr == &dev_attr_fnode_tcp_timestamp_stat.attr) {
+ param = ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT;
+ } else if (attr == &dev_attr_fnode_tcp_nagle_disable.attr) {
+ param = ISCSI_FLASHNODE_TCP_NAGLE_DISABLE;
+ } else if (attr == &dev_attr_fnode_tcp_wsf_disable.attr) {
+ param = ISCSI_FLASHNODE_TCP_WSF_DISABLE;
+ } else if (attr == &dev_attr_fnode_tcp_timer_scale.attr) {
+ param = ISCSI_FLASHNODE_TCP_TIMER_SCALE;
+ } else if (attr == &dev_attr_fnode_tcp_timestamp_enable.attr) {
+ param = ISCSI_FLASHNODE_TCP_TIMESTAMP_EN;
+ } else if (attr == &dev_attr_fnode_fragment_disable.attr) {
+ param = ISCSI_FLASHNODE_IP_FRAG_DISABLE;
+ } else if (attr == &dev_attr_fnode_max_recv_dlength.attr) {
+ param = ISCSI_FLASHNODE_MAX_RECV_DLENGTH;
+ } else if (attr == &dev_attr_fnode_max_xmit_dlength.attr) {
+ param = ISCSI_FLASHNODE_MAX_XMIT_DLENGTH;
+ } else if (attr == &dev_attr_fnode_keepalive_tmo.attr) {
+ param = ISCSI_FLASHNODE_KEEPALIVE_TMO;
+ } else if (attr == &dev_attr_fnode_port.attr) {
+ param = ISCSI_FLASHNODE_PORT;
+ } else if (attr == &dev_attr_fnode_ipaddress.attr) {
+ param = ISCSI_FLASHNODE_IPADDR;
+ } else if (attr == &dev_attr_fnode_redirect_ipaddr.attr) {
+ param = ISCSI_FLASHNODE_REDIRECT_IPADDR;
+ } else if (attr == &dev_attr_fnode_max_segment_size.attr) {
+ param = ISCSI_FLASHNODE_MAX_SEGMENT_SIZE;
+ } else if (attr == &dev_attr_fnode_local_port.attr) {
+ param = ISCSI_FLASHNODE_LOCAL_PORT;
+ } else if (attr == &dev_attr_fnode_ipv4_tos.attr) {
+ param = ISCSI_FLASHNODE_IPV4_TOS;
+ } else if (attr == &dev_attr_fnode_ipv6_traffic_class.attr) {
+ param = ISCSI_FLASHNODE_IPV6_TC;
+ } else if (attr == &dev_attr_fnode_ipv6_flow_label.attr) {
+ param = ISCSI_FLASHNODE_IPV6_FLOW_LABEL;
+ } else if (attr == &dev_attr_fnode_link_local_ipv6.attr) {
+ param = ISCSI_FLASHNODE_LINK_LOCAL_IPV6;
+ } else if (attr == &dev_attr_fnode_tcp_xmit_wsf.attr) {
+ param = ISCSI_FLASHNODE_TCP_XMIT_WSF;
+ } else if (attr == &dev_attr_fnode_tcp_recv_wsf.attr) {
+ param = ISCSI_FLASHNODE_TCP_RECV_WSF;
+ } else if (attr == &dev_attr_fnode_statsn.attr) {
+ param = ISCSI_FLASHNODE_STATSN;
+ } else if (attr == &dev_attr_fnode_exp_statsn.attr) {
+ param = ISCSI_FLASHNODE_EXP_STATSN;
+ } else {
+ WARN_ONCE(1, "Invalid flashnode connection attr");
+ return 0;
+ }
+
+ return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
+}
+
+static struct attribute_group iscsi_flashnode_conn_attr_group = {
+ .attrs = iscsi_flashnode_conn_attrs,
+ .is_visible = iscsi_flashnode_conn_attr_is_visible,
+};
+
+static const struct attribute_group *iscsi_flashnode_conn_attr_groups[] = {
+ &iscsi_flashnode_conn_attr_group,
+ NULL,
+};
+
+static void iscsi_flashnode_conn_release(struct device *dev)
+{
+ struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
+
+ kfree(fnode_conn->ipaddress);
+ kfree(fnode_conn->redirect_ipaddr);
+ kfree(fnode_conn->link_local_ipv6_addr);
+ kfree(fnode_conn);
+}
+
+struct device_type iscsi_flashnode_conn_dev_type = {
+ .name = "iscsi_flashnode_conn_dev_type",
+ .groups = iscsi_flashnode_conn_attr_groups,
+ .release = iscsi_flashnode_conn_release,
+};
+
+struct bus_type iscsi_flashnode_bus;
+
+int iscsi_flashnode_bus_match(struct device *dev,
+ struct device_driver *drv)
+{
+ if (dev->bus == &iscsi_flashnode_bus)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match);
+
+struct bus_type iscsi_flashnode_bus = {
+ .name = "iscsi_flashnode",
+ .match = &iscsi_flashnode_bus_match,
+};
+
+/**
+ * iscsi_create_flashnode_sess - Add flashnode session entry in sysfs
+ * @shost: pointer to host data
+ * @index: index of flashnode to add in sysfs
+ * @transport: pointer to transport data
+ * @dd_size: total size to allocate
+ *
+ * Adds a sysfs entry for the flashnode session attributes
+ *
+ * Returns:
+ * pointer to allocated flashnode sess on sucess
+ * %NULL on failure
+ */
+struct iscsi_bus_flash_session *
+iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index,
+ struct iscsi_transport *transport,
+ int dd_size)
+{
+ struct iscsi_bus_flash_session *fnode_sess;
+ int err;
+
+ fnode_sess = kzalloc(sizeof(*fnode_sess) + dd_size, GFP_KERNEL);
+ if (!fnode_sess)
+ return NULL;
+
+ fnode_sess->transport = transport;
+ fnode_sess->target_id = index;
+ fnode_sess->dev.type = &iscsi_flashnode_sess_dev_type;
+ fnode_sess->dev.bus = &iscsi_flashnode_bus;
+ fnode_sess->dev.parent = &shost->shost_gendev;
+ dev_set_name(&fnode_sess->dev, "flashnode_sess-%u:%u",
+ shost->host_no, index);
+
+ err = device_register(&fnode_sess->dev);
+ if (err)
+ goto free_fnode_sess;
+
+ if (dd_size)
+ fnode_sess->dd_data = &fnode_sess[1];
+
+ return fnode_sess;
+
+free_fnode_sess:
+ kfree(fnode_sess);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess);
+
+/**
+ * iscsi_create_flashnode_conn - Add flashnode conn entry in sysfs
+ * @shost: pointer to host data
+ * @fnode_sess: pointer to the parent flashnode session entry
+ * @transport: pointer to transport data
+ * @dd_size: total size to allocate
+ *
+ * Adds a sysfs entry for the flashnode connection attributes
+ *
+ * Returns:
+ * pointer to allocated flashnode conn on success
+ * %NULL on failure
+ */
+struct iscsi_bus_flash_conn *
+iscsi_create_flashnode_conn(struct Scsi_Host *shost,
+ struct iscsi_bus_flash_session *fnode_sess,
+ struct iscsi_transport *transport,
+ int dd_size)
+{
+ struct iscsi_bus_flash_conn *fnode_conn;
+ int err;
+
+ fnode_conn = kzalloc(sizeof(*fnode_conn) + dd_size, GFP_KERNEL);
+ if (!fnode_conn)
+ return NULL;
+
+ fnode_conn->transport = transport;
+ fnode_conn->dev.type = &iscsi_flashnode_conn_dev_type;
+ fnode_conn->dev.bus = &iscsi_flashnode_bus;
+ fnode_conn->dev.parent = &fnode_sess->dev;
+ dev_set_name(&fnode_conn->dev, "flashnode_conn-%u:%u:0",
+ shost->host_no, fnode_sess->target_id);
+
+ err = device_register(&fnode_conn->dev);
+ if (err)
+ goto free_fnode_conn;
+
+ if (dd_size)
+ fnode_conn->dd_data = &fnode_conn[1];
+
+ return fnode_conn;
+
+free_fnode_conn:
+ kfree(fnode_conn);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn);
+
+/**
+ * iscsi_is_flashnode_conn_dev - verify passed device is to be flashnode conn
+ * @dev: device to verify
+ * @data: pointer to data containing value to use for verification
+ *
+ * Verifies if the passed device is flashnode conn device
+ *
+ * Returns:
+ * 1 on success
+ * 0 on failure
+ */
+int iscsi_is_flashnode_conn_dev(struct device *dev, void *data)
+{
+ return dev->bus == &iscsi_flashnode_bus;
+}
+EXPORT_SYMBOL_GPL(iscsi_is_flashnode_conn_dev);
+
+static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn)
+{
+ device_unregister(&fnode_conn->dev);
+ return 0;
+}
+
+static int flashnode_match_index(struct device *dev, void *data)
+{
+ struct iscsi_bus_flash_session *fnode_sess = NULL;
+ int ret = 0;
+
+ if (!iscsi_flashnode_bus_match(dev, NULL))
+ goto exit_match_index;
+
+ fnode_sess = iscsi_dev_to_flash_session(dev);
+ ret = (fnode_sess->target_id == *((int *)data)) ? 1 : 0;
+
+exit_match_index:
+ return ret;
+}
+
+/**
+ * iscsi_get_flashnode_by_index -finds flashnode session entry by index
+ * @shost: pointer to host data
+ * @idx: index to match
+ *
+ * Finds the flashnode session object for the passed index
+ *
+ * Returns:
+ * pointer to found flashnode session object on success
+ * %NULL on failure
+ */
+static struct iscsi_bus_flash_session *
+iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
+{
+ struct iscsi_bus_flash_session *fnode_sess = NULL;
+ struct device *dev;
+
+ dev = device_find_child(&shost->shost_gendev, &idx,
+ flashnode_match_index);
+ if (dev)
+ fnode_sess = iscsi_dev_to_flash_session(dev);
+
+ return fnode_sess;
+}
+
+/**
+ * iscsi_find_flashnode_sess - finds flashnode session entry
+ * @shost: pointer to host data
+ * @data: pointer to data containing value to use for comparison
+ * @fn: function pointer that does actual comparison
+ *
+ * Finds the flashnode session object comparing the data passed using logic
+ * defined in passed function pointer
+ *
+ * Returns:
+ * pointer to found flashnode session device object on success
+ * %NULL on failure
+ */
+struct device *
+iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
+ int (*fn)(struct device *dev, void *data))
+{
+ return device_find_child(&shost->shost_gendev, data, fn);
+}
+EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
+
+/**
+ * iscsi_find_flashnode_conn - finds flashnode connection entry
+ * @fnode_sess: pointer to parent flashnode session entry
+ *
+ * Finds the flashnode connection object comparing the data passed using logic
+ * defined in passed function pointer
+ *
+ * Returns:
+ * pointer to found flashnode connection device object on success
+ * %NULL on failure
+ */
+struct device *
+iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
+{
+ return device_find_child(&fnode_sess->dev, NULL,
+ iscsi_is_flashnode_conn_dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
+
+static int iscsi_iter_destroy_flashnode_conn_fn(struct device *dev, void *data)
+{
+ if (!iscsi_is_flashnode_conn_dev(dev, NULL))
+ return 0;
+
+ return iscsi_destroy_flashnode_conn(iscsi_dev_to_flash_conn(dev));
+}
+
+/**
+ * iscsi_destroy_flashnode_sess - destory flashnode session entry
+ * @fnode_sess: pointer to flashnode session entry to be destroyed
+ *
+ * Deletes the flashnode session entry and all children flashnode connection
+ * entries from sysfs
+ */
+void iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess)
+{
+ int err;
+
+ err = device_for_each_child(&fnode_sess->dev, NULL,
+ iscsi_iter_destroy_flashnode_conn_fn);
+ if (err)
+ pr_err("Could not delete all connections for %s. Error %d.\n",
+ fnode_sess->dev.kobj.name, err);
+
+ device_unregister(&fnode_sess->dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_destroy_flashnode_sess);
+
+static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data)
+{
+ if (!iscsi_flashnode_bus_match(dev, NULL))
+ return 0;
+
+ iscsi_destroy_flashnode_sess(iscsi_dev_to_flash_session(dev));
+ return 0;
+}
+
+/**
+ * iscsi_destroy_all_flashnode - destory all flashnode session entries
+ * @shost: pointer to host data
+ *
+ * Destroys all the flashnode session entries and all corresponding children
+ * flashnode connection entries from sysfs
+ */
+void iscsi_destroy_all_flashnode(struct Scsi_Host *shost)
+{
+ device_for_each_child(&shost->shost_gendev, NULL,
+ iscsi_iter_destroy_flashnode_fn);
+}
+EXPORT_SYMBOL_GPL(iscsi_destroy_all_flashnode);
+
+/*
* BSG support
*/
/**
@@ -1344,8 +2018,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
struct iscsi_uevent *ev;
char *pdu;
struct iscsi_internal *priv;
- int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
- data_size);
+ int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) +
+ data_size);
priv = iscsi_if_transport_lookup(conn->transport);
if (!priv)
@@ -1360,7 +2034,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
memset(ev, 0, sizeof(*ev));
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_RECV_PDU;
@@ -1381,7 +2055,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+ int len = nlmsg_total_size(sizeof(*ev) + data_size);
skb = alloc_skb(len, GFP_ATOMIC);
if (!skb) {
@@ -1390,7 +2064,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
memset(ev, 0, sizeof(*ev));
ev->type = type;
ev->transport_handle = iscsi_handle(transport);
@@ -1415,7 +2089,7 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
struct sk_buff *skb;
struct iscsi_uevent *ev;
struct iscsi_internal *priv;
- int len = NLMSG_SPACE(sizeof(*ev));
+ int len = nlmsg_total_size(sizeof(*ev));
priv = iscsi_if_transport_lookup(conn->transport);
if (!priv)
@@ -1429,7 +2103,7 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_CONN_ERROR;
ev->r.connerror.error = error;
@@ -1450,7 +2124,7 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
struct sk_buff *skb;
struct iscsi_uevent *ev;
struct iscsi_internal *priv;
- int len = NLMSG_SPACE(sizeof(*ev));
+ int len = nlmsg_total_size(sizeof(*ev));
priv = iscsi_if_transport_lookup(conn->transport);
if (!priv)
@@ -1464,7 +2138,7 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
ev->r.conn_login.state = state;
@@ -1484,7 +2158,7 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+ int len = nlmsg_total_size(sizeof(*ev) + data_size);
skb = alloc_skb(len, GFP_NOIO);
if (!skb) {
@@ -1494,7 +2168,7 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
ev->transport_handle = iscsi_handle(transport);
ev->type = ISCSI_KEVENT_HOST_EVENT;
ev->r.host_event.host_no = host_no;
@@ -1515,7 +2189,7 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+ int len = nlmsg_total_size(sizeof(*ev) + data_size);
skb = alloc_skb(len, GFP_NOIO);
if (!skb) {
@@ -1524,7 +2198,7 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
ev->transport_handle = iscsi_handle(transport);
ev->type = ISCSI_KEVENT_PING_COMP;
ev->r.ping_comp.host_no = host_no;
@@ -1543,7 +2217,7 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
- int len = NLMSG_SPACE(size);
+ int len = nlmsg_total_size(size);
int flags = multi ? NLM_F_MULTI : 0;
int t = done ? NLMSG_DONE : type;
@@ -1555,24 +2229,24 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0);
nlh->nlmsg_flags = flags;
- memcpy(NLMSG_DATA(nlh), payload, size);
+ memcpy(nlmsg_data(nlh), payload, size);
return iscsi_multicast_skb(skb, group, GFP_ATOMIC);
}
static int
iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
{
- struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ struct iscsi_uevent *ev = nlmsg_data(nlh);
struct iscsi_stats *stats;
struct sk_buff *skbstat;
struct iscsi_cls_conn *conn;
struct nlmsghdr *nlhstat;
struct iscsi_uevent *evstat;
struct iscsi_internal *priv;
- int len = NLMSG_SPACE(sizeof(*ev) +
- sizeof(struct iscsi_stats) +
- sizeof(struct iscsi_stats_custom) *
- ISCSI_STATS_CUSTOM_MAX);
+ int len = nlmsg_total_size(sizeof(*ev) +
+ sizeof(struct iscsi_stats) +
+ sizeof(struct iscsi_stats_custom) *
+ ISCSI_STATS_CUSTOM_MAX);
int err = 0;
priv = iscsi_if_transport_lookup(transport);
@@ -1595,7 +2269,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
(len - sizeof(*nlhstat)), 0);
- evstat = NLMSG_DATA(nlhstat);
+ evstat = nlmsg_data(nlhstat);
memset(evstat, 0, sizeof(*evstat));
evstat->transport_handle = iscsi_handle(conn->transport);
evstat->type = nlh->nlmsg_type;
@@ -1608,12 +2282,12 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
memset(stats, 0, sizeof(*stats));
transport->get_stats(conn, stats);
- actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
- sizeof(struct iscsi_stats) +
- sizeof(struct iscsi_stats_custom) *
- stats->custom_length);
+ actual_size = nlmsg_total_size(sizeof(struct iscsi_uevent) +
+ sizeof(struct iscsi_stats) +
+ sizeof(struct iscsi_stats_custom) *
+ stats->custom_length);
actual_size -= sizeof(*nlhstat);
- actual_size = NLMSG_LENGTH(actual_size);
+ actual_size = nlmsg_msg_size(actual_size);
skb_trim(skbstat, NLMSG_ALIGN(actual_size));
nlhstat->nlmsg_len = actual_size;
@@ -1637,7 +2311,7 @@ int iscsi_session_event(struct iscsi_cls_session *session,
struct iscsi_uevent *ev;
struct sk_buff *skb;
struct nlmsghdr *nlh;
- int rc, len = NLMSG_SPACE(sizeof(*ev));
+ int rc, len = nlmsg_total_size(sizeof(*ev));
priv = iscsi_if_transport_lookup(session->transport);
if (!priv)
@@ -1653,7 +2327,7 @@ int iscsi_session_event(struct iscsi_cls_session *session,
}
nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
ev->transport_handle = iscsi_handle(session->transport);
ev->type = event;
@@ -2005,7 +2679,7 @@ iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
static int
iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
{
- struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ struct iscsi_uevent *ev = nlmsg_data(nlh);
struct Scsi_Host *shost = NULL;
struct iscsi_chap_rec *chap_rec;
struct iscsi_internal *priv;
@@ -2024,7 +2698,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
return -EINVAL;
chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec));
- len = NLMSG_SPACE(sizeof(*ev) + chap_buf_size);
+ len = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
shost = scsi_host_lookup(ev->u.get_chap.host_no);
if (!shost) {
@@ -2045,7 +2719,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
nlhchap = __nlmsg_put(skbchap, 0, 0, 0,
(len - sizeof(*nlhchap)), 0);
- evchap = NLMSG_DATA(nlhchap);
+ evchap = nlmsg_data(nlhchap);
memset(evchap, 0, sizeof(*evchap));
evchap->transport_handle = iscsi_handle(transport);
evchap->type = nlh->nlmsg_type;
@@ -2058,7 +2732,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
&evchap->u.get_chap.num_entries, buf);
- actual_size = NLMSG_SPACE(sizeof(*ev) + chap_buf_size);
+ actual_size = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
skb_trim(skbchap, NLMSG_ALIGN(actual_size));
nlhchap->nlmsg_len = actual_size;
@@ -2092,11 +2766,305 @@ static int iscsi_delete_chap(struct iscsi_transport *transport,
return err;
}
+static const struct {
+ enum iscsi_discovery_parent_type value;
+ char *name;
+} iscsi_discovery_parent_names[] = {
+ {ISCSI_DISC_PARENT_UNKNOWN, "Unknown" },
+ {ISCSI_DISC_PARENT_SENDTGT, "Sendtarget" },
+ {ISCSI_DISC_PARENT_ISNS, "isns" },
+};
+
+char *iscsi_get_discovery_parent_name(int parent_type)
+{
+ int i;
+ char *state = "Unknown!";
+
+ for (i = 0; i < ARRAY_SIZE(iscsi_discovery_parent_names); i++) {
+ if (iscsi_discovery_parent_names[i].value & parent_type) {
+ state = iscsi_discovery_parent_names[i].name;
+ break;
+ }
+ }
+ return state;
+}
+EXPORT_SYMBOL_GPL(iscsi_get_discovery_parent_name);
+
+static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev, uint32_t len)
+{
+ char *data = (char *)ev + sizeof(*ev);
+ struct Scsi_Host *shost;
+ struct iscsi_bus_flash_session *fnode_sess;
+ struct iscsi_bus_flash_conn *fnode_conn;
+ struct device *dev;
+ uint32_t idx;
+ int err = 0;
+
+ if (!transport->set_flashnode_param) {
+ err = -ENOSYS;
+ goto exit_set_fnode;
+ }
+
+ shost = scsi_host_lookup(ev->u.set_flashnode.host_no);
+ if (!shost) {
+ pr_err("%s could not find host no %u\n",
+ __func__, ev->u.set_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ idx = ev->u.set_flashnode.flashnode_idx;
+ fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ if (!fnode_sess) {
+ pr_err("%s could not find flashnode %u for host no %u\n",
+ __func__, idx, ev->u.set_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ dev = iscsi_find_flashnode_conn(fnode_sess);
+ if (!dev) {
+ err = -ENODEV;
+ goto put_sess;
+ }
+
+ fnode_conn = iscsi_dev_to_flash_conn(dev);
+ err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
+ put_device(dev);
+
+put_sess:
+ put_device(&fnode_sess->dev);
+
+put_host:
+ scsi_host_put(shost);
+
+exit_set_fnode:
+ return err;
+}
+
+static int iscsi_new_flashnode(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev, uint32_t len)
+{
+ char *data = (char *)ev + sizeof(*ev);
+ struct Scsi_Host *shost;
+ int index;
+ int err = 0;
+
+ if (!transport->new_flashnode) {
+ err = -ENOSYS;
+ goto exit_new_fnode;
+ }
+
+ shost = scsi_host_lookup(ev->u.new_flashnode.host_no);
+ if (!shost) {
+ pr_err("%s could not find host no %u\n",
+ __func__, ev->u.new_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ index = transport->new_flashnode(shost, data, len);
+
+ if (index >= 0)
+ ev->r.new_flashnode_ret.flashnode_idx = index;
+ else
+ err = -EIO;
+
+put_host:
+ scsi_host_put(shost);
+
+exit_new_fnode:
+ return err;
+}
+
+static int iscsi_del_flashnode(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ struct iscsi_bus_flash_session *fnode_sess;
+ uint32_t idx;
+ int err = 0;
+
+ if (!transport->del_flashnode) {
+ err = -ENOSYS;
+ goto exit_del_fnode;
+ }
+
+ shost = scsi_host_lookup(ev->u.del_flashnode.host_no);
+ if (!shost) {
+ pr_err("%s could not find host no %u\n",
+ __func__, ev->u.del_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ idx = ev->u.del_flashnode.flashnode_idx;
+ fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ if (!fnode_sess) {
+ pr_err("%s could not find flashnode %u for host no %u\n",
+ __func__, idx, ev->u.del_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ err = transport->del_flashnode(fnode_sess);
+ put_device(&fnode_sess->dev);
+
+put_host:
+ scsi_host_put(shost);
+
+exit_del_fnode:
+ return err;
+}
+
+static int iscsi_login_flashnode(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ struct iscsi_bus_flash_session *fnode_sess;
+ struct iscsi_bus_flash_conn *fnode_conn;
+ struct device *dev;
+ uint32_t idx;
+ int err = 0;
+
+ if (!transport->login_flashnode) {
+ err = -ENOSYS;
+ goto exit_login_fnode;
+ }
+
+ shost = scsi_host_lookup(ev->u.login_flashnode.host_no);
+ if (!shost) {
+ pr_err("%s could not find host no %u\n",
+ __func__, ev->u.login_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ idx = ev->u.login_flashnode.flashnode_idx;
+ fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ if (!fnode_sess) {
+ pr_err("%s could not find flashnode %u for host no %u\n",
+ __func__, idx, ev->u.login_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ dev = iscsi_find_flashnode_conn(fnode_sess);
+ if (!dev) {
+ err = -ENODEV;
+ goto put_sess;
+ }
+
+ fnode_conn = iscsi_dev_to_flash_conn(dev);
+ err = transport->login_flashnode(fnode_sess, fnode_conn);
+ put_device(dev);
+
+put_sess:
+ put_device(&fnode_sess->dev);
+
+put_host:
+ scsi_host_put(shost);
+
+exit_login_fnode:
+ return err;
+}
+
+static int iscsi_logout_flashnode(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ struct iscsi_bus_flash_session *fnode_sess;
+ struct iscsi_bus_flash_conn *fnode_conn;
+ struct device *dev;
+ uint32_t idx;
+ int err = 0;
+
+ if (!transport->logout_flashnode) {
+ err = -ENOSYS;
+ goto exit_logout_fnode;
+ }
+
+ shost = scsi_host_lookup(ev->u.logout_flashnode.host_no);
+ if (!shost) {
+ pr_err("%s could not find host no %u\n",
+ __func__, ev->u.logout_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ idx = ev->u.logout_flashnode.flashnode_idx;
+ fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ if (!fnode_sess) {
+ pr_err("%s could not find flashnode %u for host no %u\n",
+ __func__, idx, ev->u.logout_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ dev = iscsi_find_flashnode_conn(fnode_sess);
+ if (!dev) {
+ err = -ENODEV;
+ goto put_sess;
+ }
+
+ fnode_conn = iscsi_dev_to_flash_conn(dev);
+
+ err = transport->logout_flashnode(fnode_sess, fnode_conn);
+ put_device(dev);
+
+put_sess:
+ put_device(&fnode_sess->dev);
+
+put_host:
+ scsi_host_put(shost);
+
+exit_logout_fnode:
+ return err;
+}
+
+static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ struct iscsi_cls_session *session;
+ int err = 0;
+
+ if (!transport->logout_flashnode_sid) {
+ err = -ENOSYS;
+ goto exit_logout_sid;
+ }
+
+ shost = scsi_host_lookup(ev->u.logout_flashnode_sid.host_no);
+ if (!shost) {
+ pr_err("%s could not find host no %u\n",
+ __func__, ev->u.logout_flashnode.host_no);
+ err = -ENODEV;
+ goto put_host;
+ }
+
+ session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid);
+ if (!session) {
+ pr_err("%s could not find session id %u\n",
+ __func__, ev->u.logout_flashnode_sid.sid);
+ err = -EINVAL;
+ goto put_host;
+ }
+
+ err = transport->logout_flashnode_sid(session);
+
+put_host:
+ scsi_host_put(shost);
+
+exit_logout_sid:
+ return err;
+}
+
static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
{
int err = 0;
- struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ struct iscsi_uevent *ev = nlmsg_data(nlh);
struct iscsi_transport *transport = NULL;
struct iscsi_internal *priv;
struct iscsi_cls_session *session;
@@ -2246,6 +3214,27 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
case ISCSI_UEVENT_DELETE_CHAP:
err = iscsi_delete_chap(transport, ev);
break;
+ case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
+ err = iscsi_set_flashnode_param(transport, ev,
+ nlmsg_attrlen(nlh,
+ sizeof(*ev)));
+ break;
+ case ISCSI_UEVENT_NEW_FLASHNODE:
+ err = iscsi_new_flashnode(transport, ev,
+ nlmsg_attrlen(nlh, sizeof(*ev)));
+ break;
+ case ISCSI_UEVENT_DEL_FLASHNODE:
+ err = iscsi_del_flashnode(transport, ev);
+ break;
+ case ISCSI_UEVENT_LOGIN_FLASHNODE:
+ err = iscsi_login_flashnode(transport, ev);
+ break;
+ case ISCSI_UEVENT_LOGOUT_FLASHNODE:
+ err = iscsi_logout_flashnode(transport, ev);
+ break;
+ case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID:
+ err = iscsi_logout_flashnode_sid(transport, ev);
+ break;
default:
err = -ENOSYS;
break;
@@ -2263,7 +3252,7 @@ static void
iscsi_if_rx(struct sk_buff *skb)
{
mutex_lock(&rx_queue_mutex);
- while (skb->len >= NLMSG_SPACE(0)) {
+ while (skb->len >= NLMSG_HDRLEN) {
int err;
uint32_t rlen;
struct nlmsghdr *nlh;
@@ -2276,7 +3265,7 @@ iscsi_if_rx(struct sk_buff *skb)
break;
}
- ev = NLMSG_DATA(nlh);
+ ev = nlmsg_data(nlh);
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
rlen = skb->len;
@@ -2484,6 +3473,9 @@ iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0);
iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0);
+iscsi_session_attr(boot_root, ISCSI_PARAM_BOOT_ROOT, 0);
+iscsi_session_attr(boot_nic, ISCSI_PARAM_BOOT_NIC, 0);
+iscsi_session_attr(boot_target, ISCSI_PARAM_BOOT_TARGET, 0);
static ssize_t
show_priv_session_state(struct device *dev, struct device_attribute *attr,
@@ -2503,6 +3495,15 @@ show_priv_session_creator(struct device *dev, struct device_attribute *attr,
}
static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
NULL);
+static ssize_t
+show_priv_session_target_id(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
+ return sprintf(buf, "%d\n", session->target_id);
+}
+static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO,
+ show_priv_session_target_id, NULL);
#define iscsi_priv_session_attr_show(field, format) \
static ssize_t \
@@ -2570,11 +3571,15 @@ static struct attribute *iscsi_session_attrs[] = {
&dev_attr_sess_ifacename.attr,
&dev_attr_sess_initiatorname.attr,
&dev_attr_sess_targetalias.attr,
+ &dev_attr_sess_boot_root.attr,
+ &dev_attr_sess_boot_nic.attr,
+ &dev_attr_sess_boot_target.attr,
&dev_attr_priv_sess_recovery_tmo.attr,
&dev_attr_priv_sess_state.attr,
&dev_attr_priv_sess_creator.attr,
&dev_attr_sess_chap_out_idx.attr,
&dev_attr_sess_chap_in_idx.attr,
+ &dev_attr_priv_sess_target_id.attr,
NULL,
};
@@ -2632,12 +3637,20 @@ static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
param = ISCSI_PARAM_INITIATOR_NAME;
else if (attr == &dev_attr_sess_targetalias.attr)
param = ISCSI_PARAM_TARGET_ALIAS;
+ else if (attr == &dev_attr_sess_boot_root.attr)
+ param = ISCSI_PARAM_BOOT_ROOT;
+ else if (attr == &dev_attr_sess_boot_nic.attr)
+ param = ISCSI_PARAM_BOOT_NIC;
+ else if (attr == &dev_attr_sess_boot_target.attr)
+ param = ISCSI_PARAM_BOOT_TARGET;
else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
return S_IRUGO | S_IWUSR;
else if (attr == &dev_attr_priv_sess_state.attr)
return S_IRUGO;
else if (attr == &dev_attr_priv_sess_creator.attr)
return S_IRUGO;
+ else if (attr == &dev_attr_priv_sess_target_id.attr)
+ return S_IRUGO;
else {
WARN_ONCE(1, "Invalid session attr");
return 0;
@@ -2969,20 +3982,28 @@ static __init int iscsi_transport_init(void)
if (err)
goto unregister_conn_class;
+ err = bus_register(&iscsi_flashnode_bus);
+ if (err)
+ goto unregister_session_class;
+
nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg);
if (!nls) {
err = -ENOBUFS;
- goto unregister_session_class;
+ goto unregister_flashnode_bus;
}
iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
- if (!iscsi_eh_timer_workq)
+ if (!iscsi_eh_timer_workq) {
+ err = -ENOMEM;
goto release_nls;
+ }
return 0;
release_nls:
netlink_kernel_release(nls);
+unregister_flashnode_bus:
+ bus_unregister(&iscsi_flashnode_bus);
unregister_session_class:
transport_class_unregister(&iscsi_session_class);
unregister_conn_class:
@@ -3002,6 +4023,7 @@ static void __exit iscsi_transport_exit(void)
{
destroy_workqueue(iscsi_eh_timer_workq);
netlink_kernel_release(nls);
+ bus_unregister(&iscsi_flashnode_bus);
transport_class_unregister(&iscsi_connection_class);
transport_class_unregister(&iscsi_session_class);
transport_class_unregister(&iscsi_host_class);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 7992635..80f39b8 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -142,6 +142,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
char *buffer_data;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
+ static const char temp[] = "temporary ";
int len;
if (sdp->type != TYPE_DISK)
@@ -150,6 +151,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
* it's not worth the risk */
return -EINVAL;
+ if (strncmp(buf, temp, sizeof(temp) - 1) == 0) {
+ buf += sizeof(temp) - 1;
+ sdkp->cache_override = 1;
+ } else {
+ sdkp->cache_override = 0;
+ }
+
for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
len = strlen(sd_cache_types[i]);
if (strncmp(sd_cache_types[i], buf, len) == 0 &&
@@ -162,6 +170,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
return -EINVAL;
rcd = ct & 0x01 ? 1 : 0;
wce = ct & 0x02 ? 1 : 0;
+
+ if (sdkp->cache_override) {
+ sdkp->WCE = wce;
+ sdkp->RCD = rcd;
+ return count;
+ }
+
if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
SD_MAX_RETRIES, &data, NULL))
return -EINVAL;
@@ -427,8 +442,10 @@ sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
if (max == 0)
sdp->no_write_same = 1;
- else if (max <= SD_MAX_WS16_BLOCKS)
+ else if (max <= SD_MAX_WS16_BLOCKS) {
+ sdp->no_write_same = 0;
sdkp->max_ws_blocks = max;
+ }
sd_config_write_same(sdkp);
@@ -489,6 +506,16 @@ static struct scsi_driver sd_template = {
};
/*
+ * Dummy kobj_map->probe function.
+ * The default ->probe function will call modprobe, which is
+ * pointless as this module is already loaded.
+ */
+static struct kobject *sd_default_probe(dev_t devt, int *partno, void *data)
+{
+ return NULL;
+}
+
+/*
* Device no to disk mapping:
*
* major disc2 disc p1
@@ -725,7 +752,6 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
{
struct request_queue *q = sdkp->disk->queue;
unsigned int logical_block_size = sdkp->device->sector_size;
- unsigned int blocks = 0;
if (sdkp->device->no_write_same) {
sdkp->max_ws_blocks = 0;
@@ -737,18 +763,20 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
* blocks per I/O unless the device explicitly advertises a
* bigger limit.
*/
- if (sdkp->max_ws_blocks == 0)
- sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
-
- if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
- blocks = min_not_zero(sdkp->max_ws_blocks,
- (u32)SD_MAX_WS16_BLOCKS);
- else
- blocks = min_not_zero(sdkp->max_ws_blocks,
- (u32)SD_MAX_WS10_BLOCKS);
+ if (sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+ sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS16_BLOCKS);
+ else if (sdkp->ws16 || sdkp->ws10 || sdkp->device->no_report_opcodes)
+ sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS10_BLOCKS);
+ else {
+ sdkp->device->no_write_same = 1;
+ sdkp->max_ws_blocks = 0;
+ }
out:
- blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+ blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks *
+ (logical_block_size >> 9));
}
/**
@@ -1121,10 +1149,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
sdev = sdkp->device;
- retval = scsi_autopm_get_device(sdev);
- if (retval)
- goto error_autopm;
-
/*
* If the device is in error recovery, wait until it is done.
* If the device is offline, then disallow any access to it.
@@ -1169,8 +1193,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
return 0;
error_out:
- scsi_autopm_put_device(sdev);
-error_autopm:
scsi_disk_put(sdkp);
return retval;
}
@@ -1188,7 +1210,7 @@ error_autopm:
*
* Locking: called with bdev->bd_mutex held.
**/
-static int sd_release(struct gendisk *disk, fmode_t mode)
+static void sd_release(struct gendisk *disk, fmode_t mode)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdev = sdkp->device;
@@ -1205,9 +1227,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode)
* XXX is followed by a "rmmod sd_mod"?
*/
- scsi_autopm_put_device(sdev);
scsi_disk_put(sdkp);
- return 0;
}
static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
@@ -1367,14 +1387,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
retval = -ENODEV;
if (scsi_block_when_processing_errors(sdp)) {
- retval = scsi_autopm_get_device(sdp);
- if (retval)
- goto out;
-
sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL);
retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
sshdr);
- scsi_autopm_put_device(sdp);
}
/* failed to execute TUR, assume media not present */
@@ -1424,8 +1439,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
* Leave the rest of the command zero to indicate
* flush everything.
*/
- res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
- SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
+ res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
+ &sshdr, SD_FLUSH_TIMEOUT,
+ SD_MAX_RETRIES, NULL, REQ_PM);
if (res == 0)
break;
}
@@ -2319,6 +2335,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
int old_rcd = sdkp->RCD;
int old_dpofua = sdkp->DPOFUA;
+
+ if (sdkp->cache_override)
+ return;
+
first_len = 4;
if (sdp->skip_ms_page_8) {
if (sdp->type == TYPE_RBC)
@@ -2628,9 +2648,24 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
{
- if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
- WRITE_SAME_16))
+ struct scsi_device *sdev = sdkp->device;
+
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
+ sdev->no_report_opcodes = 1;
+
+ /* Disable WRITE SAME if REPORT SUPPORTED OPERATION
+ * CODES is unsupported and the device has an ATA
+ * Information VPD page (SAT).
+ */
+ if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE))
+ sdev->no_write_same = 1;
+ }
+
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
sdkp->ws16 = 1;
+
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1)
+ sdkp->ws10 = 1;
}
static int sd_try_extended_inquiry(struct scsi_device *sdp)
@@ -2812,6 +2847,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sdkp->capacity = 0;
sdkp->media_present = 1;
sdkp->write_prot = 0;
+ sdkp->cache_override = 0;
sdkp->WCE = 0;
sdkp->RCD = 0;
sdkp->ATO = 0;
@@ -2838,6 +2874,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : "");
+ blk_pm_runtime_init(sdp->request_queue, dev);
scsi_autopm_put_device(sdp);
put_device(&sdkp->dev);
}
@@ -2922,7 +2959,7 @@ static int sd_probe(struct device *dev)
device_initialize(&sdkp->dev);
sdkp->dev.parent = dev;
sdkp->dev.class = &sd_disk_class;
- dev_set_name(&sdkp->dev, dev_name(dev));
+ dev_set_name(&sdkp->dev, "%s", dev_name(dev));
if (device_add(&sdkp->dev))
goto out_free_index;
@@ -2961,8 +2998,10 @@ static int sd_probe(struct device *dev)
static int sd_remove(struct device *dev)
{
struct scsi_disk *sdkp;
+ dev_t devt;
sdkp = dev_get_drvdata(dev);
+ devt = disk_devt(sdkp->disk);
scsi_autopm_get_device(sdkp->device);
async_synchronize_full_domain(&scsi_sd_probe_domain);
@@ -2972,6 +3011,9 @@ static int sd_remove(struct device *dev)
del_gendisk(sdkp->disk);
sd_shutdown(dev);
+ blk_register_region(devt, SD_MINORS, NULL,
+ sd_default_probe, NULL, NULL);
+
mutex_lock(&sd_ref_mutex);
dev_set_drvdata(dev, NULL);
put_device(&sdkp->dev);
@@ -3021,8 +3063,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
if (!scsi_device_online(sdp))
return -ENODEV;
- res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+ res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
if (res) {
sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
sd_print_result(sdkp, res);
@@ -3115,9 +3157,13 @@ static int __init init_sd(void)
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
- for (i = 0; i < SD_MAJORS; i++)
- if (register_blkdev(sd_major(i), "sd") == 0)
- majors++;
+ for (i = 0; i < SD_MAJORS; i++) {
+ if (register_blkdev(sd_major(i), "sd") != 0)
+ continue;
+ majors++;
+ blk_register_region(sd_major(i), SD_MINORS, NULL,
+ sd_default_probe, NULL, NULL);
+ }
if (!majors)
return -ENODEV;
@@ -3176,8 +3222,10 @@ static void __exit exit_sd(void)
class_unregister(&sd_disk_class);
- for (i = 0; i < SD_MAJORS; i++)
+ for (i = 0; i < SD_MAJORS; i++) {
+ blk_unregister_region(sd_major(i), SD_MINORS);
unregister_blkdev(sd_major(i), "sd");
+ }
}
module_init(init_sd);
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 74a1e4c..7a049de 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -73,6 +73,7 @@ struct scsi_disk {
u8 protection_type;/* Data Integrity Field */
u8 provisioning_mode;
unsigned ATO : 1; /* state of disk ATO bit */
+ unsigned cache_override : 1; /* temp override of WCE,RCD */
unsigned WCE : 1; /* state of disk WCE bit */
unsigned RCD : 1; /* state of disk RCD bit, unused */
unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
@@ -83,6 +84,7 @@ struct scsi_disk {
unsigned lbpws : 1;
unsigned lbpws10 : 1;
unsigned lbpvpd : 1;
+ unsigned ws10 : 1;
unsigned ws16 : 1;
};
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 04998f3..6174ca4 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -93,14 +93,6 @@ static int sd_dif_type1_verify(struct blk_integrity_exchg *bix, csum_fn *fn)
if (sdt->app_tag == 0xffff)
return 0;
- /* Bad ref tag received from disk */
- if (sdt->ref_tag == 0xffffffff) {
- printk(KERN_ERR
- "%s: bad phys ref tag on sector %lu\n",
- bix->disk_name, (unsigned long)sector);
- return -EIO;
- }
-
if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
printk(KERN_ERR
"%s: ref tag error on sector %lu (rcvd %u)\n",
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index be2c9a6..df5e961 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -35,6 +35,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <linux/aio.h>
#include <linux/errno.h>
#include <linux/mtio.h>
#include <linux/ioctl.h>
@@ -1391,24 +1392,23 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
return ERR_PTR(-ENOMEM);
}
- if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) {
- printk(KERN_WARNING "idr expansion Sg_device failure\n");
- error = -ENOMEM;
- goto out;
- }
-
+ idr_preload(GFP_KERNEL);
write_lock_irqsave(&sg_index_lock, iflags);
- error = idr_get_new(&sg_index_idr, sdp, &k);
- if (error) {
- write_unlock_irqrestore(&sg_index_lock, iflags);
- printk(KERN_WARNING "idr allocation Sg_device failure: %d\n",
- error);
- goto out;
+ error = idr_alloc(&sg_index_idr, sdp, 0, SG_MAX_DEVS, GFP_NOWAIT);
+ if (error < 0) {
+ if (error == -ENOSPC) {
+ sdev_printk(KERN_WARNING, scsidp,
+ "Unable to attach sg device type=%d, minor number exceeds %d\n",
+ scsidp->type, SG_MAX_DEVS - 1);
+ error = -ENODEV;
+ } else {
+ printk(KERN_WARNING
+ "idr allocation Sg_device failure: %d\n", error);
+ }
+ goto out_unlock;
}
-
- if (unlikely(k >= SG_MAX_DEVS))
- goto overflow;
+ k = error;
SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k));
sprintf(disk->disk_name, "sg%d", k);
@@ -1420,25 +1420,17 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
sdp->sg_tablesize = queue_max_segments(q);
sdp->index = k;
kref_init(&sdp->d_ref);
+ error = 0;
+out_unlock:
write_unlock_irqrestore(&sg_index_lock, iflags);
+ idr_preload_end();
- error = 0;
- out:
if (error) {
kfree(sdp);
return ERR_PTR(error);
}
return sdp;
-
- overflow:
- idr_remove(&sg_index_idr, k);
- write_unlock_irqrestore(&sg_index_lock, iflags);
- sdev_printk(KERN_WARNING, scsidp,
- "Unable to attach sg device type=%d, minor "
- "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1);
- error = -ENODEV;
- goto out;
}
static int
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 3a9d85c..a464d95 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -226,7 +226,7 @@ static struct scsi_host_template sgiwd93_template = {
.use_clustering = DISABLE_CLUSTERING,
};
-static int __devinit sgiwd93_probe(struct platform_device *pdev)
+static int sgiwd93_probe(struct platform_device *pdev)
{
struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
unsigned char *wdregs = pd->wdregs;
@@ -312,7 +312,7 @@ static int __exit sgiwd93_remove(struct platform_device *pdev)
static struct platform_driver sgiwd93_driver = {
.probe = sgiwd93_probe,
- .remove = __devexit_p(sgiwd93_remove),
+ .remove = sgiwd93_remove,
.driver = {
.name = "sgiwd93",
.owner = THIS_MODULE,
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index a318264..3b3b56f 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -94,9 +94,9 @@ static struct scsi_host_template sim710_driver_template = {
.module = THIS_MODULE,
};
-static __devinit int
-sim710_probe_common(struct device *dev, unsigned long base_addr,
- int irq, int clock, int differential, int scsi_id)
+static int sim710_probe_common(struct device *dev, unsigned long base_addr,
+ int irq, int clock, int differential,
+ int scsi_id)
{
struct Scsi_Host * host = NULL;
struct NCR_700_Host_Parameters *hostdata =
@@ -153,8 +153,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
return -ENODEV;
}
-static __devexit int
-sim710_device_remove(struct device *dev)
+static int sim710_device_remove(struct device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata =
@@ -221,7 +220,7 @@ static struct eisa_driver sim710_eisa_driver = {
.driver = {
.name = "sim710",
.probe = sim710_eisa_probe,
- .remove = __devexit_p(sim710_device_remove),
+ .remove = sim710_device_remove,
},
};
#endif /* CONFIG_EISA */
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index cf51432..52d54e7 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -65,7 +65,7 @@ static struct scsi_host_template snirm710_template = {
.module = THIS_MODULE,
};
-static int __devinit snirm710_probe(struct platform_device *dev)
+static int snirm710_probe(struct platform_device *dev)
{
unsigned long base;
struct NCR_700_Host_Parameters *hostdata;
@@ -134,7 +134,7 @@ static int __exit snirm710_driver_remove(struct platform_device *dev)
static struct platform_driver snirm710_driver = {
.probe = snirm710_probe,
- .remove = __devexit_p(snirm710_driver_remove),
+ .remove = snirm710_driver_remove,
.driver = {
.name = "snirm_53c710",
.owner = THIS_MODULE,
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 5fc97d2..119d67f 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -45,6 +45,7 @@
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -79,6 +80,11 @@ static DEFINE_MUTEX(sr_mutex);
static int sr_probe(struct device *);
static int sr_remove(struct device *);
static int sr_done(struct scsi_cmnd *);
+static int sr_runtime_suspend(struct device *dev);
+
+static struct dev_pm_ops sr_pm_ops = {
+ .runtime_suspend = sr_runtime_suspend,
+};
static struct scsi_driver sr_template = {
.owner = THIS_MODULE,
@@ -86,6 +92,7 @@ static struct scsi_driver sr_template = {
.name = "sr",
.probe = sr_probe,
.remove = sr_remove,
+ .pm = &sr_pm_ops,
},
.done = sr_done,
};
@@ -131,6 +138,16 @@ static inline struct scsi_cd *scsi_cd(struct gendisk *disk)
return container_of(disk->private_data, struct scsi_cd, driver);
}
+static int sr_runtime_suspend(struct device *dev)
+{
+ struct scsi_cd *cd = dev_get_drvdata(dev);
+
+ if (cd->media_present)
+ return -EBUSY;
+ else
+ return 0;
+}
+
/*
* The get and put routines for the struct scsi_cd. Note this entity
* has a scsi_device pointer and owns a reference to this.
@@ -146,7 +163,8 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
kref_get(&cd->kref);
if (scsi_device_get(cd->device))
goto out_put;
- goto out;
+ if (!scsi_autopm_get_device(cd->device))
+ goto out;
out_put:
kref_put(&cd->kref, sr_kref_release);
@@ -162,6 +180,7 @@ static void scsi_cd_put(struct scsi_cd *cd)
mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
+ scsi_autopm_put_device(sdev);
scsi_device_put(sdev);
mutex_unlock(&sr_ref_mutex);
}
@@ -522,14 +541,13 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode)
return ret;
}
-static int sr_block_release(struct gendisk *disk, fmode_t mode)
+static void sr_block_release(struct gendisk *disk, fmode_t mode)
{
struct scsi_cd *cd = scsi_cd(disk);
mutex_lock(&sr_mutex);
cdrom_release(&cd->cdi, mode);
scsi_cd_put(cd);
mutex_unlock(&sr_mutex);
- return 0;
}
static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
@@ -540,6 +558,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
void __user *argp = (void __user *)arg;
int ret;
+ scsi_autopm_get_device(cd->device);
+
mutex_lock(&sr_mutex);
/*
@@ -571,6 +591,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
out:
mutex_unlock(&sr_mutex);
+ scsi_autopm_put_device(cd->device);
return ret;
}
@@ -578,7 +599,17 @@ static unsigned int sr_block_check_events(struct gendisk *disk,
unsigned int clearing)
{
struct scsi_cd *cd = scsi_cd(disk);
- return cdrom_check_events(&cd->cdi, clearing);
+ unsigned int ret;
+
+ if (atomic_read(&cd->device->disk_events_disable_depth) == 0) {
+ scsi_autopm_get_device(cd->device);
+ ret = cdrom_check_events(&cd->cdi, clearing);
+ scsi_autopm_put_device(cd->device);
+ } else {
+ ret = 0;
+ }
+
+ return ret;
}
static int sr_block_revalidate_disk(struct gendisk *disk)
@@ -586,12 +617,16 @@ static int sr_block_revalidate_disk(struct gendisk *disk)
struct scsi_cd *cd = scsi_cd(disk);
struct scsi_sense_hdr sshdr;
+ scsi_autopm_get_device(cd->device);
+
/* if the unit is not ready, nothing more to do */
if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
- return 0;
+ goto out;
sr_cd_check(&cd->cdi);
get_sectorsize(cd);
+out:
+ scsi_autopm_put_device(cd->device);
return 0;
}
@@ -718,6 +753,8 @@ static int sr_probe(struct device *dev)
sdev_printk(KERN_DEBUG, sdev,
"Attached scsi CD-ROM %s\n", cd->cdi.name);
+ scsi_autopm_put_device(cd->device);
+
return 0;
fail_put:
@@ -965,6 +1002,8 @@ static int sr_remove(struct device *dev)
{
struct scsi_cd *cd = dev_get_drvdata(dev);
+ scsi_autopm_get_device(cd->device);
+
blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
del_gendisk(cd->disk);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 98156a9..2a32036 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -977,7 +977,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
struct st_modedef *STm;
struct st_partstat *STps;
char *name = tape_name(STp);
- struct inode *inode = filp->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(filp);
int mode = TAPE_MODE(inode);
STp->ready = ST_READY;
@@ -4076,7 +4076,7 @@ static int st_probe(struct device *dev)
struct st_modedef *STm;
struct st_partstat *STps;
struct st_buffer *buffer;
- int i, dev_num, error;
+ int i, error;
char *stp;
if (SDp->type != TYPE_TAPE)
@@ -4112,6 +4112,10 @@ static int st_probe(struct device *dev)
tpnt->disk = disk;
disk->private_data = &tpnt->driver;
disk->queue = SDp->request_queue;
+ /* SCSI tape doesn't register this gendisk via add_disk(). Manually
+ * take queue reference that release_disk() expects. */
+ if (!blk_get_queue(disk->queue))
+ goto out_put_disk;
tpnt->driver = &st_template;
tpnt->device = SDp;
@@ -4178,27 +4182,17 @@ static int st_probe(struct device *dev)
tpnt->blksize_changed = 0;
mutex_init(&tpnt->lock);
- if (!idr_pre_get(&st_index_idr, GFP_KERNEL)) {
- pr_warn("st: idr expansion failed\n");
- error = -ENOMEM;
- goto out_put_disk;
- }
-
+ idr_preload(GFP_KERNEL);
spin_lock(&st_index_lock);
- error = idr_get_new(&st_index_idr, tpnt, &dev_num);
+ error = idr_alloc(&st_index_idr, tpnt, 0, ST_MAX_TAPES + 1, GFP_NOWAIT);
spin_unlock(&st_index_lock);
- if (error) {
+ idr_preload_end();
+ if (error < 0) {
pr_warn("st: idr allocation failed: %d\n", error);
- goto out_put_disk;
+ goto out_put_queue;
}
-
- if (dev_num > ST_MAX_TAPES) {
- pr_err("st: Too many tape devices (max. %d).\n", ST_MAX_TAPES);
- goto out_put_index;
- }
-
- tpnt->index = dev_num;
- sprintf(disk->disk_name, "st%d", dev_num);
+ tpnt->index = error;
+ sprintf(disk->disk_name, "st%d", tpnt->index);
dev_set_drvdata(dev, tpnt);
@@ -4218,10 +4212,11 @@ static int st_probe(struct device *dev)
out_remove_devs:
remove_cdevs(tpnt);
-out_put_index:
spin_lock(&st_index_lock);
- idr_remove(&st_index_idr, dev_num);
+ idr_remove(&st_index_idr, tpnt->index);
spin_unlock(&st_index_lock);
+out_put_queue:
+ blk_put_queue(disk->queue);
out_put_disk:
put_disk(disk);
kfree(tpnt);
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 606215e..325c31c 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -1540,8 +1540,7 @@ static void stex_free_irq(struct st_hba *hba)
pci_disable_msi(pdev);
}
-static int __devinit
-stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct st_hba *hba;
struct Scsi_Host *host;
@@ -1815,7 +1814,7 @@ static struct pci_driver stex_pci_driver = {
.name = DRV_NAME,
.id_table = stex_pci_tbl,
.probe = stex_probe,
- .remove = __devexit_p(stex_remove),
+ .remove = stex_remove,
.shutdown = stex_shutdown,
};
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 0144078..83ec1aa 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -55,10 +55,15 @@
* V1 RC < 2008/1/31: 1.0
* V1 RC > 2008/1/31: 2.0
* Win7: 4.2
+ * Win8: 5.1
*/
-#define VMSTOR_CURRENT_MAJOR 4
-#define VMSTOR_CURRENT_MINOR 2
+
+#define VMSTOR_WIN7_MAJOR 4
+#define VMSTOR_WIN7_MINOR 2
+
+#define VMSTOR_WIN8_MAJOR 5
+#define VMSTOR_WIN8_MINOR 1
/* Packet structure describing virtual storage requests. */
@@ -74,18 +79,103 @@ enum vstor_packet_operation {
VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9,
VSTOR_OPERATION_QUERY_PROPERTIES = 10,
VSTOR_OPERATION_ENUMERATE_BUS = 11,
- VSTOR_OPERATION_MAXIMUM = 11
+ VSTOR_OPERATION_FCHBA_DATA = 12,
+ VSTOR_OPERATION_CREATE_SUB_CHANNELS = 13,
+ VSTOR_OPERATION_MAXIMUM = 13
+};
+
+/*
+ * WWN packet for Fibre Channel HBA
+ */
+
+struct hv_fc_wwn_packet {
+ bool primary_active;
+ u8 reserved1;
+ u8 reserved2;
+ u8 primary_port_wwn[8];
+ u8 primary_node_wwn[8];
+ u8 secondary_port_wwn[8];
+ u8 secondary_node_wwn[8];
};
+
+
+/*
+ * SRB Flag Bits
+ */
+
+#define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002
+#define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004
+#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008
+#define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010
+#define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020
+#define SRB_FLAGS_DATA_IN 0x00000040
+#define SRB_FLAGS_DATA_OUT 0x00000080
+#define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000
+#define SRB_FLAGS_UNSPECIFIED_DIRECTION (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)
+#define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100
+#define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200
+#define SRB_FLAGS_FREE_SENSE_BUFFER 0x00000400
+
+/*
+ * This flag indicates the request is part of the workflow for processing a D3.
+ */
+#define SRB_FLAGS_D3_PROCESSING 0x00000800
+#define SRB_FLAGS_IS_ACTIVE 0x00010000
+#define SRB_FLAGS_ALLOCATED_FROM_ZONE 0x00020000
+#define SRB_FLAGS_SGLIST_FROM_POOL 0x00040000
+#define SRB_FLAGS_BYPASS_LOCKED_QUEUE 0x00080000
+#define SRB_FLAGS_NO_KEEP_AWAKE 0x00100000
+#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE 0x00200000
+#define SRB_FLAGS_PORT_DRIVER_SENSEHASPORT 0x00400000
+#define SRB_FLAGS_DONT_START_NEXT_PACKET 0x00800000
+#define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000
+#define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000
+
+
/*
* Platform neutral description of a scsi request -
* this remains the same across the write regardless of 32/64 bit
* note: it's patterned off the SCSI_PASS_THROUGH structure
*/
#define STORVSC_MAX_CMD_LEN 0x10
-#define STORVSC_SENSE_BUFFER_SIZE 0x12
+
+#define POST_WIN7_STORVSC_SENSE_BUFFER_SIZE 0x14
+#define PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE 0x12
+
+#define STORVSC_SENSE_BUFFER_SIZE 0x14
#define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14
+/*
+ * Sense buffer size changed in win8; have a run-time
+ * variable to track the size we should use.
+ */
+static int sense_buffer_size;
+
+/*
+ * The size of the vmscsi_request has changed in win8. The
+ * additional size is because of new elements added to the
+ * structure. These elements are valid only when we are talking
+ * to a win8 host.
+ * Track the correction to size we need to apply.
+ */
+
+static int vmscsi_size_delta;
+static int vmstor_current_major;
+static int vmstor_current_minor;
+
+struct vmscsi_win8_extension {
+ /*
+ * The following were added in Windows 8
+ */
+ u16 reserve;
+ u8 queue_tag;
+ u8 queue_action;
+ u32 srb_flags;
+ u32 time_out_value;
+ u32 queue_sort_ey;
+} __packed;
+
struct vmscsi_request {
u16 length;
u8 srb_status;
@@ -108,6 +198,11 @@ struct vmscsi_request {
u8 sense_data[STORVSC_SENSE_BUFFER_SIZE];
u8 reserved_array[STORVSC_MAX_BUF_LEN_WITH_PADDING];
};
+ /*
+ * The following was added in win8.
+ */
+ struct vmscsi_win8_extension win8_extension;
+
} __attribute((packed));
@@ -115,22 +210,18 @@ struct vmscsi_request {
* This structure is sent during the intialization phase to get the different
* properties of the channel.
*/
+
+#define STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL 0x1
+
struct vmstorage_channel_properties {
- u16 protocol_version;
- u8 path_id;
- u8 target_id;
+ u32 reserved;
+ u16 max_channel_cnt;
+ u16 reserved1;
- /* Note: port number is only really known on the client side */
- u32 port_number;
- u32 flags;
+ u32 flags;
u32 max_transfer_bytes;
- /*
- * This id is unique for each channel and will correspond with
- * vendor specific data in the inquiry data.
- */
-
- u64 unique_id;
+ u64 reserved2;
} __packed;
/* This structure is sent during the storage protocol negotiations. */
@@ -175,6 +266,15 @@ struct vstor_packet {
/* Used during version negotiations. */
struct vmstorage_protocol_version version;
+
+ /* Fibre channel address packet */
+ struct hv_fc_wwn_packet wwn_packet;
+
+ /* Number of sub-channels to create */
+ u16 sub_channel_count;
+
+ /* This will be the maximum of the union members */
+ u8 buffer[0x34];
};
} __packed;
@@ -201,6 +301,7 @@ enum storvsc_request_type {
#define SRB_STATUS_AUTOSENSE_VALID 0x80
#define SRB_STATUS_INVALID_LUN 0x20
#define SRB_STATUS_SUCCESS 0x01
+#define SRB_STATUS_ABORTED 0x02
#define SRB_STATUS_ERROR 0x04
/*
@@ -220,7 +321,14 @@ static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
module_param(storvsc_ringbuffer_size, int, S_IRUGO);
MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
-#define STORVSC_MAX_IO_REQUESTS 128
+/*
+ * Timeout in seconds for all devices managed by this driver.
+ */
+static int storvsc_timeout = 180;
+
+#define STORVSC_MAX_IO_REQUESTS 200
+
+static void storvsc_on_channel_callback(void *context);
/*
* In Hyper-V, each port/path/target maps to 1 scsi host adapter. In
@@ -258,6 +366,7 @@ struct storvsc_device {
bool destroy;
bool drain_notify;
+ bool open_sub_channel;
atomic_t num_outstanding_req;
struct Scsi_Host *host;
@@ -295,6 +404,25 @@ struct storvsc_scan_work {
uint lun;
};
+static void storvsc_device_scan(struct work_struct *work)
+{
+ struct storvsc_scan_work *wrk;
+ uint lun;
+ struct scsi_device *sdev;
+
+ wrk = container_of(work, struct storvsc_scan_work, work);
+ lun = wrk->lun;
+
+ sdev = scsi_device_lookup(wrk->host, 0, 0, lun);
+ if (!sdev)
+ goto done;
+ scsi_rescan_device(&sdev->sdev_gendev);
+ scsi_device_put(sdev);
+
+done:
+ kfree(wrk);
+}
+
static void storvsc_bus_scan(struct work_struct *work)
{
struct storvsc_scan_work *wrk;
@@ -467,6 +595,7 @@ static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
if (!bounce_sgl)
return NULL;
+ sg_init_table(bounce_sgl, num_pages);
for (i = 0; i < num_pages; i++) {
page_buf = alloc_page(GFP_ATOMIC);
if (!page_buf)
@@ -629,12 +758,104 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
return total_copied;
}
+static void handle_sc_creation(struct vmbus_channel *new_sc)
+{
+ struct hv_device *device = new_sc->primary_channel->device_obj;
+ struct storvsc_device *stor_device;
+ struct vmstorage_channel_properties props;
+
+ stor_device = get_out_stor_device(device);
+ if (!stor_device)
+ return;
+
+ if (stor_device->open_sub_channel == false)
+ return;
+
+ memset(&props, 0, sizeof(struct vmstorage_channel_properties));
+
+ vmbus_open(new_sc,
+ storvsc_ringbuffer_size,
+ storvsc_ringbuffer_size,
+ (void *)&props,
+ sizeof(struct vmstorage_channel_properties),
+ storvsc_on_channel_callback, new_sc);
+}
+
+static void handle_multichannel_storage(struct hv_device *device, int max_chns)
+{
+ struct storvsc_device *stor_device;
+ int num_cpus = num_online_cpus();
+ int num_sc;
+ struct storvsc_cmd_request *request;
+ struct vstor_packet *vstor_packet;
+ int ret, t;
+
+ num_sc = ((max_chns > num_cpus) ? num_cpus : max_chns);
+ stor_device = get_out_stor_device(device);
+ if (!stor_device)
+ return;
+
+ request = &stor_device->init_request;
+ vstor_packet = &request->vstor_packet;
+
+ stor_device->open_sub_channel = true;
+ /*
+ * Establish a handler for dealing with subchannels.
+ */
+ vmbus_set_sc_create_callback(device->channel, handle_sc_creation);
+
+ /*
+ * Check to see if sub-channels have already been created. This
+ * can happen when this driver is re-loaded after unloading.
+ */
+
+ if (vmbus_are_subchannels_present(device->channel))
+ return;
+
+ stor_device->open_sub_channel = false;
+ /*
+ * Request the host to create sub-channels.
+ */
+ memset(request, 0, sizeof(struct storvsc_cmd_request));
+ init_completion(&request->wait_event);
+ vstor_packet->operation = VSTOR_OPERATION_CREATE_SUB_CHANNELS;
+ vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+ vstor_packet->sub_channel_count = num_sc;
+
+ ret = vmbus_sendpacket(device->channel, vstor_packet,
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
+ (unsigned long)request,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+
+ if (ret != 0)
+ return;
+
+ t = wait_for_completion_timeout(&request->wait_event, 10*HZ);
+ if (t == 0)
+ return;
+
+ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
+ vstor_packet->status != 0)
+ return;
+
+ /*
+ * Now that we created the sub-channels, invoke the check; this
+ * may trigger the callback.
+ */
+ stor_device->open_sub_channel = true;
+ vmbus_are_subchannels_present(device->channel);
+}
+
static int storvsc_channel_init(struct hv_device *device)
{
struct storvsc_device *stor_device;
struct storvsc_cmd_request *request;
struct vstor_packet *vstor_packet;
int ret, t;
+ int max_chns;
+ bool process_sub_channels = false;
stor_device = get_out_stor_device(device);
if (!stor_device)
@@ -653,7 +874,8 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = vmbus_sendpacket(device->channel, vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -677,7 +899,7 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
vstor_packet->version.major_minor =
- storvsc_get_version(VMSTOR_CURRENT_MAJOR, VMSTOR_CURRENT_MINOR);
+ storvsc_get_version(vmstor_current_major, vmstor_current_minor);
/*
* The revision number is only used in Windows; set it to 0.
@@ -685,7 +907,8 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->version.revision = 0;
ret = vmbus_sendpacket(device->channel, vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -706,11 +929,10 @@ static int storvsc_channel_init(struct hv_device *device)
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
- vstor_packet->storage_channel_properties.port_number =
- stor_device->port_number;
ret = vmbus_sendpacket(device->channel, vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -728,16 +950,26 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->status != 0)
goto cleanup;
- stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
- stor_device->target_id
- = vstor_packet->storage_channel_properties.target_id;
+ /*
+ * Check to see if multi-channel support is there.
+ * Hosts that implement protocol version of 5.1 and above
+ * support multi-channel.
+ */
+ max_chns = vstor_packet->storage_channel_properties.max_channel_cnt;
+ if ((vmbus_proto_version != VERSION_WIN7) &&
+ (vmbus_proto_version != VERSION_WS2008)) {
+ if (vstor_packet->storage_channel_properties.flags &
+ STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL)
+ process_sub_channels = true;
+ }
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = vmbus_sendpacket(device->channel, vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -755,11 +987,74 @@ static int storvsc_channel_init(struct hv_device *device)
vstor_packet->status != 0)
goto cleanup;
+ if (process_sub_channels)
+ handle_multichannel_storage(device, max_chns);
+
cleanup:
return ret;
}
+static void storvsc_handle_error(struct vmscsi_request *vm_srb,
+ struct scsi_cmnd *scmnd,
+ struct Scsi_Host *host,
+ u8 asc, u8 ascq)
+{
+ struct storvsc_scan_work *wrk;
+ void (*process_err_fn)(struct work_struct *work);
+ bool do_work = false;
+
+ switch (vm_srb->srb_status) {
+ case SRB_STATUS_ERROR:
+ /*
+ * If there is an error; offline the device since all
+ * error recovery strategies would have already been
+ * deployed on the host side. However, if the command
+ * were a pass-through command deal with it appropriately.
+ */
+ switch (scmnd->cmnd[0]) {
+ case ATA_16:
+ case ATA_12:
+ set_host_byte(scmnd, DID_PASSTHROUGH);
+ break;
+ default:
+ set_host_byte(scmnd, DID_TARGET_FAILURE);
+ }
+ break;
+ case SRB_STATUS_INVALID_LUN:
+ do_work = true;
+ process_err_fn = storvsc_remove_lun;
+ break;
+ case (SRB_STATUS_ABORTED | SRB_STATUS_AUTOSENSE_VALID):
+ if ((asc == 0x2a) && (ascq == 0x9)) {
+ do_work = true;
+ process_err_fn = storvsc_device_scan;
+ /*
+ * Retry the I/O that trigerred this.
+ */
+ set_host_byte(scmnd, DID_REQUEUE);
+ }
+ break;
+ }
+
+ if (!do_work)
+ return;
+
+ /*
+ * We need to schedule work to process this error; schedule it.
+ */
+ wrk = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC);
+ if (!wrk) {
+ set_host_byte(scmnd, DID_TARGET_FAILURE);
+ return;
+ }
+
+ wrk->host = host;
+ wrk->lun = vm_srb->lun;
+ INIT_WORK(&wrk->work, process_err_fn);
+ schedule_work(&wrk->work);
+}
+
static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
{
@@ -768,8 +1063,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
void (*scsi_done_fn)(struct scsi_cmnd *);
struct scsi_sense_hdr sense_hdr;
struct vmscsi_request *vm_srb;
- struct storvsc_scan_work *wrk;
struct stor_mem_pools *memp = scmnd->device->hostdata;
+ struct Scsi_Host *host;
+ struct storvsc_device *stor_dev;
+ struct hv_device *dev = host_dev->dev;
+
+ stor_dev = get_in_stor_device(dev);
+ host = stor_dev->host;
vm_srb = &cmd_request->vstor_packet.vm_srb;
if (cmd_request->bounce_sgl_count) {
@@ -782,55 +1082,18 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
cmd_request->bounce_sgl_count);
}
- /*
- * If there is an error; offline the device since all
- * error recovery strategies would have already been
- * deployed on the host side. However, if the command
- * were a pass-through command deal with it appropriately.
- */
scmnd->result = vm_srb->scsi_status;
- if (vm_srb->srb_status == SRB_STATUS_ERROR) {
- switch (scmnd->cmnd[0]) {
- case ATA_16:
- case ATA_12:
- set_host_byte(scmnd, DID_PASSTHROUGH);
- break;
- default:
- set_host_byte(scmnd, DID_TARGET_FAILURE);
- }
- }
-
-
- /*
- * If the LUN is invalid; remove the device.
- */
- if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
- struct storvsc_device *stor_dev;
- struct hv_device *dev = host_dev->dev;
- struct Scsi_Host *host;
-
- stor_dev = get_in_stor_device(dev);
- host = stor_dev->host;
-
- wrk = kmalloc(sizeof(struct storvsc_scan_work),
- GFP_ATOMIC);
- if (!wrk) {
- scmnd->result = DID_TARGET_FAILURE << 16;
- } else {
- wrk->host = host;
- wrk->lun = vm_srb->lun;
- INIT_WORK(&wrk->work, storvsc_remove_lun);
- schedule_work(&wrk->work);
- }
- }
-
if (scmnd->result) {
if (scsi_normalize_sense(scmnd->sense_buffer,
SCSI_SENSE_BUFFERSIZE, &sense_hdr))
scsi_print_sense_hdr("storvsc", &sense_hdr);
}
+ if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
+ storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc,
+ sense_hdr.ascq);
+
scsi_set_resid(scmnd,
cmd_request->data_buffer.len -
vm_srb->data_transfer_length);
@@ -948,7 +1211,8 @@ static void storvsc_on_receive(struct hv_device *device,
static void storvsc_on_channel_callback(void *context)
{
- struct hv_device *device = (struct hv_device *)context;
+ struct vmbus_channel *channel = (struct vmbus_channel *)context;
+ struct hv_device *device;
struct storvsc_device *stor_device;
u32 bytes_recvd;
u64 request_id;
@@ -956,14 +1220,19 @@ static void storvsc_on_channel_callback(void *context)
struct storvsc_cmd_request *request;
int ret;
+ if (channel->primary_channel != NULL)
+ device = channel->primary_channel->device_obj;
+ else
+ device = channel->device_obj;
stor_device = get_in_stor_device(device);
if (!stor_device)
return;
do {
- ret = vmbus_recvpacket(device->channel, packet,
- ALIGN(sizeof(struct vstor_packet), 8),
+ ret = vmbus_recvpacket(channel, packet,
+ ALIGN((sizeof(struct vstor_packet) -
+ vmscsi_size_delta), 8),
&bytes_recvd, &request_id);
if (ret == 0 && bytes_recvd > 0) {
@@ -974,7 +1243,8 @@ static void storvsc_on_channel_callback(void *context)
(request == &stor_device->reset_request)) {
memcpy(&request->vstor_packet, packet,
- sizeof(struct vstor_packet));
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta));
complete(&request->wait_event);
} else {
storvsc_on_receive(device,
@@ -1001,7 +1271,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
ring_size,
(void *)&props,
sizeof(struct vmstorage_channel_properties),
- storvsc_on_channel_callback, device);
+ storvsc_on_channel_callback, device->channel);
if (ret != 0)
return ret;
@@ -1053,6 +1323,7 @@ static int storvsc_do_io(struct hv_device *device,
{
struct storvsc_device *stor_device;
struct vstor_packet *vstor_packet;
+ struct vmbus_channel *outgoing_channel;
int ret = 0;
vstor_packet = &request->vstor_packet;
@@ -1063,14 +1334,20 @@ static int storvsc_do_io(struct hv_device *device,
request->device = device;
+ /*
+ * Select an an appropriate channel to send the request out.
+ */
+
+ outgoing_channel = vmbus_get_outgoing_channel(device->channel);
vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
- vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
+ vstor_packet->vm_srb.length = (sizeof(struct vmscsi_request) -
+ vmscsi_size_delta);
- vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE;
+ vstor_packet->vm_srb.sense_info_length = sense_buffer_size;
vstor_packet->vm_srb.data_transfer_length =
@@ -1079,14 +1356,16 @@ static int storvsc_do_io(struct hv_device *device,
vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
if (request->data_buffer.len) {
- ret = vmbus_sendpacket_multipagebuffer(device->channel,
+ ret = vmbus_sendpacket_multipagebuffer(outgoing_channel,
&request->data_buffer,
vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)request);
} else {
ret = vmbus_sendpacket(device->channel, vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -1155,6 +1434,10 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
+ blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ));
+
+ sdevice->no_write_same = 1;
+
return 0;
}
@@ -1206,7 +1489,8 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
vstor_packet->vm_srb.path_id = stor_device->path_id;
ret = vmbus_sendpacket(device->channel, vstor_packet,
- sizeof(struct vstor_packet),
+ (sizeof(struct vstor_packet) -
+ vmscsi_size_delta),
(unsigned long)&stor_device->reset_request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
@@ -1237,6 +1521,8 @@ static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
u8 scsi_op = scmnd->cmnd[0];
switch (scsi_op) {
+ /* the host does not handle WRITE_SAME, log accident usage */
+ case WRITE_SAME:
/*
* smartd sends this command and the host does not handle
* this. So, don't send it.
@@ -1289,18 +1575,28 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
scmnd->host_scribble = (unsigned char *)cmd_request;
vm_srb = &cmd_request->vstor_packet.vm_srb;
+ vm_srb->win8_extension.time_out_value = 60;
/* Build the SRB */
switch (scmnd->sc_data_direction) {
case DMA_TO_DEVICE:
vm_srb->data_in = WRITE_TYPE;
+ vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT;
+ vm_srb->win8_extension.srb_flags |=
+ (SRB_FLAGS_QUEUE_ACTION_ENABLE |
+ SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
break;
case DMA_FROM_DEVICE:
vm_srb->data_in = READ_TYPE;
+ vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN;
+ vm_srb->win8_extension.srb_flags |=
+ (SRB_FLAGS_QUEUE_ACTION_ENABLE |
+ SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
break;
default:
vm_srb->data_in = UNKNOWN_TYPE;
+ vm_srb->win8_extension.srb_flags = 0;
break;
}
@@ -1406,17 +1702,23 @@ static struct scsi_host_template scsi_driver = {
enum {
SCSI_GUID,
IDE_GUID,
+ SFC_GUID,
};
static const struct hv_vmbus_device_id id_table[] = {
/* SCSI guid */
- { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
- 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f)
- .driver_data = SCSI_GUID },
+ { HV_SCSI_GUID,
+ .driver_data = SCSI_GUID
+ },
/* IDE guid */
- { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
- 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5)
- .driver_data = IDE_GUID },
+ { HV_IDE_GUID,
+ .driver_data = IDE_GUID
+ },
+ /* Fibre Channel GUID */
+ {
+ HV_SYNTHFC_GUID,
+ .driver_data = SFC_GUID
+ },
{ },
};
@@ -1432,6 +1734,24 @@ static int storvsc_probe(struct hv_device *device,
int target = 0;
struct storvsc_device *stor_device;
+ /*
+ * Based on the windows host we are running on,
+ * set state to properly communicate with the host.
+ */
+
+ if (vmbus_proto_version == VERSION_WIN8) {
+ sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
+ vmscsi_size_delta = 0;
+ vmstor_current_major = VMSTOR_WIN8_MAJOR;
+ vmstor_current_minor = VMSTOR_WIN8_MINOR;
+ } else {
+ sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
+ vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
+ vmstor_current_major = VMSTOR_WIN7_MAJOR;
+ vmstor_current_minor = VMSTOR_WIN7_MINOR;
+ }
+
+
host = scsi_host_alloc(&scsi_driver,
sizeof(struct hv_host_device));
if (!host)
@@ -1451,6 +1771,7 @@ static int storvsc_probe(struct hv_device *device,
}
stor_device->destroy = false;
+ stor_device->open_sub_channel = false;
init_waitqueue_head(&stor_device->waiting_to_drain);
stor_device->device = device;
stor_device->host = host;
@@ -1541,7 +1862,8 @@ static int __init storvsc_drv_init(void)
max_outstanding_req_per_channel =
((storvsc_ringbuffer_size - PAGE_SIZE) /
ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
- sizeof(struct vstor_packet) + sizeof(u64),
+ sizeof(struct vstor_packet) + sizeof(u64) -
+ vmscsi_size_delta,
sizeof(u64)));
if (max_outstanding_req_per_channel <
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 7e12a2e..636bbe0 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -661,121 +661,94 @@ static void __init NCR5380_print_options (struct Scsi_Host *instance)
* Inputs : instance, pointer to this instance.
*/
-static void NCR5380_print_status (struct Scsi_Host *instance)
+static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
{
- char *pr_bfr;
- char *start;
- int len;
-
- NCR_PRINT(NDEBUG_ANY);
- NCR_PRINT_PHASE(NDEBUG_ANY);
-
- pr_bfr = (char *) __get_free_page(GFP_ATOMIC);
- if (!pr_bfr) {
- printk("NCR5380_print_status: no memory for print buffer\n");
- return;
- }
- len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
- pr_bfr[len] = 0;
- printk("\n%s\n", pr_bfr);
- free_page((unsigned long) pr_bfr);
+ int i, s;
+ unsigned char *command;
+ printk("scsi%d: destination target %d, lun %d\n",
+ H_NO(cmd), cmd->device->id, cmd->device->lun);
+ printk(KERN_CONT " command = ");
+ command = cmd->cmnd;
+ printk(KERN_CONT "%2d (0x%02x)", command[0], command[0]);
+ for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+ printk(KERN_CONT " %02x", command[i]);
+ printk("\n");
}
-
-/******************************************/
-/*
- * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
- *
- * Return the number of bytes read from or written
-*/
-
-#undef SPRINTF
-#define SPRINTF(fmt,args...) \
- do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
- pos += sprintf(pos, fmt , ## args); } while(0)
-static
-char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer,
- int length);
-
-static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
- char **start, off_t offset, int length, int inout)
+static void NCR5380_print_status(struct Scsi_Host *instance)
{
- char *pos = buffer;
- struct NCR5380_hostdata *hostdata;
- struct scsi_cmnd *ptr;
- unsigned long flags;
- off_t begin = 0;
-#define check_offset() \
- do { \
- if (pos - buffer < offset - begin) { \
- begin += pos - buffer; \
- pos = buffer; \
- } \
- } while (0)
-
- hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-
- if (inout) { /* Has data been written to the file ? */
- return(-ENOSYS); /* Currently this is a no-op */
- }
- SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
- check_offset();
- local_irq_save(flags);
- SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
- check_offset();
- if (!hostdata->connected)
- SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
- else
- pos = lprint_Scsi_Cmnd ((struct scsi_cmnd *) hostdata->connected,
- pos, buffer, length);
- SPRINTF("scsi%d: issue_queue\n", HOSTNO);
- check_offset();
- for (ptr = (struct scsi_cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr))
- {
- pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
- check_offset();
- }
-
- SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
- check_offset();
- for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr;
- ptr = NEXT(ptr)) {
- pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
- check_offset();
- }
+ struct NCR5380_hostdata *hostdata;
+ Scsi_Cmnd *ptr;
+ unsigned long flags;
+
+ NCR_PRINT(NDEBUG_ANY);
+ NCR_PRINT_PHASE(NDEBUG_ANY);
+
+ hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+ printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+ local_irq_save(flags);
+ printk("NCR5380: coroutine is%s running.\n",
+ main_running ? "" : "n't");
+ if (!hostdata->connected)
+ printk("scsi%d: no currently connected command\n", HOSTNO);
+ else
+ lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
+ printk("scsi%d: issue_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ lprint_Scsi_Cmnd(ptr);
+
+ printk("scsi%d: disconnected_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+ ptr = NEXT(ptr))
+ lprint_Scsi_Cmnd(ptr);
- local_irq_restore(flags);
- *start = buffer + (offset - begin);
- if (pos - buffer < offset - begin)
- return 0;
- else if (pos - buffer - (offset - begin) < length)
- return pos - buffer - (offset - begin);
- return length;
+ local_irq_restore(flags);
+ printk("\n");
}
-static char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer,
- int length)
+static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
{
- int i, s;
- unsigned char *command;
- SPRINTF("scsi%d: destination target %d, lun %d\n",
- H_NO(cmd), cmd->device->id, cmd->device->lun);
- SPRINTF(" command = ");
- command = cmd->cmnd;
- SPRINTF("%2d (0x%02x)", command[0], command[0]);
- for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
- SPRINTF(" %02x", command[i]);
- SPRINTF("\n");
- return pos;
+ int i, s;
+ unsigned char *command;
+ seq_printf(m, "scsi%d: destination target %d, lun %d\n",
+ H_NO(cmd), cmd->device->id, cmd->device->lun);
+ seq_printf(m, " command = ");
+ command = cmd->cmnd;
+ seq_printf(m, "%2d (0x%02x)", command[0], command[0]);
+ for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+ seq_printf(m, " %02x", command[i]);
+ seq_printf(m, "\n");
}
+static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+ struct NCR5380_hostdata *hostdata;
+ Scsi_Cmnd *ptr;
+ unsigned long flags;
+
+ hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+ seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+ local_irq_save(flags);
+ seq_printf(m, "NCR5380: coroutine is%s running.\n",
+ main_running ? "" : "n't");
+ if (!hostdata->connected)
+ seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
+ else
+ show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+ seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ show_Scsi_Cmnd(ptr, m);
+
+ seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
+ for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+ ptr = NEXT(ptr))
+ show_Scsi_Cmnd(ptr, m);
+
+ local_irq_restore(flags);
+ return 0;
+}
/*
* Function : void NCR5380_init (struct Scsi_Host *instance)
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 6e25889..e2c009b 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -626,6 +626,7 @@ static int sun3scsi_dma_finish(int write_flag)
#include "sun3_NCR5380.c"
static struct scsi_host_template driver_template = {
+ .show_info = sun3scsi_show_info,
.name = SUN3_SCSI_NAME,
.detect = sun3scsi_detect,
.release = sun3scsi_release,
diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h
index bcefd84..a8da9c7 100644
--- a/drivers/scsi/sun3_scsi.h
+++ b/drivers/scsi/sun3_scsi.h
@@ -100,7 +100,7 @@ static int sun3scsi_release (struct Scsi_Host *);
#define NCR5380_queue_command sun3scsi_queue_command
#define NCR5380_bus_reset sun3scsi_bus_reset
#define NCR5380_abort sun3scsi_abort
-#define NCR5380_proc_info sun3scsi_proc_info
+#define NCR5380_show_info sun3scsi_show_info
#define NCR5380_dma_xfer_len(i, cmd, phase) \
sun3scsi_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 0621037..534eb96 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -194,7 +194,7 @@ static const struct esp_driver_ops sun3x_esp_ops = {
.dma_error = sun3x_esp_dma_error,
};
-static int __devinit esp_sun3x_probe(struct platform_device *dev)
+static int esp_sun3x_probe(struct platform_device *dev)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
struct Scsi_Host *host;
@@ -268,7 +268,7 @@ fail:
return err;
}
-static int __devexit esp_sun3x_remove(struct platform_device *dev)
+static int esp_sun3x_remove(struct platform_device *dev)
{
struct esp *esp = dev_get_drvdata(&dev->dev);
unsigned int irq = esp->host->irq;
@@ -292,7 +292,7 @@ static int __devexit esp_sun3x_remove(struct platform_device *dev)
static struct platform_driver esp_sun3x_driver = {
.probe = esp_sun3x_probe,
- .remove = __devexit_p(esp_sun3x_remove),
+ .remove = esp_sun3x_remove,
.driver = {
.name = "sun3x_esp",
.owner = THIS_MODULE,
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index 676fe9a..f2e6845 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -43,8 +43,7 @@ enum dvma_rev {
dvmahme
};
-static int __devinit esp_sbus_setup_dma(struct esp *esp,
- struct platform_device *dma_of)
+static int esp_sbus_setup_dma(struct esp *esp, struct platform_device *dma_of)
{
esp->dma = dma_of;
@@ -79,7 +78,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp,
}
-static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
+static int esp_sbus_map_regs(struct esp *esp, int hme)
{
struct platform_device *op = esp->dev;
struct resource *res;
@@ -99,7 +98,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
return 0;
}
-static int __devinit esp_sbus_map_command_block(struct esp *esp)
+static int esp_sbus_map_command_block(struct esp *esp)
{
struct platform_device *op = esp->dev;
@@ -111,7 +110,7 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp)
return 0;
}
-static int __devinit esp_sbus_register_irq(struct esp *esp)
+static int esp_sbus_register_irq(struct esp *esp)
{
struct Scsi_Host *host = esp->host;
struct platform_device *op = esp->dev;
@@ -120,7 +119,7 @@ static int __devinit esp_sbus_register_irq(struct esp *esp)
return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
}
-static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
+static void esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
{
struct platform_device *op = esp->dev;
struct device_node *dp;
@@ -142,7 +141,7 @@ done:
esp->scsi_id_mask = (1 << esp->scsi_id);
}
-static void __devinit esp_get_differential(struct esp *esp)
+static void esp_get_differential(struct esp *esp)
{
struct platform_device *op = esp->dev;
struct device_node *dp;
@@ -154,7 +153,7 @@ static void __devinit esp_get_differential(struct esp *esp)
esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
}
-static void __devinit esp_get_clock_params(struct esp *esp)
+static void esp_get_clock_params(struct esp *esp)
{
struct platform_device *op = esp->dev;
struct device_node *bus_dp, *dp;
@@ -170,7 +169,7 @@ static void __devinit esp_get_clock_params(struct esp *esp)
esp->cfreq = fmhz;
}
-static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
+static void esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
{
struct device_node *dma_dp = dma_of->dev.of_node;
struct platform_device *op = esp->dev;
@@ -195,7 +194,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dm
esp->bursts = bursts;
}
-static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
+static void esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
{
esp_get_scsi_id(esp, espdma);
esp_get_differential(esp);
@@ -487,9 +486,8 @@ static const struct esp_driver_ops sbus_esp_ops = {
.dma_error = sbus_esp_dma_error,
};
-static int __devinit esp_sbus_probe_one(struct platform_device *op,
- struct platform_device *espdma,
- int hme)
+static int esp_sbus_probe_one(struct platform_device *op,
+ struct platform_device *espdma, int hme)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
struct Scsi_Host *host;
@@ -562,7 +560,7 @@ fail:
return err;
}
-static int __devinit esp_sbus_probe(struct platform_device *op)
+static int esp_sbus_probe(struct platform_device *op)
{
struct device_node *dma_node = NULL;
struct device_node *dp = op->dev.of_node;
@@ -585,7 +583,7 @@ static int __devinit esp_sbus_probe(struct platform_device *op)
return esp_sbus_probe_one(op, dma_of, hme);
}
-static int __devexit esp_sbus_remove(struct platform_device *op)
+static int esp_sbus_remove(struct platform_device *op)
{
struct esp *esp = dev_get_drvdata(&op->dev);
struct platform_device *dma_of = esp->dma;
@@ -639,7 +637,7 @@ static struct platform_driver esp_sbus_driver = {
.of_match_table = esp_match,
},
.probe = esp_sbus_probe,
- .remove = __devexit_p(esp_sbus_remove),
+ .remove = esp_sbus_remove,
};
static int __init sunesp_init(void)
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index ac4eca6..0b7819f 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -581,7 +581,7 @@ static int sym53c416_test(int base)
}
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4161), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index e2b8e68..bac55f7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1171,112 +1171,36 @@ printk("sym_user_command: data=%ld\n", uc->data);
#endif /* SYM_LINUX_USER_COMMAND_SUPPORT */
-#ifdef SYM_LINUX_USER_INFO_SUPPORT
-/*
- * Informations through the proc file system.
- */
-struct info_str {
- char *buffer;
- int length;
- int offset;
- int pos;
-};
-
-static void copy_mem_info(struct info_str *info, char *data, int len)
-{
- if (info->pos + len > info->length)
- len = info->length - info->pos;
-
- if (info->pos + len < info->offset) {
- info->pos += len;
- return;
- }
- if (info->pos < info->offset) {
- data += (info->offset - info->pos);
- len -= (info->offset - info->pos);
- }
-
- if (len > 0) {
- memcpy(info->buffer + info->pos, data, len);
- info->pos += len;
- }
-}
-
-static int copy_info(struct info_str *info, char *fmt, ...)
-{
- va_list args;
- char buf[81];
- int len;
-
- va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
- va_end(args);
-
- copy_mem_info(info, buf, len);
- return len;
-}
-
/*
* Copy formatted information into the input buffer.
*/
-static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len)
+static int sym_show_info(struct seq_file *m, struct Scsi_Host *shost)
{
+#ifdef SYM_LINUX_USER_INFO_SUPPORT
struct sym_data *sym_data = shost_priv(shost);
struct pci_dev *pdev = sym_data->pdev;
struct sym_hcb *np = sym_data->ncb;
- struct info_str info;
-
- info.buffer = ptr;
- info.length = len;
- info.offset = offset;
- info.pos = 0;
- copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
- "revision id 0x%x\n", np->s.chip_name,
- pdev->device, pdev->revision);
- copy_info(&info, "At PCI address %s, IRQ %u\n",
+ seq_printf(m, "Chip " NAME53C "%s, device id 0x%x, "
+ "revision id 0x%x\n", np->s.chip_name,
+ pdev->device, pdev->revision);
+ seq_printf(m, "At PCI address %s, IRQ %u\n",
pci_name(pdev), pdev->irq);
- copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
- (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
- np->maxwide ? "Wide" : "Narrow",
- np->minsync_dt ? ", DT capable" : "");
+ seq_printf(m, "Min. period factor %d, %s SCSI BUS%s\n",
+ (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
+ np->maxwide ? "Wide" : "Narrow",
+ np->minsync_dt ? ", DT capable" : "");
- copy_info(&info, "Max. started commands %d, "
- "max. commands per LUN %d\n",
- SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
+ seq_printf(m, "Max. started commands %d, "
+ "max. commands per LUN %d\n",
+ SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);
- return info.pos > info.offset? info.pos - info.offset : 0;
-}
-#endif /* SYM_LINUX_USER_INFO_SUPPORT */
-
-/*
- * Entry point of the scsi proc fs of the driver.
- * - func = 0 means read (returns adapter infos)
- * - func = 1 means write (not yet merget from sym53c8xx)
- */
-static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
- char **start, off_t offset, int length, int func)
-{
- int retv;
-
- if (func) {
-#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
- retv = sym_user_command(shost, buffer, length);
-#else
- retv = -EINVAL;
-#endif
- } else {
- if (start)
- *start = buffer;
-#ifdef SYM_LINUX_USER_INFO_SUPPORT
- retv = sym_host_info(shost, buffer, offset, length);
+ return 0;
#else
- retv = -EINVAL;
-#endif
- }
-
- return retv;
+ return -EINVAL;
+#endif /* SYM_LINUX_USER_INFO_SUPPORT */
}
+
#endif /* SYM_LINUX_PROC_INFO_SUPPORT */
/*
@@ -1284,8 +1208,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
* sym_free_resources() should be used instead of this function after calling
* sym_attach().
*/
-static void __devinit
-sym_iounmap_device(struct sym_device *device)
+static void sym_iounmap_device(struct sym_device *device)
{
if (device->s.ioaddr)
pci_iounmap(device->pdev, device->s.ioaddr);
@@ -1325,8 +1248,8 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev,
* If all is OK, install interrupt handling and
* start the timer daemon.
*/
-static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
- int unit, struct sym_device *dev)
+static struct Scsi_Host *sym_attach(struct scsi_host_template *tpnt, int unit,
+ struct sym_device *dev)
{
struct sym_data *sym_data;
struct sym_hcb *np = NULL;
@@ -1481,7 +1404,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* Detect and try to read SYMBIOS and TEKRAM NVRAM.
*/
#if SYM_CONF_NVRAM_SUPPORT
-static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
+static void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
{
devp->nvram = nvp;
nvp->type = 0;
@@ -1494,7 +1417,7 @@ static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
}
#endif /* SYM_CONF_NVRAM_SUPPORT */
-static int __devinit sym_check_supported(struct sym_device *device)
+static int sym_check_supported(struct sym_device *device)
{
struct sym_chip *chip;
struct pci_dev *pdev = device->pdev;
@@ -1531,7 +1454,7 @@ static int __devinit sym_check_supported(struct sym_device *device)
* Ignore Symbios chips controlled by various RAID controllers.
* These controllers set value 0x52414944 at RAM end - 16.
*/
-static int __devinit sym_check_raid(struct sym_device *device)
+static int sym_check_raid(struct sym_device *device)
{
unsigned int ram_size, ram_val;
@@ -1552,7 +1475,7 @@ static int __devinit sym_check_raid(struct sym_device *device)
return -ENODEV;
}
-static int __devinit sym_set_workarounds(struct sym_device *device)
+static int sym_set_workarounds(struct sym_device *device)
{
struct sym_chip *chip = &device->chip;
struct pci_dev *pdev = device->pdev;
@@ -1602,8 +1525,7 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
/*
* Map HBA registers and on-chip SRAM (if present).
*/
-static int __devinit
-sym_iomap_device(struct sym_device *device)
+static int sym_iomap_device(struct sym_device *device)
{
struct pci_dev *pdev = device->pdev;
struct pci_bus_region bus_addr;
@@ -1744,15 +1666,17 @@ static struct scsi_host_template sym2_template = {
.use_clustering = ENABLE_CLUSTERING,
.max_sectors = 0xFFFF,
#ifdef SYM_LINUX_PROC_INFO_SUPPORT
- .proc_info = sym53c8xx_proc_info,
+ .show_info = sym_show_info,
+#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
+ .write_info = sym_user_command,
+#endif
.proc_name = NAME53C8XX,
#endif
};
static int attach_count;
-static int __devinit sym2_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int sym2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct sym_device sym_dev;
struct sym_nvram nvram;
@@ -2077,7 +2001,7 @@ static struct spi_function_template sym2_transport_functions = {
.get_signalling = sym2_get_signalling,
};
-static struct pci_device_id sym2_id_table[] __devinitdata = {
+static struct pci_device_id sym2_id_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C810,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C820,
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index d672d97..f1e4b41 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -201,7 +201,8 @@ int __init t128_detect(struct scsi_host_template * tpnt){
int sig, count;
tpnt->proc_name = "t128";
- tpnt->proc_info = &t128_proc_info;
+ tpnt->show_info = t128_show_info;
+ tpnt->write_info = t128_write_info;
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
base = 0;
diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h
index ada1115..1df82c28 100644
--- a/drivers/scsi/t128.h
+++ b/drivers/scsi/t128.h
@@ -140,7 +140,8 @@ static int t128_bus_reset(struct scsi_cmnd *);
#define NCR5380_queue_command t128_queue_command
#define NCR5380_abort t128_abort
#define NCR5380_bus_reset t128_bus_reset
-#define NCR5380_proc_info t128_proc_info
+#define NCR5380_show_info t128_show_info
+#define NCR5380_write_info t128_write_info
/* 15 14 12 10 7 5 3
1101 0100 1010 1000 */
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index a1baccc..9327f5f 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -2219,7 +2219,7 @@ static struct scsi_host_template driver_template = {
*
**********************************************************************/
-static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
{
u8 carryFlag = 1, j = 0x80, bval;
int i;
@@ -2242,7 +2242,7 @@ static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
}
}
-static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev)
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
{
int i;
u16 wval = 0;
@@ -2264,7 +2264,7 @@ static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev)
return wval;
}
-static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
{
u8 cmd = EEPROM_READ, i;
@@ -2282,7 +2282,7 @@ static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
}
/* Override EEprom values with explicitly set values */
-static void __devinit dc390_eeprom_override(u8 index)
+static void dc390_eeprom_override(u8 index)
{
u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
@@ -2305,7 +2305,7 @@ static void __devinit dc390_eeprom_override(u8 index)
}
}
-static int __devinitdata tmscsim_def[] = {
+static int tmscsim_def[] = {
7,
0 /* 10MHz */,
PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
@@ -2315,7 +2315,7 @@ static int __devinitdata tmscsim_def[] = {
};
/* Copy defaults over set values where missing */
-static void __devinit dc390_fill_with_defaults (void)
+static void dc390_fill_with_defaults (void)
{
int i;
@@ -2335,7 +2335,7 @@ static void __devinit dc390_fill_with_defaults (void)
tmscsim[5] = 180;
}
-static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index)
+static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
{
u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
u8 EEbuf[128];
@@ -2372,7 +2372,7 @@ static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index)
}
}
-static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index)
+static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
{
struct Scsi_Host *shost = pACB->pScsiHost;
u8 dstate;
@@ -2422,8 +2422,7 @@ static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index)
DC390_write8(DMA_Status, dstate);
}
-static int __devinit dc390_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct dc390_acb *pACB;
struct Scsi_Host *shost;
@@ -2532,7 +2531,7 @@ static int __devinit dc390_probe_one(struct pci_dev *pdev,
*
* @dev: The PCI device to remove.
*/
-static void __devexit dc390_remove_one(struct pci_dev *dev)
+static void dc390_remove_one(struct pci_dev *dev)
{
struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
unsigned long iflags;
@@ -2568,7 +2567,7 @@ static struct pci_driver dc390_driver = {
.name = "tmscsim",
.id_table = tmscsim_pci_tbl,
.probe = dc390_probe_one,
- .remove = __devexit_p(dc390_remove_one),
+ .remove = dc390_remove_one,
};
static int __init dc390_module_init(void)
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 8f27f9d..f07f9017 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -2,48 +2,69 @@
# Kernel configuration file for the UFS Host Controller
#
# This code is based on drivers/scsi/ufs/Kconfig
-# Copyright (C) 2011 Samsung Samsung India Software Operations
+# Copyright (C) 2011-2013 Samsung India Software Operations
+#
+# Authors:
+# Santosh Yaraganavi <santosh.sy@samsung.com>
+# Vinayak Holikatti <h.vinayak@samsung.com>
#
-# Santosh Yaraganavi <santosh.sy@samsung.com>
-# Vinayak Holikatti <h.vinayak@samsung.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.
-
+# See the COPYING file in the top-level directory or visit
+# <http://www.gnu.org/licenses/gpl-2.0.html>
+#
# 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.
+#
+# This program is provided "AS IS" and "WITH ALL FAULTS" and
+# without warranty of any kind. You are solely responsible for
+# determining the appropriateness of using and distributing
+# the program and assume all risks associated with your exercise
+# of rights with respect to the program, including but not limited
+# to infringement of third party rights, the risks and costs of
+# program errors, damage to or loss of data, programs or equipment,
+# and unavailability or interruption of operations. Under no
+# circumstances will the contributor of this Program be liable for
+# any damages of any kind arising from your use or distribution of
+# this program.
config SCSI_UFSHCD
- tristate "Universal Flash Storage host controller driver"
- depends on PCI && SCSI
+ tristate "Universal Flash Storage Controller Driver Core"
+ depends on SCSI && SCSI_DMA
---help---
- This is a generic driver which supports PCIe UFS Host controllers.
+ This selects the support for UFS devices in Linux, say Y and make
+ sure that you know the name of your UFS host adapter (the card
+ inside your computer that "speaks" the UFS protocol, also
+ called UFS Host Controller), because you will be asked for it.
+ The module will be called ufshcd.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/scsi/ufs.txt>.
+ However, do not compile this as a module if your root file system
+ (the one containing the directory /) is located on a UFS device.
+
+config SCSI_UFSHCD_PCI
+ tristate "PCI bus based UFS Controller support"
+ depends on SCSI_UFSHCD && PCI
+ ---help---
+ This selects the PCI UFS Host Controller Interface. Select this if
+ you have UFS Host Controller with PCI Interface.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
+config SCSI_UFSHCD_PLATFORM
+ tristate "Platform bus based UFS Controller support"
+ depends on SCSI_UFSHCD
+ ---help---
+ This selects the UFS host controller support. Select this if
+ you have an UFS controller on Platform bus.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index adf7895..1e5bd48 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,2 +1,4 @@
# UFSHCD makefile
obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
+obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b207529..139bc06 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -2,45 +2,35 @@
* Universal Flash Storage Host controller driver
*
* This code is based on drivers/scsi/ufs/ufs.h
- * Copyright (C) 2011-2012 Samsung India Software Operations
+ * Copyright (C) 2011-2013 Samsung India Software Operations
*
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
*
* 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.
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
*/
#ifndef _UFS_H
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
new file mode 100644
index 0000000..48be39a
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -0,0 +1,210 @@
+/*
+ * Universal Flash Storage Host controller PCI glue driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pci.c
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ *
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * 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 program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include "ufshcd.h"
+#include <linux/pci.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pci_suspend - suspend power management function
+ * @pdev: pointer to PCI device handle
+ * @state: power state
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ /*
+ * TODO:
+ * 1. Call ufshcd_suspend
+ * 2. Do bus specific power management
+ */
+
+ return -ENOSYS;
+}
+
+/**
+ * ufshcd_pci_resume - resume power management function
+ * @pdev: pointer to PCI device handle
+ *
+ * Returns -ENOSYS
+ */
+static int ufshcd_pci_resume(struct pci_dev *pdev)
+{
+ /*
+ * TODO:
+ * 1. Call ufshcd_resume.
+ * 2. Do bus specific wake up
+ */
+
+ return -ENOSYS;
+}
+#endif /* CONFIG_PM */
+
+/**
+ * ufshcd_pci_shutdown - main function to put the controller in reset state
+ * @pdev: pointer to PCI device handle
+ */
+static void ufshcd_pci_shutdown(struct pci_dev *pdev)
+{
+ ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
+}
+
+/**
+ * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
+ * data structure memory
+ * @pdev - pointer to PCI handle
+ */
+static void ufshcd_pci_remove(struct pci_dev *pdev)
+{
+ struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+ disable_irq(pdev->irq);
+ ufshcd_remove(hba);
+ pci_release_regions(pdev);
+ pci_set_drvdata(pdev, NULL);
+ pci_clear_master(pdev);
+ pci_disable_device(pdev);
+}
+
+/**
+ * ufshcd_set_dma_mask - Set dma mask based on the controller
+ * addressing capability
+ * @pdev: PCI device structure
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_set_dma_mask(struct pci_dev *pdev)
+{
+ int err;
+
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+ && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
+ return 0;
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ return err;
+}
+
+/**
+ * ufshcd_pci_probe - probe routine of the driver
+ * @pdev: pointer to PCI device handle
+ * @id: PCI device id
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int
+ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct ufs_hba *hba;
+ void __iomem *mmio_base;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_device failed\n");
+ goto out_error;
+ }
+
+ pci_set_master(pdev);
+
+
+ err = pci_request_regions(pdev, UFSHCD);
+ if (err < 0) {
+ dev_err(&pdev->dev, "request regions failed\n");
+ goto out_disable;
+ }
+
+ mmio_base = pci_ioremap_bar(pdev, 0);
+ if (!mmio_base) {
+ dev_err(&pdev->dev, "memory map failed\n");
+ err = -ENOMEM;
+ goto out_release_regions;
+ }
+
+ err = ufshcd_set_dma_mask(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "set dma mask failed\n");
+ goto out_iounmap;
+ }
+
+ err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
+ if (err) {
+ dev_err(&pdev->dev, "Initialization failed\n");
+ goto out_iounmap;
+ }
+
+ pci_set_drvdata(pdev, hba);
+
+ return 0;
+
+out_iounmap:
+ iounmap(mmio_base);
+out_release_regions:
+ pci_release_regions(pdev);
+out_disable:
+ pci_clear_master(pdev);
+ pci_disable_device(pdev);
+out_error:
+ return err;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
+ { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { } /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
+
+static struct pci_driver ufshcd_pci_driver = {
+ .name = UFSHCD,
+ .id_table = ufshcd_pci_tbl,
+ .probe = ufshcd_pci_probe,
+ .remove = ufshcd_pci_remove,
+ .shutdown = ufshcd_pci_shutdown,
+#ifdef CONFIG_PM
+ .suspend = ufshcd_pci_suspend,
+ .resume = ufshcd_pci_resume,
+#endif
+};
+
+module_pci_driver(ufshcd_pci_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("UFS host controller PCI glue driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
new file mode 100644
index 0000000..c42db40
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -0,0 +1,179 @@
+/*
+ * Universal Flash Storage Host controller Platform bus based glue driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ *
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * 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 program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include <linux/platform_device.h>
+
+#include "ufshcd.h"
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pltfrm_suspend - suspend power management function
+ * @dev: pointer to device handle
+ *
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ /*
+ * TODO:
+ * 1. Call ufshcd_suspend
+ * 2. Do bus specific power management
+ */
+
+ disable_irq(hba->irq);
+
+ return 0;
+}
+
+/**
+ * ufshcd_pltfrm_resume - resume power management function
+ * @dev: pointer to device handle
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ /*
+ * TODO:
+ * 1. Call ufshcd_resume.
+ * 2. Do bus specific wake up
+ */
+
+ enable_irq(hba->irq);
+
+ return 0;
+}
+#else
+#define ufshcd_pltfrm_suspend NULL
+#define ufshcd_pltfrm_resume NULL
+#endif
+
+/**
+ * ufshcd_pltfrm_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_probe(struct platform_device *pdev)
+{
+ struct ufs_hba *hba;
+ void __iomem *mmio_base;
+ struct resource *mem_res;
+ int irq, err;
+ struct device *dev = &pdev->dev;
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(dev, "Memory resource not available\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ mmio_base = devm_ioremap_resource(dev, mem_res);
+ if (IS_ERR(mmio_base)) {
+ dev_err(dev, "memory map failed\n");
+ err = PTR_ERR(mmio_base);
+ goto out;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "IRQ resource not available\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ err = ufshcd_init(dev, &hba, mmio_base, irq);
+ if (err) {
+ dev_err(dev, "Intialization failed\n");
+ goto out;
+ }
+
+ platform_set_drvdata(pdev, hba);
+
+out:
+ return err;
+}
+
+/**
+ * ufshcd_pltfrm_remove - remove platform driver routine
+ * @pdev: pointer to platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_remove(struct platform_device *pdev)
+{
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ disable_irq(hba->irq);
+ ufshcd_remove(hba);
+ return 0;
+}
+
+static const struct of_device_id ufs_of_match[] = {
+ { .compatible = "jedec,ufs-1.1"},
+ {},
+};
+
+static const struct dev_pm_ops ufshcd_dev_pm_ops = {
+ .suspend = ufshcd_pltfrm_suspend,
+ .resume = ufshcd_pltfrm_resume,
+};
+
+static struct platform_driver ufshcd_pltfrm_driver = {
+ .probe = ufshcd_pltfrm_probe,
+ .remove = ufshcd_pltfrm_remove,
+ .driver = {
+ .name = "ufshcd",
+ .owner = THIS_MODULE,
+ .pm = &ufshcd_dev_pm_ops,
+ .of_match_table = ufs_of_match,
+ },
+};
+
+module_platform_driver(ufshcd_pltfrm_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 58f4ba6..b743bd6 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1,77 +1,47 @@
/*
- * Universal Flash Storage Host controller driver
+ * Universal Flash Storage Host controller driver Core
*
* This code is based on drivers/scsi/ufs/ufshcd.c
- * Copyright (C) 2011-2012 Samsung India Software Operations
+ * Copyright (C) 2011-2013 Samsung India Software Operations
*
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
*
* 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.
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_eh.h>
-
-#include "ufs.h"
-#include "ufshci.h"
-
-#define UFSHCD "ufshcd"
-#define UFSHCD_DRIVER_VERSION "0.1"
+#include <linux/async.h>
+
+#include "ufshcd.h"
+
+#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\
+ UTP_TASK_REQ_COMPL |\
+ UFSHCD_ERROR_MASK)
+/* UIC command timeout, unit: ms */
+#define UIC_CMD_TIMEOUT 500
enum {
UFSHCD_MAX_CHANNEL = 0,
@@ -102,119 +72,18 @@ enum {
};
/**
- * struct uic_command - UIC command structure
- * @command: UIC command
- * @argument1: UIC command argument 1
- * @argument2: UIC command argument 2
- * @argument3: UIC command argument 3
- * @cmd_active: Indicate if UIC command is outstanding
- * @result: UIC command result
- */
-struct uic_command {
- u32 command;
- u32 argument1;
- u32 argument2;
- u32 argument3;
- int cmd_active;
- int result;
-};
-
-/**
- * struct ufs_hba - per adapter private structure
- * @mmio_base: UFSHCI base register address
- * @ucdl_base_addr: UFS Command Descriptor base address
- * @utrdl_base_addr: UTP Transfer Request Descriptor base address
- * @utmrdl_base_addr: UTP Task Management Descriptor base address
- * @ucdl_dma_addr: UFS Command Descriptor DMA address
- * @utrdl_dma_addr: UTRDL DMA address
- * @utmrdl_dma_addr: UTMRDL DMA address
- * @host: Scsi_Host instance of the driver
- * @pdev: PCI device handle
- * @lrb: local reference block
- * @outstanding_tasks: Bits representing outstanding task requests
- * @outstanding_reqs: Bits representing outstanding transfer requests
- * @capabilities: UFS Controller Capabilities
- * @nutrs: Transfer Request Queue depth supported by controller
- * @nutmrs: Task Management Queue depth supported by controller
- * @active_uic_cmd: handle of active UIC command
- * @ufshcd_tm_wait_queue: wait queue for task management
- * @tm_condition: condition variable for task management
- * @ufshcd_state: UFSHCD states
- * @int_enable_mask: Interrupt Mask Bits
- * @uic_workq: Work queue for UIC completion handling
- * @feh_workq: Work queue for fatal controller error handling
- * @errors: HBA errors
- */
-struct ufs_hba {
- void __iomem *mmio_base;
-
- /* Virtual memory reference */
- struct utp_transfer_cmd_desc *ucdl_base_addr;
- struct utp_transfer_req_desc *utrdl_base_addr;
- struct utp_task_req_desc *utmrdl_base_addr;
-
- /* DMA memory reference */
- dma_addr_t ucdl_dma_addr;
- dma_addr_t utrdl_dma_addr;
- dma_addr_t utmrdl_dma_addr;
-
- struct Scsi_Host *host;
- struct pci_dev *pdev;
-
- struct ufshcd_lrb *lrb;
-
- unsigned long outstanding_tasks;
- unsigned long outstanding_reqs;
-
- u32 capabilities;
- int nutrs;
- int nutmrs;
- u32 ufs_version;
-
- struct uic_command active_uic_cmd;
- wait_queue_head_t ufshcd_tm_wait_queue;
- unsigned long tm_condition;
-
- u32 ufshcd_state;
- u32 int_enable_mask;
-
- /* Work Queues */
- struct work_struct uic_workq;
- struct work_struct feh_workq;
-
- /* HBA Errors */
- u32 errors;
-};
-
-/**
- * struct ufshcd_lrb - local reference block
- * @utr_descriptor_ptr: UTRD address of the command
- * @ucd_cmd_ptr: UCD address of the command
- * @ucd_rsp_ptr: Response UPIU address for this command
- * @ucd_prdt_ptr: PRDT address of the command
- * @cmd: pointer to SCSI command
- * @sense_buffer: pointer to sense buffer address of the SCSI command
- * @sense_bufflen: Length of the sense buffer
- * @scsi_status: SCSI status of the command
- * @command_type: SCSI, UFS, Query.
- * @task_tag: Task tag of the command
- * @lun: LUN of the command
+ * ufshcd_get_intr_mask - Get the interrupt bit mask
+ * @hba - Pointer to adapter instance
+ *
+ * Returns interrupt bit mask per version
*/
-struct ufshcd_lrb {
- struct utp_transfer_req_desc *utr_descriptor_ptr;
- struct utp_upiu_cmd *ucd_cmd_ptr;
- struct utp_upiu_rsp *ucd_rsp_ptr;
- struct ufshcd_sg_entry *ucd_prdt_ptr;
-
- struct scsi_cmnd *cmd;
- u8 *sense_buffer;
- unsigned int sense_bufflen;
- int scsi_status;
-
- int command_type;
- int task_tag;
- unsigned int lun;
-};
+static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
+{
+ if (hba->ufs_version == UFSHCI_VERSION_10)
+ return INTERRUPT_MASK_ALL_VER_10;
+ else
+ return INTERRUPT_MASK_ALL_VER_11;
+}
/**
* ufshcd_get_ufs_version - Get the UFS version supported by the HBA
@@ -224,7 +93,7 @@ struct ufshcd_lrb {
*/
static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
{
- return readl(hba->mmio_base + REG_UFS_VERSION);
+ return ufshcd_readl(hba, REG_UFS_VERSION);
}
/**
@@ -283,8 +152,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)
*/
static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
{
- writel(~(1 << pos),
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
+ ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
}
/**
@@ -318,43 +186,11 @@ static inline int ufshcd_get_lists_status(u32 reg)
*/
static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
{
- return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
+ return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
MASK_UIC_COMMAND_RESULT;
}
/**
- * ufshcd_free_hba_memory - Free allocated memory for LRB, request
- * and task lists
- * @hba: Pointer to adapter instance
- */
-static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
-{
- size_t utmrdl_size, utrdl_size, ucdl_size;
-
- kfree(hba->lrb);
-
- if (hba->utmrdl_base_addr) {
- utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
- dma_free_coherent(&hba->pdev->dev, utmrdl_size,
- hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
- }
-
- if (hba->utrdl_base_addr) {
- utrdl_size =
- (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
- dma_free_coherent(&hba->pdev->dev, utrdl_size,
- hba->utrdl_base_addr, hba->utrdl_dma_addr);
- }
-
- if (hba->ucdl_base_addr) {
- ucdl_size =
- (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
- dma_free_coherent(&hba->pdev->dev, ucdl_size,
- hba->ucdl_base_addr, hba->ucdl_dma_addr);
- }
-}
-
-/**
* ufshcd_is_valid_req_rsp - checks if controller TR response is valid
* @ucd_rsp_ptr: pointer to response UPIU
*
@@ -396,18 +232,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
{
switch (option) {
case INT_AGGR_RESET:
- writel((INT_AGGR_ENABLE |
- INT_AGGR_COUNTER_AND_TIMER_RESET),
- (hba->mmio_base +
- REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+ ufshcd_writel(hba, INT_AGGR_ENABLE |
+ INT_AGGR_COUNTER_AND_TIMER_RESET,
+ REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
break;
case INT_AGGR_CONFIG:
- writel((INT_AGGR_ENABLE |
- INT_AGGR_PARAM_WRITE |
- INT_AGGR_COUNTER_THRESHOLD_VALUE |
- INT_AGGR_TIMEOUT_VALUE),
- (hba->mmio_base +
- REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+ ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
+ INT_AGGR_COUNTER_THRESHOLD_VALUE |
+ INT_AGGR_TIMEOUT_VALUE,
+ REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
break;
}
}
@@ -420,21 +253,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
*/
static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
{
- writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
- (hba->mmio_base +
- REG_UTP_TASK_REQ_LIST_RUN_STOP));
- writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
- (hba->mmio_base +
- REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
-}
-
-/**
- * ufshcd_hba_stop - Send controller to reset state
- * @hba: per adapter instance
- */
-static inline void ufshcd_hba_stop(struct ufs_hba *hba)
-{
- writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
+ ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
+ REG_UTP_TASK_REQ_LIST_RUN_STOP);
+ ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
+ REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
}
/**
@@ -443,7 +265,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba)
*/
static inline void ufshcd_hba_start(struct ufs_hba *hba)
{
- writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
+ ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
}
/**
@@ -454,7 +276,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)
*/
static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
{
- return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
+ return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
}
/**
@@ -466,8 +288,7 @@ static inline
void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
{
__set_bit(task_tag, &hba->outstanding_reqs);
- writel((1 << task_tag),
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
+ ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
}
/**
@@ -491,8 +312,7 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
*/
static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
{
- hba->capabilities =
- readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
+ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
/* nutrs and nutmrs are 0 based values */
hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
@@ -501,24 +321,119 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
}
/**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ * to accept UIC commands
* @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+ if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
*/
static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
{
+ WARN_ON(hba->active_uic_cmd);
+
+ hba->active_uic_cmd = uic_cmd;
+
/* Write Args */
- writel(uic_cmnd->argument1,
- (hba->mmio_base + REG_UIC_COMMAND_ARG_1));
- writel(uic_cmnd->argument2,
- (hba->mmio_base + REG_UIC_COMMAND_ARG_2));
- writel(uic_cmnd->argument3,
- (hba->mmio_base + REG_UIC_COMMAND_ARG_3));
+ ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
+ ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
+ ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
/* Write UIC Cmd */
- writel((uic_cmnd->command & COMMAND_OPCODE_MASK),
- (hba->mmio_base + REG_UIC_COMMAND));
+ ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
+ REG_UIC_COMMAND);
+}
+
+/**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+ int ret;
+ unsigned long flags;
+
+ if (wait_for_completion_timeout(&uic_cmd->done,
+ msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+ ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+ else
+ ret = -ETIMEDOUT;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->active_uic_cmd = NULL;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+ int ret;
+ unsigned long flags;
+
+ if (!ufshcd_ready_for_uic_cmd(hba)) {
+ dev_err(hba->dev,
+ "Controller not ready to accept UIC commands\n");
+ return -EIO;
+ }
+
+ init_completion(&uic_cmd->done);
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+ return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+ int ret;
+
+ mutex_lock(&hba->uic_cmd_mutex);
+ ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+ mutex_unlock(&hba->uic_cmd_mutex);
+
+ return ret;
}
/**
@@ -562,26 +477,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
}
/**
- * ufshcd_int_config - enable/disable interrupts
+ * ufshcd_enable_intr - enable interrupts
* @hba: per adapter instance
- * @option: interrupt option
+ * @intrs: interrupt bits
*/
-static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
+static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
{
- switch (option) {
- case UFSHCD_INT_ENABLE:
- writel(hba->int_enable_mask,
- (hba->mmio_base + REG_INTERRUPT_ENABLE));
- break;
- case UFSHCD_INT_DISABLE:
- if (hba->ufs_version == UFSHCI_VERSION_10)
- writel(INTERRUPT_DISABLE_MASK_10,
- (hba->mmio_base + REG_INTERRUPT_ENABLE));
- else
- writel(INTERRUPT_DISABLE_MASK_11,
- (hba->mmio_base + REG_INTERRUPT_ENABLE));
- break;
+ u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+ if (hba->ufs_version == UFSHCI_VERSION_10) {
+ u32 rw;
+ rw = set & INTERRUPT_MASK_RW_VER_10;
+ set = rw | ((set ^ intrs) & intrs);
+ } else {
+ set |= intrs;
+ }
+
+ ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
+}
+
+/**
+ * ufshcd_disable_intr - disable interrupts
+ * @hba: per adapter instance
+ * @intrs: interrupt bits
+ */
+static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
+{
+ u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+ if (hba->ufs_version == UFSHCI_VERSION_10) {
+ u32 rw;
+ rw = (set & INTERRUPT_MASK_RW_VER_10) &
+ ~(intrs & INTERRUPT_MASK_RW_VER_10);
+ set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
+
+ } else {
+ set &= ~intrs;
}
+
+ ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
}
/**
@@ -640,7 +574,7 @@ static void ufshcd_compose_upiu(struct ufshcd_lrb *lrbp)
ucd_cmd_ptr->header.dword_2 = 0;
ucd_cmd_ptr->exp_data_transfer_len =
- cpu_to_be32(lrbp->cmd->transfersize);
+ cpu_to_be32(lrbp->cmd->sdb.length);
memcpy(ucd_cmd_ptr->cdb,
lrbp->cmd->cmnd,
@@ -724,10 +658,10 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate memory for UTP command descriptors */
ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
- hba->ucdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
- ucdl_size,
- &hba->ucdl_dma_addr,
- GFP_KERNEL);
+ hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
+ ucdl_size,
+ &hba->ucdl_dma_addr,
+ GFP_KERNEL);
/*
* UFSHCI requires UTP command descriptor to be 128 byte aligned.
@@ -737,7 +671,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
*/
if (!hba->ucdl_base_addr ||
WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Command Descriptor Memory allocation failed\n");
goto out;
}
@@ -747,13 +681,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* UFSHCI requires 1024 byte alignment of UTRD
*/
utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
- hba->utrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
- utrdl_size,
- &hba->utrdl_dma_addr,
- GFP_KERNEL);
+ hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev,
+ utrdl_size,
+ &hba->utrdl_dma_addr,
+ GFP_KERNEL);
if (!hba->utrdl_base_addr ||
WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Transfer Descriptor Memory allocation failed\n");
goto out;
}
@@ -763,26 +697,27 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* UFSHCI requires 1024 byte alignment of UTMRD
*/
utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
- hba->utmrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
- utmrdl_size,
- &hba->utmrdl_dma_addr,
- GFP_KERNEL);
+ hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev,
+ utmrdl_size,
+ &hba->utmrdl_dma_addr,
+ GFP_KERNEL);
if (!hba->utmrdl_base_addr ||
WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Task Management Descriptor Memory allocation failed\n");
goto out;
}
/* Allocate memory for local reference block */
- hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
+ hba->lrb = devm_kzalloc(hba->dev,
+ hba->nutrs * sizeof(struct ufshcd_lrb),
+ GFP_KERNEL);
if (!hba->lrb) {
- dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
+ dev_err(hba->dev, "LRB Memory allocation failed\n");
goto out;
}
return 0;
out:
- ufshcd_free_hba_memory(hba);
return -ENOMEM;
}
@@ -836,7 +771,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
utrdlp[i].prd_table_offset =
cpu_to_le16((prdt_offset >> 2));
utrdlp[i].response_upiu_length =
- cpu_to_le16(ALIGNED_UPIU_SIZE);
+ cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
hba->lrb[i].ucd_cmd_ptr =
@@ -861,35 +796,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
*/
static int ufshcd_dme_link_startup(struct ufs_hba *hba)
{
- struct uic_command *uic_cmd;
- unsigned long flags;
-
- /* check if controller is ready to accept UIC commands */
- if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
- UIC_COMMAND_READY) == 0x0) {
- dev_err(&hba->pdev->dev,
- "Controller not ready"
- " to accept UIC commands\n");
- return -EIO;
- }
-
- spin_lock_irqsave(hba->host->host_lock, flags);
+ struct uic_command uic_cmd = {0};
+ int ret;
- /* form UIC command */
- uic_cmd = &hba->active_uic_cmd;
- uic_cmd->command = UIC_CMD_DME_LINK_STARTUP;
- uic_cmd->argument1 = 0;
- uic_cmd->argument2 = 0;
- uic_cmd->argument3 = 0;
+ uic_cmd.command = UIC_CMD_DME_LINK_STARTUP;
- /* enable UIC related interrupts */
- hba->int_enable_mask |= UIC_COMMAND_COMPL;
- ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
-
- /* sending UIC commands to controller */
- ufshcd_send_uic_command(hba, uic_cmd);
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- return 0;
+ ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+ if (ret)
+ dev_err(hba->dev,
+ "dme-link-startup: error code %d\n", ret);
+ return ret;
}
/**
@@ -898,9 +814,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
*
* To bring UFS host controller to operational state,
* 1. Check if device is present
- * 2. Configure run-stop-registers
- * 3. Enable required interrupts
- * 4. Configure interrupt aggregation
+ * 2. Enable required interrupts
+ * 3. Configure interrupt aggregation
+ * 4. Program UTRL and UTMRL base addres
+ * 5. Configure run-stop-registers
*
* Returns 0 on success, non-zero value on failure
*/
@@ -910,13 +827,29 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
u32 reg;
/* check if device present */
- reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
+ reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
if (!ufshcd_is_device_present(reg)) {
- dev_err(&hba->pdev->dev, "cc: Device not present\n");
+ dev_err(hba->dev, "cc: Device not present\n");
err = -ENXIO;
goto out;
}
+ /* Enable required interrupts */
+ ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
+
+ /* Configure interrupt aggregation */
+ ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
+
+ /* Configure UTRL and UTMRL base address registers */
+ ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
+ REG_UTP_TRANSFER_REQ_LIST_BASE_L);
+ ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
+ REG_UTP_TRANSFER_REQ_LIST_BASE_H);
+ ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
+ REG_UTP_TASK_REQ_LIST_BASE_L);
+ ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
+ REG_UTP_TASK_REQ_LIST_BASE_H);
+
/*
* UCRDY, UTMRLDY and UTRLRDY bits must be 1
* DEI, HEI bits must be 0
@@ -924,29 +857,17 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
if (!(ufshcd_get_lists_status(reg))) {
ufshcd_enable_run_stop_reg(hba);
} else {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Host controller not ready to process requests");
err = -EIO;
goto out;
}
- /* Enable required interrupts */
- hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
- UIC_ERROR |
- UTP_TASK_REQ_COMPL |
- DEVICE_FATAL_ERROR |
- CONTROLLER_FATAL_ERROR |
- SYSTEM_BUS_FATAL_ERROR);
- ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
-
- /* Configure interrupt aggregation */
- ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
-
if (hba->ufshcd_state == UFSHCD_STATE_RESET)
scsi_unblock_requests(hba->host);
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
- scsi_scan_host(hba->host);
+
out:
return err;
}
@@ -1005,7 +926,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
if (retry) {
retry--;
} else {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Controller enable failed\n");
return -EIO;
}
@@ -1015,34 +936,28 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
}
/**
- * ufshcd_initialize_hba - start the initialization process
+ * ufshcd_link_startup - Initialize unipro link startup
* @hba: per adapter instance
*
- * 1. Enable the controller via ufshcd_hba_enable.
- * 2. Program the Transfer Request List Address with the starting address of
- * UTRDL.
- * 3. Program the Task Management Request List Address with starting address
- * of UTMRDL.
- *
- * Returns 0 on success, non-zero value on failure.
+ * Returns 0 for success, non-zero in case of failure
*/
-static int ufshcd_initialize_hba(struct ufs_hba *hba)
+static int ufshcd_link_startup(struct ufs_hba *hba)
{
- if (ufshcd_hba_enable(hba))
- return -EIO;
+ int ret;
- /* Configure UTRL and UTMRL base address registers */
- writel(lower_32_bits(hba->utrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
- writel(upper_32_bits(hba->utrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
- writel(lower_32_bits(hba->utmrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
- writel(upper_32_bits(hba->utmrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
-
- /* Initialize unipro link startup procedure */
- return ufshcd_dme_link_startup(hba);
+ /* enable UIC related interrupts */
+ ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
+
+ ret = ufshcd_dme_link_startup(hba);
+ if (ret)
+ goto out;
+
+ ret = ufshcd_make_hba_operational(hba);
+
+out:
+ if (ret)
+ dev_err(hba->dev, "link startup failed %d\n", ret);
+ return ret;
}
/**
@@ -1082,12 +997,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
hba->outstanding_reqs = 0;
hba->outstanding_tasks = 0;
- /* start the initialization process */
- if (ufshcd_initialize_hba(hba)) {
- dev_err(&hba->pdev->dev,
+ /* Host controller enable */
+ if (ufshcd_hba_enable(hba)) {
+ dev_err(hba->dev,
"Reset: Controller initialization failed\n");
return FAILED;
}
+
+ if (ufshcd_link_startup(hba)) {
+ dev_err(hba->dev,
+ "Reset: Link start-up failed\n");
+ return FAILED;
+ }
+
return SUCCESS;
}
@@ -1167,7 +1089,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
task_result = SUCCESS;
} else {
task_result = FAILED;
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"trc: Invalid ocs = %x\n", ocs_value);
}
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -1281,7 +1203,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
/* check if the returned transfer response is valid */
result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
if (result) {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Invalid response = %x\n", result);
break;
}
@@ -1310,7 +1232,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
case OCS_FATAL_ERROR:
default:
result |= DID_ERROR << 16;
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"OCS error from controller = %x\n", ocs);
break;
} /* end of switch */
@@ -1319,6 +1241,19 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
}
/**
+ * ufshcd_uic_cmd_compl - handle completion of uic command
+ * @hba: per adapter instance
+ */
+static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
+{
+ if (hba->active_uic_cmd) {
+ hba->active_uic_cmd->argument2 |=
+ ufshcd_get_uic_cmd_result(hba);
+ complete(&hba->active_uic_cmd->done);
+ }
+}
+
+/**
* ufshcd_transfer_req_compl - handle SCSI and query command completion
* @hba: per adapter instance
*/
@@ -1331,8 +1266,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
int index;
lrb = hba->lrb;
- tr_doorbell =
- readl(hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
for (index = 0; index < hba->nutrs; index++) {
@@ -1359,28 +1293,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
}
/**
- * ufshcd_uic_cc_handler - handle UIC command completion
- * @work: pointer to a work queue structure
- *
- * Returns 0 on success, non-zero value on failure
- */
-static void ufshcd_uic_cc_handler (struct work_struct *work)
-{
- struct ufs_hba *hba;
-
- hba = container_of(work, struct ufs_hba, uic_workq);
-
- if ((hba->active_uic_cmd.command == UIC_CMD_DME_LINK_STARTUP) &&
- !(ufshcd_get_uic_cmd_result(hba))) {
-
- if (ufshcd_make_hba_operational(hba))
- dev_err(&hba->pdev->dev,
- "cc: hba not operational state\n");
- return;
- }
-}
-
-/**
* ufshcd_fatal_err_handler - handle fatal errors
* @hba: per adapter instance
*/
@@ -1406,9 +1318,7 @@ static void ufshcd_err_handler(struct ufs_hba *hba)
goto fatal_eh;
if (hba->errors & UIC_ERROR) {
-
- reg = readl(hba->mmio_base +
- REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
+ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER);
if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
goto fatal_eh;
}
@@ -1426,7 +1336,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba)
{
u32 tm_doorbell;
- tm_doorbell = readl(hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL);
+ tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;
wake_up_interruptible(&hba->ufshcd_tm_wait_queue);
}
@@ -1443,7 +1353,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
ufshcd_err_handler(hba);
if (intr_status & UIC_COMMAND_COMPL)
- schedule_work(&hba->uic_workq);
+ ufshcd_uic_cmd_compl(hba);
if (intr_status & UTP_TASK_REQ_COMPL)
ufshcd_tmc_handler(hba);
@@ -1467,15 +1377,11 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
struct ufs_hba *hba = __hba;
spin_lock(hba->host->host_lock);
- intr_status = readl(hba->mmio_base + REG_INTERRUPT_STATUS);
+ intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
if (intr_status) {
+ ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
ufshcd_sl_intr(hba, intr_status);
-
- /* If UFSHCI 1.0 then clear interrupt status register */
- if (hba->ufs_version == UFSHCI_VERSION_10)
- writel(intr_status,
- (hba->mmio_base + REG_INTERRUPT_STATUS));
retval = IRQ_HANDLED;
}
spin_unlock(hba->host->host_lock);
@@ -1509,7 +1415,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
free_slot = ufshcd_get_tm_free_slot(hba);
if (free_slot >= hba->nutmrs) {
spin_unlock_irqrestore(host->host_lock, flags);
- dev_err(&hba->pdev->dev, "Task management queue full\n");
+ dev_err(hba->dev, "Task management queue full\n");
err = FAILED;
goto out;
}
@@ -1540,8 +1446,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
/* send command to the controller */
__set_bit(free_slot, &hba->outstanding_tasks);
- writel((1 << free_slot),
- (hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL));
+ ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
spin_unlock_irqrestore(host->host_lock, flags);
@@ -1552,7 +1457,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
&hba->tm_condition) != 0),
60 * HZ);
if (!err) {
- dev_err(&hba->pdev->dev,
+ dev_err(hba->dev,
"Task management command timed-out\n");
err = FAILED;
goto out;
@@ -1671,6 +1576,21 @@ out:
return err;
}
+/**
+ * ufshcd_async_scan - asynchronous execution for link startup
+ * @data: data pointer to pass to this function
+ * @cookie: cookie data
+ */
+static void ufshcd_async_scan(void *data, async_cookie_t cookie)
+{
+ struct ufs_hba *hba = (struct ufs_hba *)data;
+ int ret;
+
+ ret = ufshcd_link_startup(hba);
+ if (!ret)
+ scsi_scan_host(hba->host);
+}
+
static struct scsi_host_template ufshcd_driver_template = {
.module = THIS_MODULE,
.name = UFSHCD,
@@ -1688,23 +1608,13 @@ static struct scsi_host_template ufshcd_driver_template = {
};
/**
- * ufshcd_shutdown - main function to put the controller in reset state
- * @pdev: pointer to PCI device handle
- */
-static void ufshcd_shutdown(struct pci_dev *pdev)
-{
- ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
-}
-
-#ifdef CONFIG_PM
-/**
* ufshcd_suspend - suspend power management function
- * @pdev: pointer to PCI device handle
+ * @hba: per adapter instance
* @state: power state
*
* Returns -ENOSYS
*/
-static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
+int ufshcd_suspend(struct ufs_hba *hba, pm_message_t state)
{
/*
* TODO:
@@ -1717,14 +1627,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
return -ENOSYS;
}
+EXPORT_SYMBOL_GPL(ufshcd_suspend);
/**
* ufshcd_resume - resume power management function
- * @pdev: pointer to PCI device handle
+ * @hba: per adapter instance
*
* Returns -ENOSYS
*/
-static int ufshcd_resume(struct pci_dev *pdev)
+int ufshcd_resume(struct ufs_hba *hba)
{
/*
* TODO:
@@ -1737,119 +1648,65 @@ static int ufshcd_resume(struct pci_dev *pdev)
return -ENOSYS;
}
-#endif /* CONFIG_PM */
-
-/**
- * ufshcd_hba_free - free allocated memory for
- * host memory space data structures
- * @hba: per adapter instance
- */
-static void ufshcd_hba_free(struct ufs_hba *hba)
-{
- iounmap(hba->mmio_base);
- ufshcd_free_hba_memory(hba);
- pci_release_regions(hba->pdev);
-}
+EXPORT_SYMBOL_GPL(ufshcd_resume);
/**
- * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
+ * ufshcd_remove - de-allocate SCSI host and host memory space
* data structure memory
- * @pdev - pointer to PCI handle
+ * @hba - per adapter instance
*/
-static void ufshcd_remove(struct pci_dev *pdev)
+void ufshcd_remove(struct ufs_hba *hba)
{
- struct ufs_hba *hba = pci_get_drvdata(pdev);
-
/* disable interrupts */
- ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
- free_irq(pdev->irq, hba);
-
+ ufshcd_disable_intr(hba, hba->intr_mask);
ufshcd_hba_stop(hba);
- ufshcd_hba_free(hba);
scsi_remove_host(hba->host);
scsi_host_put(hba->host);
- pci_set_drvdata(pdev, NULL);
- pci_clear_master(pdev);
- pci_disable_device(pdev);
-}
-
-/**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- * addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct ufs_hba *hba)
-{
- int err;
- u64 dma_mask;
-
- /*
- * If controller supports 64 bit addressing mode, then set the DMA
- * mask to 64-bit, else set the DMA mask to 32-bit
- */
- if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
- dma_mask = DMA_BIT_MASK(64);
- else
- dma_mask = DMA_BIT_MASK(32);
-
- err = pci_set_dma_mask(hba->pdev, dma_mask);
- if (err)
- return err;
-
- err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
-
- return err;
}
+EXPORT_SYMBOL_GPL(ufshcd_remove);
/**
- * ufshcd_probe - probe routine of the driver
- * @pdev: pointer to PCI device handle
- * @id: PCI device id
- *
+ * ufshcd_init - Driver initialization routine
+ * @dev: pointer to device handle
+ * @hba_handle: driver private handle
+ * @mmio_base: base register address
+ * @irq: Interrupt line of device
* Returns 0 on success, non-zero value on failure
*/
-static int __devinit
-ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
+ void __iomem *mmio_base, unsigned int irq)
{
struct Scsi_Host *host;
struct ufs_hba *hba;
int err;
- err = pci_enable_device(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_device failed\n");
+ if (!dev) {
+ dev_err(dev,
+ "Invalid memory reference for dev is NULL\n");
+ err = -ENODEV;
goto out_error;
}
- pci_set_master(pdev);
+ if (!mmio_base) {
+ dev_err(dev,
+ "Invalid memory reference for mmio_base is NULL\n");
+ err = -ENODEV;
+ goto out_error;
+ }
host = scsi_host_alloc(&ufshcd_driver_template,
sizeof(struct ufs_hba));
if (!host) {
- dev_err(&pdev->dev, "scsi_host_alloc failed\n");
+ dev_err(dev, "scsi_host_alloc failed\n");
err = -ENOMEM;
- goto out_disable;
+ goto out_error;
}
hba = shost_priv(host);
-
- err = pci_request_regions(pdev, UFSHCD);
- if (err < 0) {
- dev_err(&pdev->dev, "request regions failed\n");
- goto out_host_put;
- }
-
- hba->mmio_base = pci_ioremap_bar(pdev, 0);
- if (!hba->mmio_base) {
- dev_err(&pdev->dev, "memory map failed\n");
- err = -ENOMEM;
- goto out_release_regions;
- }
-
hba->host = host;
- hba->pdev = pdev;
+ hba->dev = dev;
+ hba->mmio_base = mmio_base;
+ hba->irq = irq;
/* Read capabilities registers */
ufshcd_hba_capabilities(hba);
@@ -1857,17 +1714,14 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Get UFS version supported by the controller */
hba->ufs_version = ufshcd_get_ufs_version(hba);
- err = ufshcd_set_dma_mask(hba);
- if (err) {
- dev_err(&pdev->dev, "set dma mask failed\n");
- goto out_iounmap;
- }
+ /* Get Interrupt bit mask per version */
+ hba->intr_mask = ufshcd_get_intr_mask(hba);
/* Allocate memory for host memory space */
err = ufshcd_memory_alloc(hba);
if (err) {
- dev_err(&pdev->dev, "Memory allocation failed\n");
- goto out_iounmap;
+ dev_err(hba->dev, "Memory allocation failed\n");
+ goto out_disable;
}
/* Configure LRB */
@@ -1885,80 +1739,55 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
init_waitqueue_head(&hba->ufshcd_tm_wait_queue);
/* Initialize work queues */
- INIT_WORK(&hba->uic_workq, ufshcd_uic_cc_handler);
INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
+ /* Initialize UIC command mutex */
+ mutex_init(&hba->uic_cmd_mutex);
+
/* IRQ registration */
- err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+ err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
if (err) {
- dev_err(&pdev->dev, "request irq failed\n");
- goto out_lrb_free;
+ dev_err(hba->dev, "request irq failed\n");
+ goto out_disable;
}
/* Enable SCSI tag mapping */
err = scsi_init_shared_tag_map(host, host->can_queue);
if (err) {
- dev_err(&pdev->dev, "init shared queue failed\n");
- goto out_free_irq;
+ dev_err(hba->dev, "init shared queue failed\n");
+ goto out_disable;
}
- pci_set_drvdata(pdev, hba);
-
- err = scsi_add_host(host, &pdev->dev);
+ err = scsi_add_host(host, hba->dev);
if (err) {
- dev_err(&pdev->dev, "scsi_add_host failed\n");
- goto out_free_irq;
+ dev_err(hba->dev, "scsi_add_host failed\n");
+ goto out_disable;
}
- /* Initialization routine */
- err = ufshcd_initialize_hba(hba);
+ /* Host controller enable */
+ err = ufshcd_hba_enable(hba);
if (err) {
- dev_err(&pdev->dev, "Initialization failed\n");
- goto out_free_irq;
+ dev_err(hba->dev, "Host controller enable failed\n");
+ goto out_remove_scsi_host;
}
+ *hba_handle = hba;
+
+ async_schedule(ufshcd_async_scan, hba);
+
return 0;
-out_free_irq:
- free_irq(pdev->irq, hba);
-out_lrb_free:
- ufshcd_free_hba_memory(hba);
-out_iounmap:
- iounmap(hba->mmio_base);
-out_release_regions:
- pci_release_regions(pdev);
-out_host_put:
- scsi_host_put(host);
+out_remove_scsi_host:
+ scsi_remove_host(hba->host);
out_disable:
- pci_clear_master(pdev);
- pci_disable_device(pdev);
+ scsi_host_put(host);
out_error:
return err;
}
+EXPORT_SYMBOL_GPL(ufshcd_init);
-static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
- { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { } /* terminate list */
-};
-
-MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
-
-static struct pci_driver ufshcd_pci_driver = {
- .name = UFSHCD,
- .id_table = ufshcd_pci_tbl,
- .probe = ufshcd_probe,
- .remove = __devexit_p(ufshcd_remove),
- .shutdown = ufshcd_shutdown,
-#ifdef CONFIG_PM
- .suspend = ufshcd_suspend,
- .resume = ufshcd_resume,
-#endif
-};
-
-module_pci_driver(ufshcd_pci_driver);
-
-MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
- "Vinayak Holikatti <h.vinayak@samsung.com>");
-MODULE_DESCRIPTION("Generic UFS host controller driver");
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("Generic UFS host controller driver Core");
MODULE_LICENSE("GPL");
MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
new file mode 100644
index 0000000..49590ee
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -0,0 +1,211 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd.h
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ *
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * 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 program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#ifndef _UFSHCD_H
+#define _UFSHCD_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+
+#include "ufs.h"
+#include "ufshci.h"
+
+#define UFSHCD "ufshcd"
+#define UFSHCD_DRIVER_VERSION "0.2"
+
+/**
+ * struct uic_command - UIC command structure
+ * @command: UIC command
+ * @argument1: UIC command argument 1
+ * @argument2: UIC command argument 2
+ * @argument3: UIC command argument 3
+ * @cmd_active: Indicate if UIC command is outstanding
+ * @result: UIC command result
+ * @done: UIC command completion
+ */
+struct uic_command {
+ u32 command;
+ u32 argument1;
+ u32 argument2;
+ u32 argument3;
+ int cmd_active;
+ int result;
+ struct completion done;
+};
+
+/**
+ * struct ufshcd_lrb - local reference block
+ * @utr_descriptor_ptr: UTRD address of the command
+ * @ucd_cmd_ptr: UCD address of the command
+ * @ucd_rsp_ptr: Response UPIU address for this command
+ * @ucd_prdt_ptr: PRDT address of the command
+ * @cmd: pointer to SCSI command
+ * @sense_buffer: pointer to sense buffer address of the SCSI command
+ * @sense_bufflen: Length of the sense buffer
+ * @scsi_status: SCSI status of the command
+ * @command_type: SCSI, UFS, Query.
+ * @task_tag: Task tag of the command
+ * @lun: LUN of the command
+ */
+struct ufshcd_lrb {
+ struct utp_transfer_req_desc *utr_descriptor_ptr;
+ struct utp_upiu_cmd *ucd_cmd_ptr;
+ struct utp_upiu_rsp *ucd_rsp_ptr;
+ struct ufshcd_sg_entry *ucd_prdt_ptr;
+
+ struct scsi_cmnd *cmd;
+ u8 *sense_buffer;
+ unsigned int sense_bufflen;
+ int scsi_status;
+
+ int command_type;
+ int task_tag;
+ unsigned int lun;
+};
+
+
+/**
+ * struct ufs_hba - per adapter private structure
+ * @mmio_base: UFSHCI base register address
+ * @ucdl_base_addr: UFS Command Descriptor base address
+ * @utrdl_base_addr: UTP Transfer Request Descriptor base address
+ * @utmrdl_base_addr: UTP Task Management Descriptor base address
+ * @ucdl_dma_addr: UFS Command Descriptor DMA address
+ * @utrdl_dma_addr: UTRDL DMA address
+ * @utmrdl_dma_addr: UTMRDL DMA address
+ * @host: Scsi_Host instance of the driver
+ * @dev: device handle
+ * @lrb: local reference block
+ * @outstanding_tasks: Bits representing outstanding task requests
+ * @outstanding_reqs: Bits representing outstanding transfer requests
+ * @capabilities: UFS Controller Capabilities
+ * @nutrs: Transfer Request Queue depth supported by controller
+ * @nutmrs: Task Management Queue depth supported by controller
+ * @ufs_version: UFS Version to which controller complies
+ * @irq: Irq number of the controller
+ * @active_uic_cmd: handle of active UIC command
+ * @uic_cmd_mutex: mutex for uic command
+ * @ufshcd_tm_wait_queue: wait queue for task management
+ * @tm_condition: condition variable for task management
+ * @ufshcd_state: UFSHCD states
+ * @intr_mask: Interrupt Mask Bits
+ * @feh_workq: Work queue for fatal controller error handling
+ * @errors: HBA errors
+ */
+struct ufs_hba {
+ void __iomem *mmio_base;
+
+ /* Virtual memory reference */
+ struct utp_transfer_cmd_desc *ucdl_base_addr;
+ struct utp_transfer_req_desc *utrdl_base_addr;
+ struct utp_task_req_desc *utmrdl_base_addr;
+
+ /* DMA memory reference */
+ dma_addr_t ucdl_dma_addr;
+ dma_addr_t utrdl_dma_addr;
+ dma_addr_t utmrdl_dma_addr;
+
+ struct Scsi_Host *host;
+ struct device *dev;
+
+ struct ufshcd_lrb *lrb;
+
+ unsigned long outstanding_tasks;
+ unsigned long outstanding_reqs;
+
+ u32 capabilities;
+ int nutrs;
+ int nutmrs;
+ u32 ufs_version;
+ unsigned int irq;
+
+ struct uic_command *active_uic_cmd;
+ struct mutex uic_cmd_mutex;
+
+ wait_queue_head_t ufshcd_tm_wait_queue;
+ unsigned long tm_condition;
+
+ u32 ufshcd_state;
+ u32 intr_mask;
+
+ /* Work Queues */
+ struct work_struct feh_workq;
+
+ /* HBA Errors */
+ u32 errors;
+};
+
+#define ufshcd_writel(hba, val, reg) \
+ writel((val), (hba)->mmio_base + (reg))
+#define ufshcd_readl(hba, reg) \
+ readl((hba)->mmio_base + (reg))
+
+int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
+ unsigned int);
+void ufshcd_remove(struct ufs_hba *);
+
+/**
+ * ufshcd_hba_stop - Send controller to reset state
+ * @hba: per adapter instance
+ */
+static inline void ufshcd_hba_stop(struct ufs_hba *hba)
+{
+ ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE);
+}
+
+#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 6e3510f..d5c5f14 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -2,45 +2,35 @@
* Universal Flash Storage Host controller driver
*
* This code is based on drivers/scsi/ufs/ufshci.h
- * Copyright (C) 2011-2012 Samsung India Software Operations
+ * Copyright (C) 2011-2013 Samsung India Software Operations
*
- * Santosh Yaraganavi <santosh.sy@samsung.com>
- * Vinayak Holikatti <h.vinayak@samsung.com>
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
*
* 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.
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
*/
#ifndef _UFSHCI_H
@@ -242,10 +232,11 @@ enum {
/* Interrupt disable masks */
enum {
/* Interrupt disable mask for UFSHCI v1.0 */
- INTERRUPT_DISABLE_MASK_10 = 0xFFFF,
+ INTERRUPT_MASK_ALL_VER_10 = 0x30FFF,
+ INTERRUPT_MASK_RW_VER_10 = 0x30000,
/* Interrupt disable mask for UFSHCI v1.1 */
- INTERRUPT_DISABLE_MASK_11 = 0x0,
+ INTERRUPT_MASK_ALL_VER_11 = 0x31FFF,
};
/*
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 74ab67a..2168258 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -13,6 +13,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mempool.h>
@@ -20,12 +22,14 @@
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
#include <linux/virtio_scsi.h>
+#include <linux/cpu.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#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 {
@@ -57,27 +61,61 @@ struct virtio_scsi_vq {
struct virtqueue *vq;
};
-/* Per-target queue state */
+/*
+ * 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 {
- /* Protects sg. Lock hierarchy is tgt_lock -> vq_lock. */
+ /* This spinlock never held at the same time as vq_lock. */
spinlock_t tgt_lock;
- /* For sglist construction when adding commands to the virtqueue. */
- struct scatterlist sg[];
+ /* 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;
- struct virtio_scsi_vq ctrl_vq;
- struct virtio_scsi_vq event_vq;
- struct virtio_scsi_vq req_vq;
-
/* Get some buffers ready for event vq */
struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
- struct virtio_scsi_target_state *tgt[];
+ 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;
@@ -107,11 +145,13 @@ static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid)
*
* Called with vq_lock held.
*/
-static void virtscsi_complete_cmd(void *buf)
+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",
@@ -166,32 +206,71 @@ static void virtscsi_complete_cmd(void *buf)
mempool_free(cmd, virtscsi_cmd_pool);
sc->scsi_done(sc);
+
+ atomic_dec(&tgt->reqs);
}
-static void virtscsi_vq_done(struct virtqueue *vq, void (*fn)(void *buf))
+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(buf);
+ 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);
- unsigned long flags;
+ int index = vq->index - VIRTIO_SCSI_VQ_BASE;
+ struct virtio_scsi_vq *req_vq = &vscsi->req_vqs[index];
- spin_lock_irqsave(&vscsi->req_vq.vq_lock, flags);
- virtscsi_vq_done(vq, virtscsi_complete_cmd);
- spin_unlock_irqrestore(&vscsi->req_vq.vq_lock, flags);
+ /*
+ * 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_complete_free(void *buf)
+static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf)
{
struct virtio_scsi_cmd *cmd = buf;
@@ -205,11 +284,8 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
- unsigned long flags;
- spin_lock_irqsave(&vscsi->ctrl_vq.vq_lock, flags);
- virtscsi_vq_done(vq, virtscsi_complete_free);
- spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags);
+ virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free);
};
static int virtscsi_kick_event(struct virtio_scsi *vscsi,
@@ -223,8 +299,8 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
- err = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node,
- GFP_ATOMIC);
+ err = virtqueue_add_inbuf(vscsi->event_vq.vq, &sg, 1, event_node,
+ GFP_ATOMIC);
if (!err)
virtqueue_kick(vscsi->event_vq.vq);
@@ -254,7 +330,7 @@ static void virtscsi_cancel_event_work(struct virtio_scsi *vscsi)
}
static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
- struct virtio_scsi_event *event)
+ struct virtio_scsi_event *event)
{
struct scsi_device *sdev;
struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
@@ -332,7 +408,7 @@ static void virtscsi_handle_event(struct work_struct *work)
virtscsi_kick_event(vscsi, event_node);
}
-static void virtscsi_complete_event(void *buf)
+static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf)
{
struct virtio_scsi_event_node *event_node = buf;
@@ -344,82 +420,65 @@ static void virtscsi_event_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
- unsigned long flags;
- spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
- virtscsi_vq_done(vq, virtscsi_complete_event);
- spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
+ virtscsi_vq_done(vscsi, &vscsi->event_vq, virtscsi_complete_event);
};
-static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
- struct scsi_data_buffer *sdb)
-{
- struct sg_table *table = &sdb->table;
- struct scatterlist *sg_elem;
- unsigned int idx = *p_idx;
- int i;
-
- for_each_sg(table->sgl, sg_elem, table->nents, i)
- sg[idx++] = *sg_elem;
-
- *p_idx = idx;
-}
-
/**
- * virtscsi_map_cmd - map a scsi_cmd to a virtqueue scatterlist
- * @vscsi : virtio_scsi state
+ * virtscsi_add_cmd - add a virtio_scsi_cmd to a virtqueue
+ * @vq : the struct virtqueue we're talking about
* @cmd : command structure
- * @out_num : number of read-only elements
- * @in_num : number of write-only elements
* @req_size : size of the request buffer
* @resp_size : size of the response buffer
- *
- * Called with tgt_lock held.
+ * @gfp : flags to use for memory allocations
*/
-static void virtscsi_map_cmd(struct virtio_scsi_target_state *tgt,
- struct virtio_scsi_cmd *cmd,
- unsigned *out_num, unsigned *in_num,
- size_t req_size, size_t resp_size)
+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 *sg = tgt->sg;
- unsigned int idx = 0;
+ 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_set_buf(&sg[idx++], &cmd->req, req_size);
+ sg_init_one(&req, &cmd->req, req_size);
+ sgs[out_num++] = &req;
/* Data-out buffer. */
- if (sc && sc->sc_data_direction != DMA_FROM_DEVICE)
- virtscsi_map_sgl(sg, &idx, scsi_out(sc));
-
- *out_num = idx;
+ if (out)
+ sgs[out_num++] = out->sgl;
/* Response header. */
- sg_set_buf(&sg[idx++], &cmd->resp, resp_size);
+ sg_init_one(&resp, &cmd->resp, resp_size);
+ sgs[out_num + in_num++] = &resp;
/* Data-in buffer */
- if (sc && sc->sc_data_direction != DMA_TO_DEVICE)
- virtscsi_map_sgl(sg, &idx, scsi_in(sc));
+ if (in)
+ sgs[out_num + in_num++] = in->sgl;
- *in_num = idx - *out_num;
+ return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp);
}
-static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
- struct virtio_scsi_vq *vq,
+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 int out_num, in_num;
unsigned long flags;
int err;
bool needs_kick = false;
- spin_lock_irqsave(&tgt->tgt_lock, flags);
- virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size);
-
- spin_lock(&vq->vq_lock);
- err = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
- spin_unlock(&tgt->tgt_lock);
+ 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);
@@ -430,10 +489,10 @@ static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
return err;
}
-static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
+static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
+ struct virtio_scsi_vq *req_vq,
+ struct scsi_cmnd *sc)
{
- struct virtio_scsi *vscsi = shost_priv(sh);
- struct virtio_scsi_target_state *tgt = vscsi->tgt[sc->device->id];
struct virtio_scsi_cmd *cmd;
int ret;
@@ -467,7 +526,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
- if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd,
+ if (virtscsi_kick_cmd(req_vq, cmd,
sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
GFP_ATOMIC) == 0)
ret = 0;
@@ -478,14 +537,62 @@ 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);
- struct virtio_scsi_target_state *tgt = vscsi->tgt[cmd->sc->device->id];
int ret = FAILED;
cmd->comp = &comp;
- if (virtscsi_kick_cmd(tgt, &vscsi->ctrl_vq, cmd,
+ if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd,
sizeof cmd->req.tmf, sizeof cmd->resp.tmf,
GFP_NOIO) < 0)
goto out;
@@ -547,18 +654,57 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
return virtscsi_tmf(vscsi, cmd);
}
-static struct scsi_host_template virtscsi_host_template = {
+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",
- .queuecommand = virtscsi_queuecommand,
.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) \
@@ -578,29 +724,69 @@ static struct scsi_host_template virtscsi_host_template = {
&__val, sizeof(__val)); \
})
-static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
- struct virtqueue *vq)
+static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
{
- spin_lock_init(&virtscsi_vq->vq_lock);
- virtscsi_vq->vq = vq;
+ 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 - VIRTIO_SCSI_VQ_BASE; i++)
+ virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1);
+
+ vscsi->affinity_hint_set = false;
+ }
}
-static struct virtio_scsi_target_state *virtscsi_alloc_tgt(
- struct virtio_device *vdev, int sg_elems)
+static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
{
- struct virtio_scsi_target_state *tgt;
- gfp_t gfp_mask = GFP_KERNEL;
-
- /* We need extra sg elements at head and tail. */
- tgt = kmalloc(sizeof(*tgt) + sizeof(tgt->sg[0]) * (sg_elems + 2),
- gfp_mask);
+ get_online_cpus();
+ __virtscsi_set_affinity(vscsi, affinity);
+ put_online_cpus();
+}
- if (!tgt)
- return NULL;
+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;
+}
- spin_lock_init(&tgt->tgt_lock);
- sg_init_table(tgt->sg, sg_elems + 2);
- return tgt;
+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)
@@ -614,46 +800,56 @@ static void virtscsi_remove_vqs(struct virtio_device *vdev)
{
struct Scsi_Host *sh = virtio_scsi_host(vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
- u32 i, num_targets;
+
+ virtscsi_set_affinity(vscsi, false);
/* Stop all the virtqueues. */
vdev->config->reset(vdev);
- num_targets = sh->max_id;
- for (i = 0; i < num_targets; i++) {
- kfree(vscsi->tgt[i]);
- vscsi->tgt[i] = NULL;
- }
-
vdev->config->del_vqs(vdev);
}
static int virtscsi_init(struct virtio_device *vdev,
- struct virtio_scsi *vscsi, int num_targets)
+ struct virtio_scsi *vscsi)
{
int err;
- struct virtqueue *vqs[3];
- u32 i, sg_elems;
+ 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;
+ }
- vq_callback_t *callbacks[] = {
- virtscsi_ctrl_done,
- virtscsi_event_done,
- virtscsi_req_done
- };
- const char *names[] = {
- "control",
- "event",
- "request"
- };
+ 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, 3, vqs, callbacks, names);
+ err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names);
if (err)
- return err;
+ goto out;
virtscsi_init_vq(&vscsi->ctrl_vq, vqs[0]);
virtscsi_init_vq(&vscsi->event_vq, vqs[1]);
- virtscsi_init_vq(&vscsi->req_vq, vqs[2]);
+ 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);
@@ -661,38 +857,39 @@ static int virtscsi_init(struct virtio_device *vdev,
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG))
virtscsi_kick_event_all(vscsi);
- /* We need to know how many segments before we allocate. */
- sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
-
- for (i = 0; i < num_targets; i++) {
- vscsi->tgt[i] = virtscsi_alloc_tgt(vdev, sg_elems);
- if (!vscsi->tgt[i]) {
- err = -ENOMEM;
- goto out;
- }
- }
err = 0;
out:
+ kfree(names);
+ kfree(callbacks);
+ kfree(vqs);
if (err)
virtscsi_remove_vqs(vdev);
return err;
}
-static int __devinit virtscsi_probe(struct virtio_device *vdev)
+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;
- /* Allocate memory and link the structs together. */
num_targets = virtscsi_config_get(vdev, max_target) + 1;
- shost = scsi_host_alloc(&virtscsi_host_template,
- sizeof(*vscsi)
- + num_targets * sizeof(struct virtio_scsi_target_state));
+ 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;
@@ -700,12 +897,20 @@ static int __devinit virtscsi_probe(struct virtio_device *vdev)
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, num_targets);
+ 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;
@@ -733,7 +938,7 @@ virtscsi_init_failed:
return err;
}
-static void __devexit virtscsi_remove(struct virtio_device *vdev)
+static void virtscsi_remove(struct virtio_device *vdev)
{
struct Scsi_Host *shost = virtio_scsi_host(vdev);
struct virtio_scsi *vscsi = shost_priv(shost);
@@ -743,6 +948,8 @@ static void __devexit virtscsi_remove(struct virtio_device *vdev)
scsi_remove_host(shost);
+ unregister_hotcpu_notifier(&vscsi->nb);
+
virtscsi_remove_vqs(vdev);
scsi_host_put(shost);
}
@@ -759,7 +966,7 @@ static int virtscsi_restore(struct virtio_device *vdev)
struct Scsi_Host *sh = virtio_scsi_host(vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
- return virtscsi_init(vdev, vscsi, sh->max_id);
+ return virtscsi_init(vdev, vscsi);
}
#endif
@@ -785,7 +992,7 @@ static struct virtio_driver virtio_scsi_driver = {
.freeze = virtscsi_freeze,
.restore = virtscsi_restore,
#endif
- .remove = __devexit_p(virtscsi_remove),
+ .remove = virtscsi_remove,
};
static int __init init(void)
@@ -794,8 +1001,7 @@ static int __init init(void)
virtscsi_cmd_cache = KMEM_CACHE(virtio_scsi_cmd, 0);
if (!virtscsi_cmd_cache) {
- printk(KERN_ERR "kmem_cache_create() for "
- "virtscsi_cmd_cache failed\n");
+ pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n");
goto error;
}
@@ -804,8 +1010,7 @@ static int __init init(void)
mempool_create_slab_pool(VIRTIO_SCSI_MEMPOOL_SZ,
virtscsi_cmd_cache);
if (!virtscsi_cmd_pool) {
- printk(KERN_ERR "mempool_create() for"
- "virtscsi_cmd_pool failed\n");
+ pr_err("mempool_create() for virtscsi_cmd_pool failed\n");
goto error;
}
ret = register_virtio_driver(&virtio_scsi_driver);
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 20b3a48..3bfaa66 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -397,7 +397,7 @@ static void pvscsi_unmap_buffers(const struct pvscsi_adapter *adapter,
SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE);
}
-static int __devinit pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
+static int pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
{
adapter->rings_state = pci_alloc_consistent(adapter->dev, PAGE_SIZE,
&adapter->ringStatePA);
@@ -1152,7 +1152,7 @@ static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
* just use a statically allocated scatter list.
*
*/
-static int __devinit pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
+static int pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
{
struct pvscsi_ctx *ctx;
int i;
@@ -1233,8 +1233,7 @@ exit:
return numPhys;
}
-static int __devinit pvscsi_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct pvscsi_adapter *adapter;
struct Scsi_Host *host;
@@ -1454,7 +1453,7 @@ static struct pci_driver pvscsi_pci_driver = {
.name = "vmw_pvscsi",
.id_table = pvscsi_pci_tbl,
.probe = pvscsi_probe,
- .remove = __devexit_p(pvscsi_remove),
+ .remove = pvscsi_remove,
.shutdown = pvscsi_shutdown,
};
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index c0ee4ea..41883a8 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -2054,22 +2054,16 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
printk(" Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE);
}
-int
-wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
+int wd33c93_write_info(struct Scsi_Host *instance, char *buf, int len)
{
-
#ifdef PROC_INTERFACE
-
char *bp;
- char tbuf[128];
struct WD33C93_hostdata *hd;
- struct scsi_cmnd *cmd;
int x;
- static int stop = 0;
hd = (struct WD33C93_hostdata *) instance->hostdata;
-/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
+/* We accept the following
* keywords (same format as command-line, but arguments are not optional):
* debug
* disconnect
@@ -2083,145 +2077,124 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
* nosync
*/
- if (in) {
- buf[len] = '\0';
- for (bp = buf; *bp; ) {
- while (',' == *bp || ' ' == *bp)
- ++bp;
- if (!strncmp(bp, "debug:", 6)) {
- hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
- } else if (!strncmp(bp, "disconnect:", 11)) {
- x = simple_strtoul(bp+11, &bp, 0);
- if (x < DIS_NEVER || x > DIS_ALWAYS)
- x = DIS_ADAPTIVE;
- hd->disconnect = x;
- } else if (!strncmp(bp, "period:", 7)) {
+ buf[len] = '\0';
+ for (bp = buf; *bp; ) {
+ while (',' == *bp || ' ' == *bp)
+ ++bp;
+ if (!strncmp(bp, "debug:", 6)) {
+ hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
+ } else if (!strncmp(bp, "disconnect:", 11)) {
+ x = simple_strtoul(bp+11, &bp, 0);
+ if (x < DIS_NEVER || x > DIS_ALWAYS)
+ x = DIS_ADAPTIVE;
+ hd->disconnect = x;
+ } else if (!strncmp(bp, "period:", 7)) {
+ x = simple_strtoul(bp+7, &bp, 0);
+ hd->default_sx_per =
+ hd->sx_table[round_period((unsigned int) x,
+ hd->sx_table)].period_ns;
+ } else if (!strncmp(bp, "resync:", 7)) {
+ set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
+ } else if (!strncmp(bp, "proc:", 5)) {
+ hd->proc = simple_strtoul(bp+5, &bp, 0);
+ } else if (!strncmp(bp, "nodma:", 6)) {
+ hd->no_dma = simple_strtoul(bp+6, &bp, 0);
+ } else if (!strncmp(bp, "level2:", 7)) {
+ hd->level2 = simple_strtoul(bp+7, &bp, 0);
+ } else if (!strncmp(bp, "burst:", 6)) {
+ hd->dma_mode =
+ simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
+ } else if (!strncmp(bp, "fast:", 5)) {
+ x = !!simple_strtol(bp+5, &bp, 0);
+ if (x != hd->fast)
+ set_resync(hd, 0xff);
+ hd->fast = x;
+ } else if (!strncmp(bp, "nosync:", 7)) {
x = simple_strtoul(bp+7, &bp, 0);
- hd->default_sx_per =
- hd->sx_table[round_period((unsigned int) x,
- hd->sx_table)].period_ns;
- } else if (!strncmp(bp, "resync:", 7)) {
- set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
- } else if (!strncmp(bp, "proc:", 5)) {
- hd->proc = simple_strtoul(bp+5, &bp, 0);
- } else if (!strncmp(bp, "nodma:", 6)) {
- hd->no_dma = simple_strtoul(bp+6, &bp, 0);
- } else if (!strncmp(bp, "level2:", 7)) {
- hd->level2 = simple_strtoul(bp+7, &bp, 0);
- } else if (!strncmp(bp, "burst:", 6)) {
- hd->dma_mode =
- simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
- } else if (!strncmp(bp, "fast:", 5)) {
- x = !!simple_strtol(bp+5, &bp, 0);
- if (x != hd->fast)
- set_resync(hd, 0xff);
- hd->fast = x;
- } else if (!strncmp(bp, "nosync:", 7)) {
- x = simple_strtoul(bp+7, &bp, 0);
- set_resync(hd, x ^ hd->no_sync);
- hd->no_sync = x;
- } else {
- break; /* unknown keyword,syntax-error,... */
- }
+ set_resync(hd, x ^ hd->no_sync);
+ hd->no_sync = x;
+ } else {
+ break; /* unknown keyword,syntax-error,... */
}
- return len;
}
+ return len;
+#else
+ return 0;
+#endif
+}
+
+int
+wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance)
+{
+#ifdef PROC_INTERFACE
+ struct WD33C93_hostdata *hd;
+ struct scsi_cmnd *cmd;
+ int x;
+
+ hd = (struct WD33C93_hostdata *) instance->hostdata;
spin_lock_irq(&hd->lock);
- bp = buf;
- *bp = '\0';
- if (hd->proc & PR_VERSION) {
- sprintf(tbuf, "\nVersion %s - %s.",
+ if (hd->proc & PR_VERSION)
+ seq_printf(m, "\nVersion %s - %s.",
WD33C93_VERSION, WD33C93_DATE);
- strcat(bp, tbuf);
- }
+
if (hd->proc & PR_INFO) {
- sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
+ seq_printf(m, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
" dma_mode=%02x fast=%d",
hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
- strcat(bp, tbuf);
- strcat(bp, "\nsync_xfer[] = ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
- strcat(bp, tbuf);
- }
- strcat(bp, "\nsync_stat[] = ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
- strcat(bp, tbuf);
- }
+ seq_printf(m, "\nsync_xfer[] = ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%02x", hd->sync_xfer[x]);
+ seq_printf(m, "\nsync_stat[] = ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%02x", hd->sync_stat[x]);
}
#ifdef PROC_STATISTICS
if (hd->proc & PR_STATISTICS) {
- strcat(bp, "\ncommands issued: ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
- strcat(bp, tbuf);
- }
- strcat(bp, "\ndisconnects allowed:");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
- strcat(bp, tbuf);
- }
- strcat(bp, "\ndisconnects done: ");
- for (x = 0; x < 7; x++) {
- sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
- strcat(bp, tbuf);
- }
- sprintf(tbuf,
+ seq_printf(m, "\ncommands issued: ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
+ seq_printf(m, "\ndisconnects allowed:");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
+ seq_printf(m, "\ndisconnects done: ");
+ for (x = 0; x < 7; x++)
+ seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
+ seq_printf(m,
"\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
- strcat(bp, tbuf);
}
#endif
if (hd->proc & PR_CONNECTED) {
- strcat(bp, "\nconnected: ");
+ seq_printf(m, "\nconnected: ");
if (hd->connected) {
cmd = (struct scsi_cmnd *) hd->connected;
- sprintf(tbuf, " %d:%d(%02x)",
+ seq_printf(m, " %d:%d(%02x)",
cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
- strcat(bp, tbuf);
}
}
if (hd->proc & PR_INPUTQ) {
- strcat(bp, "\ninput_Q: ");
+ seq_printf(m, "\ninput_Q: ");
cmd = (struct scsi_cmnd *) hd->input_Q;
while (cmd) {
- sprintf(tbuf, " %d:%d(%02x)",
+ seq_printf(m, " %d:%d(%02x)",
cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
- strcat(bp, tbuf);
cmd = (struct scsi_cmnd *) cmd->host_scribble;
}
}
if (hd->proc & PR_DISCQ) {
- strcat(bp, "\ndisconnected_Q:");
+ seq_printf(m, "\ndisconnected_Q:");
cmd = (struct scsi_cmnd *) hd->disconnected_Q;
while (cmd) {
- sprintf(tbuf, " %d:%d(%02x)",
+ seq_printf(m, " %d:%d(%02x)",
cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
- strcat(bp, tbuf);
cmd = (struct scsi_cmnd *) cmd->host_scribble;
}
}
- strcat(bp, "\n");
+ seq_printf(m, "\n");
spin_unlock_irq(&hd->lock);
- *start = buf;
- if (stop) {
- stop = 0;
- return 0;
- }
- if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */
- stop = 1;
- if (hd->proc & PR_STOP) /* stop every other time */
- stop = 1;
- return strlen(bp);
-
-#else /* PROC_INTERFACE */
-
- return 0;
-
#endif /* PROC_INTERFACE */
-
+ return 0;
}
EXPORT_SYMBOL(wd33c93_host_reset);
@@ -2229,4 +2202,5 @@ EXPORT_SYMBOL(wd33c93_init);
EXPORT_SYMBOL(wd33c93_abort);
EXPORT_SYMBOL(wd33c93_queuecommand);
EXPORT_SYMBOL(wd33c93_intr);
-EXPORT_SYMBOL(wd33c93_proc_info);
+EXPORT_SYMBOL(wd33c93_show_info);
+EXPORT_SYMBOL(wd33c93_write_info);
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 3b463d7..08abe50 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -345,7 +345,8 @@ void wd33c93_init (struct Scsi_Host *instance, const wd33c93_regs regs,
int wd33c93_abort (struct scsi_cmnd *cmd);
int wd33c93_queuecommand (struct Scsi_Host *h, struct scsi_cmnd *cmd);
void wd33c93_intr (struct Scsi_Host *instance);
-int wd33c93_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+int wd33c93_show_info(struct seq_file *, struct Scsi_Host *);
+int wd33c93_write_info(struct Scsi_Host *, char *, int);
int wd33c93_host_reset (struct scsi_cmnd *);
#endif /* WD33C93_H */
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index d89a5df..f9a6e4b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1296,9 +1296,9 @@ static void wd7000_revision(Adapter * host)
#undef SPRINTF
-#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
+#define SPRINTF(args...) { seq_printf(m, ## args); }
-static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host)
+static int wd7000_set_info(struct Scsi_Host *host, char *buffer, int length)
{
dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length);
@@ -1310,22 +1310,15 @@ static int wd7000_set_info(char *buffer, int length, struct Scsi_Host *host)
}
-static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
+static int wd7000_show_info(struct seq_file *m, struct Scsi_Host *host)
{
Adapter *adapter = (Adapter *)host->hostdata;
unsigned long flags;
- char *pos = buffer;
#ifdef WD7000_DEBUG
Mailbox *ogmbs, *icmbs;
short count;
#endif
- /*
- * Has data been written to the file ?
- */
- if (inout)
- return (wd7000_set_info(buffer, length, host));
-
spin_lock_irqsave(host->host_lock, flags);
SPRINTF("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", host->host_no, adapter->rev1, adapter->rev2);
SPRINTF(" IO base: 0x%x\n", adapter->iobase);
@@ -1368,17 +1361,7 @@ static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start,
spin_unlock_irqrestore(host->host_lock, flags);
- /*
- * Calculate start of next buffer, and return value.
- */
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return (0);
- else if ((pos - buffer - offset) < length)
- return (pos - buffer - offset);
- else
- return (length);
+ return 0;
}
@@ -1413,7 +1396,8 @@ static __init int wd7000_detect(struct scsi_host_template *tpnt)
for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
tpnt->proc_name = "wd7000";
- tpnt->proc_info = &wd7000_proc_info;
+ tpnt->show_info = &wd7000_show_info;
+ tpnt->write_info = wd7000_set_info;
/*
* Set up SCB free list, which is shared by all adapters
@@ -1658,7 +1642,8 @@ MODULE_LICENSE("GPL");
static struct scsi_host_template driver_template = {
.proc_name = "wd7000",
- .proc_info = wd7000_proc_info,
+ .show_info = wd7000_show_info,
+ .write_info = wd7000_set_info,
.name = "Western Digital WD-7000",
.detect = wd7000_detect,
.release = wd7000_release,
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 27e84e4..97ccb03 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -182,7 +182,7 @@ static struct parisc_driver zalon_driver = {
.name = "zalon",
.id_table = zalon_tbl,
.probe = zalon_probe,
- .remove = __devexit_p(zalon_remove),
+ .remove = zalon_remove,
};
static int __init zalon7xx_init(void)
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c
index e17764d..cbf3476 100644
--- a/drivers/scsi/zorro7xx.c
+++ b/drivers/scsi/zorro7xx.c
@@ -38,7 +38,7 @@ static struct zorro_driver_data {
const char *name;
unsigned long offset;
int absolute; /* offset is absolute address */
-} zorro7xx_driver_data[] __devinitdata = {
+} zorro7xx_driver_data[] = {
{ .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
{ .name = "WarpEngine 40xx", .offset = 0x40000 },
{ .name = "A4091", .offset = 0x800000 },
@@ -46,7 +46,7 @@ static struct zorro_driver_data {
{ 0 }
};
-static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id zorro7xx_zorro_tbl[] = {
{
.id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
.driver_data = (unsigned long)&zorro7xx_driver_data[0],
@@ -71,8 +71,8 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);
-static int __devinit zorro7xx_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
+static int zorro7xx_init_one(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
{
struct Scsi_Host *host;
struct NCR_700_Host_Parameters *hostdata;
@@ -150,7 +150,7 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z,
return -ENODEV;
}
-static __devexit void zorro7xx_remove_one(struct zorro_dev *z)
+static void zorro7xx_remove_one(struct zorro_dev *z)
{
struct Scsi_Host *host = zorro_get_drvdata(z);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
@@ -167,7 +167,7 @@ static struct zorro_driver zorro7xx_driver = {
.name = "zorro7xx-scsi",
.id_table = zorro7xx_zorro_tbl,
.probe = zorro7xx_init_one,
- .remove = __devexit_p(zorro7xx_remove_one),
+ .remove = zorro7xx_remove_one,
};
static int __init zorro7xx_scsi_init(void)
OpenPOWER on IntegriCloud