diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-31 15:02:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-31 15:02:41 -0400 |
commit | 054552272e6e152ff40f8b7f164dd390a5a62097 (patch) | |
tree | 9be4ee91a0ea090672f6ea1be2f6e6eef027d810 /drivers | |
parent | 5b461209d07ab9a9284760f6ffe696de558031a3 (diff) | |
parent | 1ff2f40305772b159a91c19590ee159d3a504afc (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull final round of SCSI updates from James Bottomley:
"This is primarily another round of driver updates (bnx2fc, qla2xxx,
qla4xxx) including the target mode driver for qla2xxx. We've also got
a couple of regression fixes (async scanning, broken this merge window
and a fix to a long standing break in the scsi_wait_scan module)."
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (45 commits)
[SCSI] fix scsi_wait_scan
[SCSI] fix async probe regression
[SCSI] be2iscsi: fix dma free size mismatch regression
[SCSI] qla4xxx: Update driver version to 5.02.00-k17
[SCSI] qla4xxx: Capture minidump for ISP82XX on firmware failure
[SCSI] qla4xxx: Add change_queue_depth API support
[SCSI] qla4xxx: Fix clear ddb mbx command failure issue.
[SCSI] qla4xxx: Fix kernel panic during discovery logout.
[SCSI] qla4xxx: Correct early completion of pending mbox.
[SCSI] fcoe, bnx2fc, libfcoe: SW FCoE and bnx2fc use FCoE Syfs
[SCSI] libfcoe: Add fcoe_sysfs
[SCSI] bnx2fc: Allocate fcoe_ctlr with bnx2fc_interface, not as a member
[SCSI] fcoe: Allocate fcoe_ctlr with fcoe_interface, not as a member
[SCSI] Fix dm-multipath starvation when scsi host is busy
[SCSI] ufs: fix potential NULL pointer dereferencing error in ufshcd_prove.
[SCSI] qla2xxx: don't free pool that wasn't allocated
[SCSI] mptfusion: unlock on error in mpt_config()
[SCSI] tcm_qla2xxx: Add >= 24xx series fabric module for target-core
[SCSI] qla2xxx: Add LLD target-mode infrastructure for >= 24xx series
[SCSI] Revert "qla2xxx: During loopdown perform Diagnostic loopback."
...
Diffstat (limited to 'drivers')
53 files changed, 11897 insertions, 674 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a5c591ffe395..444143e5f28c 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -6483,6 +6483,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
6483 | printk(MYIOC_s_INFO_FMT "%s: host reset in" | 6483 | printk(MYIOC_s_INFO_FMT "%s: host reset in" |
6484 | " progress mpt_config timed out.!!\n", | 6484 | " progress mpt_config timed out.!!\n", |
6485 | __func__, ioc->name); | 6485 | __func__, ioc->name); |
6486 | mutex_unlock(&ioc->mptbase_cmds.mutex); | ||
6486 | return -EFAULT; | 6487 | return -EFAULT; |
6487 | } | 6488 | } |
6488 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | 6489 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 01bb04cd9e75..2a096795b9aa 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -571,13 +571,12 @@ free_cmd: | |||
571 | static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, | 571 | static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, |
572 | int iscsi_cmd, int size) | 572 | int iscsi_cmd, int size) |
573 | { | 573 | { |
574 | cmd->va = pci_alloc_consistent(phba->ctrl.pdev, sizeof(size), | 574 | cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma); |
575 | &cmd->dma); | ||
576 | if (!cmd->va) { | 575 | if (!cmd->va) { |
577 | SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n"); | 576 | SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n"); |
578 | return -ENOMEM; | 577 | return -ENOMEM; |
579 | } | 578 | } |
580 | memset(cmd->va, 0, sizeof(size)); | 579 | memset(cmd->va, 0, size); |
581 | cmd->size = size; | 580 | cmd->size = size; |
582 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); | 581 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); |
583 | return 0; | 582 | return 0; |
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 8b6c6bf7837e..b83927440171 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c | |||
@@ -426,6 +426,23 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) | |||
426 | vshost = vport->drv_port.im_port->shost; | 426 | vshost = vport->drv_port.im_port->shost; |
427 | fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn); | 427 | fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn); |
428 | fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); | 428 | fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); |
429 | fc_host_supported_classes(vshost) = FC_COS_CLASS3; | ||
430 | |||
431 | memset(fc_host_supported_fc4s(vshost), 0, | ||
432 | sizeof(fc_host_supported_fc4s(vshost))); | ||
433 | |||
434 | /* For FCP type 0x08 */ | ||
435 | if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM) | ||
436 | fc_host_supported_fc4s(vshost)[2] = 1; | ||
437 | |||
438 | /* For fibre channel services type 0x20 */ | ||
439 | fc_host_supported_fc4s(vshost)[7] = 1; | ||
440 | |||
441 | fc_host_supported_speeds(vshost) = | ||
442 | bfad_im_supported_speeds(&bfad->bfa); | ||
443 | fc_host_maxframe_size(vshost) = | ||
444 | bfa_fcport_get_maxfrsize(&bfad->bfa); | ||
445 | |||
429 | fc_vport->dd_data = vport; | 446 | fc_vport->dd_data = vport; |
430 | vport->drv_port.im_port->fc_vport = fc_vport; | 447 | vport->drv_port.im_port->fc_vport = fc_vport; |
431 | } else if (rc == BFA_STATUS_INVALID_WWN) | 448 | } else if (rc == BFA_STATUS_INVALID_WWN) |
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 3153923f5b60..1ac09afe35ee 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c | |||
@@ -987,7 +987,7 @@ done: | |||
987 | return 0; | 987 | return 0; |
988 | } | 988 | } |
989 | 989 | ||
990 | static u32 | 990 | u32 |
991 | bfad_im_supported_speeds(struct bfa_s *bfa) | 991 | bfad_im_supported_speeds(struct bfa_s *bfa) |
992 | { | 992 | { |
993 | struct bfa_ioc_attr_s *ioc_attr; | 993 | struct bfa_ioc_attr_s *ioc_attr; |
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h index 0814367ef101..f6c1023e502a 100644 --- a/drivers/scsi/bfa/bfad_im.h +++ b/drivers/scsi/bfa/bfad_im.h | |||
@@ -37,6 +37,7 @@ int bfad_im_scsi_host_alloc(struct bfad_s *bfad, | |||
37 | struct bfad_im_port_s *im_port, struct device *dev); | 37 | struct bfad_im_port_s *im_port, struct device *dev); |
38 | void bfad_im_scsi_host_free(struct bfad_s *bfad, | 38 | void bfad_im_scsi_host_free(struct bfad_s *bfad, |
39 | struct bfad_im_port_s *im_port); | 39 | struct bfad_im_port_s *im_port); |
40 | u32 bfad_im_supported_speeds(struct bfa_s *bfa); | ||
40 | 41 | ||
41 | #define MAX_FCP_TARGET 1024 | 42 | #define MAX_FCP_TARGET 1024 |
42 | #define MAX_FCP_LUN 16384 | 43 | #define MAX_FCP_LUN 16384 |
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index a4953ef9e53a..0578fa0dc14b 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h | |||
@@ -62,7 +62,7 @@ | |||
62 | #include "bnx2fc_constants.h" | 62 | #include "bnx2fc_constants.h" |
63 | 63 | ||
64 | #define BNX2FC_NAME "bnx2fc" | 64 | #define BNX2FC_NAME "bnx2fc" |
65 | #define BNX2FC_VERSION "1.0.10" | 65 | #define BNX2FC_VERSION "1.0.11" |
66 | 66 | ||
67 | #define PFX "bnx2fc: " | 67 | #define PFX "bnx2fc: " |
68 | 68 | ||
@@ -228,13 +228,16 @@ struct bnx2fc_interface { | |||
228 | struct packet_type fip_packet_type; | 228 | struct packet_type fip_packet_type; |
229 | struct workqueue_struct *timer_work_queue; | 229 | struct workqueue_struct *timer_work_queue; |
230 | struct kref kref; | 230 | struct kref kref; |
231 | struct fcoe_ctlr ctlr; | ||
232 | u8 vlan_enabled; | 231 | u8 vlan_enabled; |
233 | int vlan_id; | 232 | int vlan_id; |
234 | bool enabled; | 233 | bool enabled; |
235 | }; | 234 | }; |
236 | 235 | ||
237 | #define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_interface, ctlr) | 236 | #define bnx2fc_from_ctlr(x) \ |
237 | ((struct bnx2fc_interface *)((x) + 1)) | ||
238 | |||
239 | #define bnx2fc_to_ctlr(x) \ | ||
240 | ((struct fcoe_ctlr *)(((struct fcoe_ctlr *)(x)) - 1)) | ||
238 | 241 | ||
239 | struct bnx2fc_lport { | 242 | struct bnx2fc_lport { |
240 | struct list_head list; | 243 | struct list_head list; |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c index ce0ce3e32f33..bdbbb13b8534 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/drivers/scsi/bnx2fc/bnx2fc_els.c | |||
@@ -854,7 +854,6 @@ static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, | |||
854 | struct fc_exch *exch = fc_seq_exch(seq); | 854 | struct fc_exch *exch = fc_seq_exch(seq); |
855 | struct fc_lport *lport = exch->lp; | 855 | struct fc_lport *lport = exch->lp; |
856 | u8 *mac; | 856 | u8 *mac; |
857 | struct fc_frame_header *fh; | ||
858 | u8 op; | 857 | u8 op; |
859 | 858 | ||
860 | if (IS_ERR(fp)) | 859 | if (IS_ERR(fp)) |
@@ -862,13 +861,6 @@ static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, | |||
862 | 861 | ||
863 | mac = fr_cb(fp)->granted_mac; | 862 | mac = fr_cb(fp)->granted_mac; |
864 | if (is_zero_ether_addr(mac)) { | 863 | if (is_zero_ether_addr(mac)) { |
865 | fh = fc_frame_header_get(fp); | ||
866 | if (fh->fh_type != FC_TYPE_ELS) { | ||
867 | printk(KERN_ERR PFX "bnx2fc_flogi_resp:" | ||
868 | "fh_type != FC_TYPE_ELS\n"); | ||
869 | fc_frame_free(fp); | ||
870 | return; | ||
871 | } | ||
872 | op = fc_frame_payload_op(fp); | 864 | op = fc_frame_payload_op(fp); |
873 | if (lport->vport) { | 865 | if (lport->vport) { |
874 | if (op == ELS_LS_RJT) { | 866 | if (op == ELS_LS_RJT) { |
@@ -878,12 +870,10 @@ static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, | |||
878 | return; | 870 | return; |
879 | } | 871 | } |
880 | } | 872 | } |
881 | if (fcoe_ctlr_recv_flogi(fip, lport, fp)) { | 873 | fcoe_ctlr_recv_flogi(fip, lport, fp); |
882 | fc_frame_free(fp); | ||
883 | return; | ||
884 | } | ||
885 | } | 874 | } |
886 | fip->update_mac(lport, mac); | 875 | if (!is_zero_ether_addr(mac)) |
876 | fip->update_mac(lport, mac); | ||
887 | done: | 877 | done: |
888 | fc_lport_flogi_resp(seq, fp, lport); | 878 | fc_lport_flogi_resp(seq, fp, lport); |
889 | } | 879 | } |
@@ -910,7 +900,7 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did, | |||
910 | { | 900 | { |
911 | struct fcoe_port *port = lport_priv(lport); | 901 | struct fcoe_port *port = lport_priv(lport); |
912 | struct bnx2fc_interface *interface = port->priv; | 902 | struct bnx2fc_interface *interface = port->priv; |
913 | struct fcoe_ctlr *fip = &interface->ctlr; | 903 | struct fcoe_ctlr *fip = bnx2fc_to_ctlr(interface); |
914 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 904 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
915 | 905 | ||
916 | switch (op) { | 906 | switch (op) { |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index c1c6a92a0b98..f52f668fd247 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c | |||
@@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); | |||
22 | 22 | ||
23 | #define DRV_MODULE_NAME "bnx2fc" | 23 | #define DRV_MODULE_NAME "bnx2fc" |
24 | #define DRV_MODULE_VERSION BNX2FC_VERSION | 24 | #define DRV_MODULE_VERSION BNX2FC_VERSION |
25 | #define DRV_MODULE_RELDATE "Jan 22, 2011" | 25 | #define DRV_MODULE_RELDATE "Apr 24, 2012" |
26 | 26 | ||
27 | 27 | ||
28 | static char version[] __devinitdata = | 28 | static char version[] __devinitdata = |
@@ -54,6 +54,7 @@ static struct cnic_ulp_ops bnx2fc_cnic_cb; | |||
54 | static struct libfc_function_template bnx2fc_libfc_fcn_templ; | 54 | static struct libfc_function_template bnx2fc_libfc_fcn_templ; |
55 | static struct scsi_host_template bnx2fc_shost_template; | 55 | static struct scsi_host_template bnx2fc_shost_template; |
56 | static struct fc_function_template bnx2fc_transport_function; | 56 | static struct fc_function_template bnx2fc_transport_function; |
57 | static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ; | ||
57 | static struct fc_function_template bnx2fc_vport_xport_function; | 58 | static struct fc_function_template bnx2fc_vport_xport_function; |
58 | static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode); | 59 | static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode); |
59 | static void __bnx2fc_destroy(struct bnx2fc_interface *interface); | 60 | static void __bnx2fc_destroy(struct bnx2fc_interface *interface); |
@@ -88,6 +89,7 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport); | |||
88 | static void bnx2fc_stop(struct bnx2fc_interface *interface); | 89 | static void bnx2fc_stop(struct bnx2fc_interface *interface); |
89 | static int __init bnx2fc_mod_init(void); | 90 | static int __init bnx2fc_mod_init(void); |
90 | static void __exit bnx2fc_mod_exit(void); | 91 | static void __exit bnx2fc_mod_exit(void); |
92 | static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev); | ||
91 | 93 | ||
92 | unsigned int bnx2fc_debug_level; | 94 | unsigned int bnx2fc_debug_level; |
93 | module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR); | 95 | module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR); |
@@ -118,6 +120,41 @@ static void bnx2fc_get_lesb(struct fc_lport *lport, | |||
118 | __fcoe_get_lesb(lport, fc_lesb, netdev); | 120 | __fcoe_get_lesb(lport, fc_lesb, netdev); |
119 | } | 121 | } |
120 | 122 | ||
123 | static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) | ||
124 | { | ||
125 | struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); | ||
126 | struct net_device *netdev = bnx2fc_netdev(fip->lp); | ||
127 | struct fcoe_fc_els_lesb *fcoe_lesb; | ||
128 | struct fc_els_lesb fc_lesb; | ||
129 | |||
130 | __fcoe_get_lesb(fip->lp, &fc_lesb, netdev); | ||
131 | fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb); | ||
132 | |||
133 | ctlr_dev->lesb.lesb_link_fail = | ||
134 | ntohl(fcoe_lesb->lesb_link_fail); | ||
135 | ctlr_dev->lesb.lesb_vlink_fail = | ||
136 | ntohl(fcoe_lesb->lesb_vlink_fail); | ||
137 | ctlr_dev->lesb.lesb_miss_fka = | ||
138 | ntohl(fcoe_lesb->lesb_miss_fka); | ||
139 | ctlr_dev->lesb.lesb_symb_err = | ||
140 | ntohl(fcoe_lesb->lesb_symb_err); | ||
141 | ctlr_dev->lesb.lesb_err_block = | ||
142 | ntohl(fcoe_lesb->lesb_err_block); | ||
143 | ctlr_dev->lesb.lesb_fcs_error = | ||
144 | ntohl(fcoe_lesb->lesb_fcs_error); | ||
145 | } | ||
146 | EXPORT_SYMBOL(bnx2fc_ctlr_get_lesb); | ||
147 | |||
148 | static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) | ||
149 | { | ||
150 | struct fcoe_ctlr_device *ctlr_dev = | ||
151 | fcoe_fcf_dev_to_ctlr_dev(fcf_dev); | ||
152 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
153 | struct bnx2fc_interface *fcoe = fcoe_ctlr_priv(ctlr); | ||
154 | |||
155 | fcf_dev->vlan_id = fcoe->vlan_id; | ||
156 | } | ||
157 | |||
121 | static void bnx2fc_clean_rx_queue(struct fc_lport *lp) | 158 | static void bnx2fc_clean_rx_queue(struct fc_lport *lp) |
122 | { | 159 | { |
123 | struct fcoe_percpu_s *bg; | 160 | struct fcoe_percpu_s *bg; |
@@ -244,6 +281,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
244 | struct sk_buff *skb; | 281 | struct sk_buff *skb; |
245 | struct fc_frame_header *fh; | 282 | struct fc_frame_header *fh; |
246 | struct bnx2fc_interface *interface; | 283 | struct bnx2fc_interface *interface; |
284 | struct fcoe_ctlr *ctlr; | ||
247 | struct bnx2fc_hba *hba; | 285 | struct bnx2fc_hba *hba; |
248 | struct fcoe_port *port; | 286 | struct fcoe_port *port; |
249 | struct fcoe_hdr *hp; | 287 | struct fcoe_hdr *hp; |
@@ -256,6 +294,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
256 | 294 | ||
257 | port = (struct fcoe_port *)lport_priv(lport); | 295 | port = (struct fcoe_port *)lport_priv(lport); |
258 | interface = port->priv; | 296 | interface = port->priv; |
297 | ctlr = bnx2fc_to_ctlr(interface); | ||
259 | hba = interface->hba; | 298 | hba = interface->hba; |
260 | 299 | ||
261 | fh = fc_frame_header_get(fp); | 300 | fh = fc_frame_header_get(fp); |
@@ -268,12 +307,12 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
268 | } | 307 | } |
269 | 308 | ||
270 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) { | 309 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) { |
271 | if (!interface->ctlr.sel_fcf) { | 310 | if (!ctlr->sel_fcf) { |
272 | BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n"); | 311 | BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n"); |
273 | kfree_skb(skb); | 312 | kfree_skb(skb); |
274 | return -EINVAL; | 313 | return -EINVAL; |
275 | } | 314 | } |
276 | if (fcoe_ctlr_els_send(&interface->ctlr, lport, skb)) | 315 | if (fcoe_ctlr_els_send(ctlr, lport, skb)) |
277 | return 0; | 316 | return 0; |
278 | } | 317 | } |
279 | 318 | ||
@@ -346,14 +385,14 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
346 | /* fill up mac and fcoe headers */ | 385 | /* fill up mac and fcoe headers */ |
347 | eh = eth_hdr(skb); | 386 | eh = eth_hdr(skb); |
348 | eh->h_proto = htons(ETH_P_FCOE); | 387 | eh->h_proto = htons(ETH_P_FCOE); |
349 | if (interface->ctlr.map_dest) | 388 | if (ctlr->map_dest) |
350 | fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); | 389 | fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); |
351 | else | 390 | else |
352 | /* insert GW address */ | 391 | /* insert GW address */ |
353 | memcpy(eh->h_dest, interface->ctlr.dest_addr, ETH_ALEN); | 392 | memcpy(eh->h_dest, ctlr->dest_addr, ETH_ALEN); |
354 | 393 | ||
355 | if (unlikely(interface->ctlr.flogi_oxid != FC_XID_UNKNOWN)) | 394 | if (unlikely(ctlr->flogi_oxid != FC_XID_UNKNOWN)) |
356 | memcpy(eh->h_source, interface->ctlr.ctl_src_addr, ETH_ALEN); | 395 | memcpy(eh->h_source, ctlr->ctl_src_addr, ETH_ALEN); |
357 | else | 396 | else |
358 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); | 397 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); |
359 | 398 | ||
@@ -403,6 +442,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
403 | { | 442 | { |
404 | struct fc_lport *lport; | 443 | struct fc_lport *lport; |
405 | struct bnx2fc_interface *interface; | 444 | struct bnx2fc_interface *interface; |
445 | struct fcoe_ctlr *ctlr; | ||
406 | struct fc_frame_header *fh; | 446 | struct fc_frame_header *fh; |
407 | struct fcoe_rcv_info *fr; | 447 | struct fcoe_rcv_info *fr; |
408 | struct fcoe_percpu_s *bg; | 448 | struct fcoe_percpu_s *bg; |
@@ -410,7 +450,8 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
410 | 450 | ||
411 | interface = container_of(ptype, struct bnx2fc_interface, | 451 | interface = container_of(ptype, struct bnx2fc_interface, |
412 | fcoe_packet_type); | 452 | fcoe_packet_type); |
413 | lport = interface->ctlr.lp; | 453 | ctlr = bnx2fc_to_ctlr(interface); |
454 | lport = ctlr->lp; | ||
414 | 455 | ||
415 | if (unlikely(lport == NULL)) { | 456 | if (unlikely(lport == NULL)) { |
416 | printk(KERN_ERR PFX "bnx2fc_rcv: lport is NULL\n"); | 457 | printk(KERN_ERR PFX "bnx2fc_rcv: lport is NULL\n"); |
@@ -758,11 +799,13 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) | |||
758 | { | 799 | { |
759 | struct bnx2fc_hba *hba; | 800 | struct bnx2fc_hba *hba; |
760 | struct bnx2fc_interface *interface; | 801 | struct bnx2fc_interface *interface; |
802 | struct fcoe_ctlr *ctlr; | ||
761 | struct fcoe_port *port; | 803 | struct fcoe_port *port; |
762 | u64 wwnn, wwpn; | 804 | u64 wwnn, wwpn; |
763 | 805 | ||
764 | port = lport_priv(lport); | 806 | port = lport_priv(lport); |
765 | interface = port->priv; | 807 | interface = port->priv; |
808 | ctlr = bnx2fc_to_ctlr(interface); | ||
766 | hba = interface->hba; | 809 | hba = interface->hba; |
767 | 810 | ||
768 | /* require support for get_pauseparam ethtool op. */ | 811 | /* require support for get_pauseparam ethtool op. */ |
@@ -781,13 +824,13 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) | |||
781 | 824 | ||
782 | if (!lport->vport) { | 825 | if (!lport->vport) { |
783 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) | 826 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) |
784 | wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, | 827 | wwnn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, |
785 | 1, 0); | 828 | 1, 0); |
786 | BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn); | 829 | BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn); |
787 | fc_set_wwnn(lport, wwnn); | 830 | fc_set_wwnn(lport, wwnn); |
788 | 831 | ||
789 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) | 832 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) |
790 | wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, | 833 | wwpn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, |
791 | 2, 0); | 834 | 2, 0); |
792 | 835 | ||
793 | BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn); | 836 | BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn); |
@@ -824,6 +867,7 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, | |||
824 | struct fc_lport *lport; | 867 | struct fc_lport *lport; |
825 | struct fc_lport *vport; | 868 | struct fc_lport *vport; |
826 | struct bnx2fc_interface *interface, *tmp; | 869 | struct bnx2fc_interface *interface, *tmp; |
870 | struct fcoe_ctlr *ctlr; | ||
827 | int wait_for_upload = 0; | 871 | int wait_for_upload = 0; |
828 | u32 link_possible = 1; | 872 | u32 link_possible = 1; |
829 | 873 | ||
@@ -874,7 +918,8 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, | |||
874 | if (interface->hba != hba) | 918 | if (interface->hba != hba) |
875 | continue; | 919 | continue; |
876 | 920 | ||
877 | lport = interface->ctlr.lp; | 921 | ctlr = bnx2fc_to_ctlr(interface); |
922 | lport = ctlr->lp; | ||
878 | BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n", | 923 | BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n", |
879 | interface->netdev->name, event); | 924 | interface->netdev->name, event); |
880 | 925 | ||
@@ -889,8 +934,8 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, | |||
889 | * on a stale vlan | 934 | * on a stale vlan |
890 | */ | 935 | */ |
891 | if (interface->enabled) | 936 | if (interface->enabled) |
892 | fcoe_ctlr_link_up(&interface->ctlr); | 937 | fcoe_ctlr_link_up(ctlr); |
893 | } else if (fcoe_ctlr_link_down(&interface->ctlr)) { | 938 | } else if (fcoe_ctlr_link_down(ctlr)) { |
894 | mutex_lock(&lport->lp_mutex); | 939 | mutex_lock(&lport->lp_mutex); |
895 | list_for_each_entry(vport, &lport->vports, list) | 940 | list_for_each_entry(vport, &lport->vports, list) |
896 | fc_host_port_type(vport->host) = | 941 | fc_host_port_type(vport->host) = |
@@ -995,9 +1040,11 @@ static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev, | |||
995 | struct net_device *orig_dev) | 1040 | struct net_device *orig_dev) |
996 | { | 1041 | { |
997 | struct bnx2fc_interface *interface; | 1042 | struct bnx2fc_interface *interface; |
1043 | struct fcoe_ctlr *ctlr; | ||
998 | interface = container_of(ptype, struct bnx2fc_interface, | 1044 | interface = container_of(ptype, struct bnx2fc_interface, |
999 | fip_packet_type); | 1045 | fip_packet_type); |
1000 | fcoe_ctlr_recv(&interface->ctlr, skb); | 1046 | ctlr = bnx2fc_to_ctlr(interface); |
1047 | fcoe_ctlr_recv(ctlr, skb); | ||
1001 | return 0; | 1048 | return 0; |
1002 | } | 1049 | } |
1003 | 1050 | ||
@@ -1155,6 +1202,7 @@ static int bnx2fc_interface_setup(struct bnx2fc_interface *interface) | |||
1155 | { | 1202 | { |
1156 | struct net_device *netdev = interface->netdev; | 1203 | struct net_device *netdev = interface->netdev; |
1157 | struct net_device *physdev = interface->hba->phys_dev; | 1204 | struct net_device *physdev = interface->hba->phys_dev; |
1205 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
1158 | struct netdev_hw_addr *ha; | 1206 | struct netdev_hw_addr *ha; |
1159 | int sel_san_mac = 0; | 1207 | int sel_san_mac = 0; |
1160 | 1208 | ||
@@ -1169,7 +1217,7 @@ static int bnx2fc_interface_setup(struct bnx2fc_interface *interface) | |||
1169 | 1217 | ||
1170 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && | 1218 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && |
1171 | (is_valid_ether_addr(ha->addr))) { | 1219 | (is_valid_ether_addr(ha->addr))) { |
1172 | memcpy(interface->ctlr.ctl_src_addr, ha->addr, | 1220 | memcpy(ctlr->ctl_src_addr, ha->addr, |
1173 | ETH_ALEN); | 1221 | ETH_ALEN); |
1174 | sel_san_mac = 1; | 1222 | sel_san_mac = 1; |
1175 | BNX2FC_MISC_DBG("Found SAN MAC\n"); | 1223 | BNX2FC_MISC_DBG("Found SAN MAC\n"); |
@@ -1224,19 +1272,23 @@ static void bnx2fc_release_transport(void) | |||
1224 | 1272 | ||
1225 | static void bnx2fc_interface_release(struct kref *kref) | 1273 | static void bnx2fc_interface_release(struct kref *kref) |
1226 | { | 1274 | { |
1275 | struct fcoe_ctlr_device *ctlr_dev; | ||
1227 | struct bnx2fc_interface *interface; | 1276 | struct bnx2fc_interface *interface; |
1277 | struct fcoe_ctlr *ctlr; | ||
1228 | struct net_device *netdev; | 1278 | struct net_device *netdev; |
1229 | 1279 | ||
1230 | interface = container_of(kref, struct bnx2fc_interface, kref); | 1280 | interface = container_of(kref, struct bnx2fc_interface, kref); |
1231 | BNX2FC_MISC_DBG("Interface is being released\n"); | 1281 | BNX2FC_MISC_DBG("Interface is being released\n"); |
1232 | 1282 | ||
1283 | ctlr = bnx2fc_to_ctlr(interface); | ||
1284 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); | ||
1233 | netdev = interface->netdev; | 1285 | netdev = interface->netdev; |
1234 | 1286 | ||
1235 | /* tear-down FIP controller */ | 1287 | /* tear-down FIP controller */ |
1236 | if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags)) | 1288 | if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags)) |
1237 | fcoe_ctlr_destroy(&interface->ctlr); | 1289 | fcoe_ctlr_destroy(ctlr); |
1238 | 1290 | ||
1239 | kfree(interface); | 1291 | fcoe_ctlr_device_delete(ctlr_dev); |
1240 | 1292 | ||
1241 | dev_put(netdev); | 1293 | dev_put(netdev); |
1242 | module_put(THIS_MODULE); | 1294 | module_put(THIS_MODULE); |
@@ -1329,33 +1381,40 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, | |||
1329 | struct net_device *netdev, | 1381 | struct net_device *netdev, |
1330 | enum fip_state fip_mode) | 1382 | enum fip_state fip_mode) |
1331 | { | 1383 | { |
1384 | struct fcoe_ctlr_device *ctlr_dev; | ||
1332 | struct bnx2fc_interface *interface; | 1385 | struct bnx2fc_interface *interface; |
1386 | struct fcoe_ctlr *ctlr; | ||
1387 | int size; | ||
1333 | int rc = 0; | 1388 | int rc = 0; |
1334 | 1389 | ||
1335 | interface = kzalloc(sizeof(*interface), GFP_KERNEL); | 1390 | size = (sizeof(*interface) + sizeof(struct fcoe_ctlr)); |
1336 | if (!interface) { | 1391 | ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &bnx2fc_fcoe_sysfs_templ, |
1392 | size); | ||
1393 | if (!ctlr_dev) { | ||
1337 | printk(KERN_ERR PFX "Unable to allocate interface structure\n"); | 1394 | printk(KERN_ERR PFX "Unable to allocate interface structure\n"); |
1338 | return NULL; | 1395 | return NULL; |
1339 | } | 1396 | } |
1397 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
1398 | interface = fcoe_ctlr_priv(ctlr); | ||
1340 | dev_hold(netdev); | 1399 | dev_hold(netdev); |
1341 | kref_init(&interface->kref); | 1400 | kref_init(&interface->kref); |
1342 | interface->hba = hba; | 1401 | interface->hba = hba; |
1343 | interface->netdev = netdev; | 1402 | interface->netdev = netdev; |
1344 | 1403 | ||
1345 | /* Initialize FIP */ | 1404 | /* Initialize FIP */ |
1346 | fcoe_ctlr_init(&interface->ctlr, fip_mode); | 1405 | fcoe_ctlr_init(ctlr, fip_mode); |
1347 | interface->ctlr.send = bnx2fc_fip_send; | 1406 | ctlr->send = bnx2fc_fip_send; |
1348 | interface->ctlr.update_mac = bnx2fc_update_src_mac; | 1407 | ctlr->update_mac = bnx2fc_update_src_mac; |
1349 | interface->ctlr.get_src_addr = bnx2fc_get_src_mac; | 1408 | ctlr->get_src_addr = bnx2fc_get_src_mac; |
1350 | set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags); | 1409 | set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags); |
1351 | 1410 | ||
1352 | rc = bnx2fc_interface_setup(interface); | 1411 | rc = bnx2fc_interface_setup(interface); |
1353 | if (!rc) | 1412 | if (!rc) |
1354 | return interface; | 1413 | return interface; |
1355 | 1414 | ||
1356 | fcoe_ctlr_destroy(&interface->ctlr); | 1415 | fcoe_ctlr_destroy(ctlr); |
1357 | dev_put(netdev); | 1416 | dev_put(netdev); |
1358 | kfree(interface); | 1417 | fcoe_ctlr_device_delete(ctlr_dev); |
1359 | return NULL; | 1418 | return NULL; |
1360 | } | 1419 | } |
1361 | 1420 | ||
@@ -1373,6 +1432,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, | |||
1373 | static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, | 1432 | static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, |
1374 | struct device *parent, int npiv) | 1433 | struct device *parent, int npiv) |
1375 | { | 1434 | { |
1435 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
1376 | struct fc_lport *lport, *n_port; | 1436 | struct fc_lport *lport, *n_port; |
1377 | struct fcoe_port *port; | 1437 | struct fcoe_port *port; |
1378 | struct Scsi_Host *shost; | 1438 | struct Scsi_Host *shost; |
@@ -1383,7 +1443,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, | |||
1383 | 1443 | ||
1384 | blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL); | 1444 | blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL); |
1385 | if (!blport) { | 1445 | if (!blport) { |
1386 | BNX2FC_HBA_DBG(interface->ctlr.lp, "Unable to alloc blport\n"); | 1446 | BNX2FC_HBA_DBG(ctlr->lp, "Unable to alloc blport\n"); |
1387 | return NULL; | 1447 | return NULL; |
1388 | } | 1448 | } |
1389 | 1449 | ||
@@ -1479,7 +1539,8 @@ static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface) | |||
1479 | 1539 | ||
1480 | static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) | 1540 | static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) |
1481 | { | 1541 | { |
1482 | struct fc_lport *lport = interface->ctlr.lp; | 1542 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1543 | struct fc_lport *lport = ctlr->lp; | ||
1483 | struct fcoe_port *port = lport_priv(lport); | 1544 | struct fcoe_port *port = lport_priv(lport); |
1484 | struct bnx2fc_hba *hba = interface->hba; | 1545 | struct bnx2fc_hba *hba = interface->hba; |
1485 | 1546 | ||
@@ -1519,7 +1580,8 @@ static void bnx2fc_if_destroy(struct fc_lport *lport) | |||
1519 | 1580 | ||
1520 | static void __bnx2fc_destroy(struct bnx2fc_interface *interface) | 1581 | static void __bnx2fc_destroy(struct bnx2fc_interface *interface) |
1521 | { | 1582 | { |
1522 | struct fc_lport *lport = interface->ctlr.lp; | 1583 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); |
1584 | struct fc_lport *lport = ctlr->lp; | ||
1523 | struct fcoe_port *port = lport_priv(lport); | 1585 | struct fcoe_port *port = lport_priv(lport); |
1524 | 1586 | ||
1525 | bnx2fc_interface_cleanup(interface); | 1587 | bnx2fc_interface_cleanup(interface); |
@@ -1543,13 +1605,15 @@ static int bnx2fc_destroy(struct net_device *netdev) | |||
1543 | { | 1605 | { |
1544 | struct bnx2fc_interface *interface = NULL; | 1606 | struct bnx2fc_interface *interface = NULL; |
1545 | struct workqueue_struct *timer_work_queue; | 1607 | struct workqueue_struct *timer_work_queue; |
1608 | struct fcoe_ctlr *ctlr; | ||
1546 | int rc = 0; | 1609 | int rc = 0; |
1547 | 1610 | ||
1548 | rtnl_lock(); | 1611 | rtnl_lock(); |
1549 | mutex_lock(&bnx2fc_dev_lock); | 1612 | mutex_lock(&bnx2fc_dev_lock); |
1550 | 1613 | ||
1551 | interface = bnx2fc_interface_lookup(netdev); | 1614 | interface = bnx2fc_interface_lookup(netdev); |
1552 | if (!interface || !interface->ctlr.lp) { | 1615 | ctlr = bnx2fc_to_ctlr(interface); |
1616 | if (!interface || !ctlr->lp) { | ||
1553 | rc = -ENODEV; | 1617 | rc = -ENODEV; |
1554 | printk(KERN_ERR PFX "bnx2fc_destroy: interface or lport not found\n"); | 1618 | printk(KERN_ERR PFX "bnx2fc_destroy: interface or lport not found\n"); |
1555 | goto netdev_err; | 1619 | goto netdev_err; |
@@ -1646,6 +1710,7 @@ static void bnx2fc_ulp_start(void *handle) | |||
1646 | { | 1710 | { |
1647 | struct bnx2fc_hba *hba = handle; | 1711 | struct bnx2fc_hba *hba = handle; |
1648 | struct bnx2fc_interface *interface; | 1712 | struct bnx2fc_interface *interface; |
1713 | struct fcoe_ctlr *ctlr; | ||
1649 | struct fc_lport *lport; | 1714 | struct fc_lport *lport; |
1650 | 1715 | ||
1651 | mutex_lock(&bnx2fc_dev_lock); | 1716 | mutex_lock(&bnx2fc_dev_lock); |
@@ -1657,7 +1722,8 @@ static void bnx2fc_ulp_start(void *handle) | |||
1657 | 1722 | ||
1658 | list_for_each_entry(interface, &if_list, list) { | 1723 | list_for_each_entry(interface, &if_list, list) { |
1659 | if (interface->hba == hba) { | 1724 | if (interface->hba == hba) { |
1660 | lport = interface->ctlr.lp; | 1725 | ctlr = bnx2fc_to_ctlr(interface); |
1726 | lport = ctlr->lp; | ||
1661 | /* Kick off Fabric discovery*/ | 1727 | /* Kick off Fabric discovery*/ |
1662 | printk(KERN_ERR PFX "ulp_init: start discovery\n"); | 1728 | printk(KERN_ERR PFX "ulp_init: start discovery\n"); |
1663 | lport->tt.frame_send = bnx2fc_xmit; | 1729 | lport->tt.frame_send = bnx2fc_xmit; |
@@ -1677,13 +1743,14 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport) | |||
1677 | 1743 | ||
1678 | static void bnx2fc_stop(struct bnx2fc_interface *interface) | 1744 | static void bnx2fc_stop(struct bnx2fc_interface *interface) |
1679 | { | 1745 | { |
1746 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
1680 | struct fc_lport *lport; | 1747 | struct fc_lport *lport; |
1681 | struct fc_lport *vport; | 1748 | struct fc_lport *vport; |
1682 | 1749 | ||
1683 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) | 1750 | if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) |
1684 | return; | 1751 | return; |
1685 | 1752 | ||
1686 | lport = interface->ctlr.lp; | 1753 | lport = ctlr->lp; |
1687 | bnx2fc_port_shutdown(lport); | 1754 | bnx2fc_port_shutdown(lport); |
1688 | 1755 | ||
1689 | mutex_lock(&lport->lp_mutex); | 1756 | mutex_lock(&lport->lp_mutex); |
@@ -1692,7 +1759,7 @@ static void bnx2fc_stop(struct bnx2fc_interface *interface) | |||
1692 | FC_PORTTYPE_UNKNOWN; | 1759 | FC_PORTTYPE_UNKNOWN; |
1693 | mutex_unlock(&lport->lp_mutex); | 1760 | mutex_unlock(&lport->lp_mutex); |
1694 | fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; | 1761 | fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; |
1695 | fcoe_ctlr_link_down(&interface->ctlr); | 1762 | fcoe_ctlr_link_down(ctlr); |
1696 | fcoe_clean_pending_queue(lport); | 1763 | fcoe_clean_pending_queue(lport); |
1697 | } | 1764 | } |
1698 | 1765 | ||
@@ -1804,6 +1871,7 @@ exit: | |||
1804 | 1871 | ||
1805 | static void bnx2fc_start_disc(struct bnx2fc_interface *interface) | 1872 | static void bnx2fc_start_disc(struct bnx2fc_interface *interface) |
1806 | { | 1873 | { |
1874 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
1807 | struct fc_lport *lport; | 1875 | struct fc_lport *lport; |
1808 | int wait_cnt = 0; | 1876 | int wait_cnt = 0; |
1809 | 1877 | ||
@@ -1814,18 +1882,18 @@ static void bnx2fc_start_disc(struct bnx2fc_interface *interface) | |||
1814 | return; | 1882 | return; |
1815 | } | 1883 | } |
1816 | 1884 | ||
1817 | lport = interface->ctlr.lp; | 1885 | lport = ctlr->lp; |
1818 | BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n"); | 1886 | BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n"); |
1819 | 1887 | ||
1820 | if (!bnx2fc_link_ok(lport) && interface->enabled) { | 1888 | if (!bnx2fc_link_ok(lport) && interface->enabled) { |
1821 | BNX2FC_HBA_DBG(lport, "ctlr_link_up\n"); | 1889 | BNX2FC_HBA_DBG(lport, "ctlr_link_up\n"); |
1822 | fcoe_ctlr_link_up(&interface->ctlr); | 1890 | fcoe_ctlr_link_up(ctlr); |
1823 | fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; | 1891 | fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; |
1824 | set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); | 1892 | set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); |
1825 | } | 1893 | } |
1826 | 1894 | ||
1827 | /* wait for the FCF to be selected before issuing FLOGI */ | 1895 | /* wait for the FCF to be selected before issuing FLOGI */ |
1828 | while (!interface->ctlr.sel_fcf) { | 1896 | while (!ctlr->sel_fcf) { |
1829 | msleep(250); | 1897 | msleep(250); |
1830 | /* give up after 3 secs */ | 1898 | /* give up after 3 secs */ |
1831 | if (++wait_cnt > 12) | 1899 | if (++wait_cnt > 12) |
@@ -1889,19 +1957,21 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev) | |||
1889 | static int bnx2fc_disable(struct net_device *netdev) | 1957 | static int bnx2fc_disable(struct net_device *netdev) |
1890 | { | 1958 | { |
1891 | struct bnx2fc_interface *interface; | 1959 | struct bnx2fc_interface *interface; |
1960 | struct fcoe_ctlr *ctlr; | ||
1892 | int rc = 0; | 1961 | int rc = 0; |
1893 | 1962 | ||
1894 | rtnl_lock(); | 1963 | rtnl_lock(); |
1895 | mutex_lock(&bnx2fc_dev_lock); | 1964 | mutex_lock(&bnx2fc_dev_lock); |
1896 | 1965 | ||
1897 | interface = bnx2fc_interface_lookup(netdev); | 1966 | interface = bnx2fc_interface_lookup(netdev); |
1898 | if (!interface || !interface->ctlr.lp) { | 1967 | ctlr = bnx2fc_to_ctlr(interface); |
1968 | if (!interface || !ctlr->lp) { | ||
1899 | rc = -ENODEV; | 1969 | rc = -ENODEV; |
1900 | printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); | 1970 | printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); |
1901 | } else { | 1971 | } else { |
1902 | interface->enabled = false; | 1972 | interface->enabled = false; |
1903 | fcoe_ctlr_link_down(&interface->ctlr); | 1973 | fcoe_ctlr_link_down(ctlr); |
1904 | fcoe_clean_pending_queue(interface->ctlr.lp); | 1974 | fcoe_clean_pending_queue(ctlr->lp); |
1905 | } | 1975 | } |
1906 | 1976 | ||
1907 | mutex_unlock(&bnx2fc_dev_lock); | 1977 | mutex_unlock(&bnx2fc_dev_lock); |
@@ -1913,17 +1983,19 @@ static int bnx2fc_disable(struct net_device *netdev) | |||
1913 | static int bnx2fc_enable(struct net_device *netdev) | 1983 | static int bnx2fc_enable(struct net_device *netdev) |
1914 | { | 1984 | { |
1915 | struct bnx2fc_interface *interface; | 1985 | struct bnx2fc_interface *interface; |
1986 | struct fcoe_ctlr *ctlr; | ||
1916 | int rc = 0; | 1987 | int rc = 0; |
1917 | 1988 | ||
1918 | rtnl_lock(); | 1989 | rtnl_lock(); |
1919 | mutex_lock(&bnx2fc_dev_lock); | 1990 | mutex_lock(&bnx2fc_dev_lock); |
1920 | 1991 | ||
1921 | interface = bnx2fc_interface_lookup(netdev); | 1992 | interface = bnx2fc_interface_lookup(netdev); |
1922 | if (!interface || !interface->ctlr.lp) { | 1993 | ctlr = bnx2fc_to_ctlr(interface); |
1994 | if (!interface || !ctlr->lp) { | ||
1923 | rc = -ENODEV; | 1995 | rc = -ENODEV; |
1924 | printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); | 1996 | printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); |
1925 | } else if (!bnx2fc_link_ok(interface->ctlr.lp)) { | 1997 | } else if (!bnx2fc_link_ok(ctlr->lp)) { |
1926 | fcoe_ctlr_link_up(&interface->ctlr); | 1998 | fcoe_ctlr_link_up(ctlr); |
1927 | interface->enabled = true; | 1999 | interface->enabled = true; |
1928 | } | 2000 | } |
1929 | 2001 | ||
@@ -1944,6 +2016,7 @@ static int bnx2fc_enable(struct net_device *netdev) | |||
1944 | */ | 2016 | */ |
1945 | static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) | 2017 | static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) |
1946 | { | 2018 | { |
2019 | struct fcoe_ctlr *ctlr; | ||
1947 | struct bnx2fc_interface *interface; | 2020 | struct bnx2fc_interface *interface; |
1948 | struct bnx2fc_hba *hba; | 2021 | struct bnx2fc_hba *hba; |
1949 | struct net_device *phys_dev; | 2022 | struct net_device *phys_dev; |
@@ -2010,6 +2083,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2010 | goto ifput_err; | 2083 | goto ifput_err; |
2011 | } | 2084 | } |
2012 | 2085 | ||
2086 | ctlr = bnx2fc_to_ctlr(interface); | ||
2013 | interface->vlan_id = vlan_id; | 2087 | interface->vlan_id = vlan_id; |
2014 | interface->vlan_enabled = 1; | 2088 | interface->vlan_enabled = 1; |
2015 | 2089 | ||
@@ -2035,10 +2109,10 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2035 | lport->boot_time = jiffies; | 2109 | lport->boot_time = jiffies; |
2036 | 2110 | ||
2037 | /* Make this master N_port */ | 2111 | /* Make this master N_port */ |
2038 | interface->ctlr.lp = lport; | 2112 | ctlr->lp = lport; |
2039 | 2113 | ||
2040 | if (!bnx2fc_link_ok(lport)) { | 2114 | if (!bnx2fc_link_ok(lport)) { |
2041 | fcoe_ctlr_link_up(&interface->ctlr); | 2115 | fcoe_ctlr_link_up(ctlr); |
2042 | fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; | 2116 | fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; |
2043 | set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); | 2117 | set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); |
2044 | } | 2118 | } |
@@ -2439,6 +2513,19 @@ static void __exit bnx2fc_mod_exit(void) | |||
2439 | module_init(bnx2fc_mod_init); | 2513 | module_init(bnx2fc_mod_init); |
2440 | module_exit(bnx2fc_mod_exit); | 2514 | module_exit(bnx2fc_mod_exit); |
2441 | 2515 | ||
2516 | static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = { | ||
2517 | .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode, | ||
2518 | .get_fcoe_ctlr_link_fail = bnx2fc_ctlr_get_lesb, | ||
2519 | .get_fcoe_ctlr_vlink_fail = bnx2fc_ctlr_get_lesb, | ||
2520 | .get_fcoe_ctlr_miss_fka = bnx2fc_ctlr_get_lesb, | ||
2521 | .get_fcoe_ctlr_symb_err = bnx2fc_ctlr_get_lesb, | ||
2522 | .get_fcoe_ctlr_err_block = bnx2fc_ctlr_get_lesb, | ||
2523 | .get_fcoe_ctlr_fcs_error = bnx2fc_ctlr_get_lesb, | ||
2524 | |||
2525 | .get_fcoe_fcf_selected = fcoe_fcf_get_selected, | ||
2526 | .get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id, | ||
2527 | }; | ||
2528 | |||
2442 | static struct fc_function_template bnx2fc_transport_function = { | 2529 | static struct fc_function_template bnx2fc_transport_function = { |
2443 | .show_host_node_name = 1, | 2530 | .show_host_node_name = 1, |
2444 | .show_host_port_name = 1, | 2531 | .show_host_port_name = 1, |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index afd570962b8c..2ca6bfe4ce5e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c | |||
@@ -167,6 +167,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port, | |||
167 | { | 167 | { |
168 | struct fc_lport *lport = port->lport; | 168 | struct fc_lport *lport = port->lport; |
169 | struct bnx2fc_interface *interface = port->priv; | 169 | struct bnx2fc_interface *interface = port->priv; |
170 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
170 | struct bnx2fc_hba *hba = interface->hba; | 171 | struct bnx2fc_hba *hba = interface->hba; |
171 | struct kwqe *kwqe_arr[4]; | 172 | struct kwqe *kwqe_arr[4]; |
172 | struct fcoe_kwqe_conn_offload1 ofld_req1; | 173 | struct fcoe_kwqe_conn_offload1 ofld_req1; |
@@ -314,13 +315,13 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port, | |||
314 | ofld_req4.src_mac_addr_mid[1] = port->data_src_addr[2]; | 315 | ofld_req4.src_mac_addr_mid[1] = port->data_src_addr[2]; |
315 | ofld_req4.src_mac_addr_hi[0] = port->data_src_addr[1]; | 316 | ofld_req4.src_mac_addr_hi[0] = port->data_src_addr[1]; |
316 | ofld_req4.src_mac_addr_hi[1] = port->data_src_addr[0]; | 317 | ofld_req4.src_mac_addr_hi[1] = port->data_src_addr[0]; |
317 | ofld_req4.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5]; | 318 | ofld_req4.dst_mac_addr_lo[0] = ctlr->dest_addr[5]; |
318 | /* fcf mac */ | 319 | /* fcf mac */ |
319 | ofld_req4.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4]; | 320 | ofld_req4.dst_mac_addr_lo[1] = ctlr->dest_addr[4]; |
320 | ofld_req4.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3]; | 321 | ofld_req4.dst_mac_addr_mid[0] = ctlr->dest_addr[3]; |
321 | ofld_req4.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2]; | 322 | ofld_req4.dst_mac_addr_mid[1] = ctlr->dest_addr[2]; |
322 | ofld_req4.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1]; | 323 | ofld_req4.dst_mac_addr_hi[0] = ctlr->dest_addr[1]; |
323 | ofld_req4.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0]; | 324 | ofld_req4.dst_mac_addr_hi[1] = ctlr->dest_addr[0]; |
324 | 325 | ||
325 | ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma; | 326 | ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma; |
326 | ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32); | 327 | ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32); |
@@ -351,6 +352,7 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port, | |||
351 | { | 352 | { |
352 | struct kwqe *kwqe_arr[2]; | 353 | struct kwqe *kwqe_arr[2]; |
353 | struct bnx2fc_interface *interface = port->priv; | 354 | struct bnx2fc_interface *interface = port->priv; |
355 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
354 | struct bnx2fc_hba *hba = interface->hba; | 356 | struct bnx2fc_hba *hba = interface->hba; |
355 | struct fcoe_kwqe_conn_enable_disable enbl_req; | 357 | struct fcoe_kwqe_conn_enable_disable enbl_req; |
356 | struct fc_lport *lport = port->lport; | 358 | struct fc_lport *lport = port->lport; |
@@ -374,12 +376,12 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port, | |||
374 | enbl_req.src_mac_addr_hi[1] = port->data_src_addr[0]; | 376 | enbl_req.src_mac_addr_hi[1] = port->data_src_addr[0]; |
375 | memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN); | 377 | memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN); |
376 | 378 | ||
377 | enbl_req.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5]; | 379 | enbl_req.dst_mac_addr_lo[0] = ctlr->dest_addr[5]; |
378 | enbl_req.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4]; | 380 | enbl_req.dst_mac_addr_lo[1] = ctlr->dest_addr[4]; |
379 | enbl_req.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3]; | 381 | enbl_req.dst_mac_addr_mid[0] = ctlr->dest_addr[3]; |
380 | enbl_req.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2]; | 382 | enbl_req.dst_mac_addr_mid[1] = ctlr->dest_addr[2]; |
381 | enbl_req.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1]; | 383 | enbl_req.dst_mac_addr_hi[0] = ctlr->dest_addr[1]; |
382 | enbl_req.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0]; | 384 | enbl_req.dst_mac_addr_hi[1] = ctlr->dest_addr[0]; |
383 | 385 | ||
384 | port_id = fc_host_port_id(lport->host); | 386 | port_id = fc_host_port_id(lport->host); |
385 | if (port_id != tgt->sid) { | 387 | if (port_id != tgt->sid) { |
@@ -419,6 +421,7 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port, | |||
419 | struct bnx2fc_rport *tgt) | 421 | struct bnx2fc_rport *tgt) |
420 | { | 422 | { |
421 | struct bnx2fc_interface *interface = port->priv; | 423 | struct bnx2fc_interface *interface = port->priv; |
424 | struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); | ||
422 | struct bnx2fc_hba *hba = interface->hba; | 425 | struct bnx2fc_hba *hba = interface->hba; |
423 | struct fcoe_kwqe_conn_enable_disable disable_req; | 426 | struct fcoe_kwqe_conn_enable_disable disable_req; |
424 | struct kwqe *kwqe_arr[2]; | 427 | struct kwqe *kwqe_arr[2]; |
@@ -440,12 +443,12 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port, | |||
440 | disable_req.src_mac_addr_hi[0] = tgt->src_addr[1]; | 443 | disable_req.src_mac_addr_hi[0] = tgt->src_addr[1]; |
441 | disable_req.src_mac_addr_hi[1] = tgt->src_addr[0]; | 444 | disable_req.src_mac_addr_hi[1] = tgt->src_addr[0]; |
442 | 445 | ||
443 | disable_req.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5]; | 446 | disable_req.dst_mac_addr_lo[0] = ctlr->dest_addr[5]; |
444 | disable_req.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4]; | 447 | disable_req.dst_mac_addr_lo[1] = ctlr->dest_addr[4]; |
445 | disable_req.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3]; | 448 | disable_req.dst_mac_addr_mid[0] = ctlr->dest_addr[3]; |
446 | disable_req.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2]; | 449 | disable_req.dst_mac_addr_mid[1] = ctlr->dest_addr[2]; |
447 | disable_req.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1]; | 450 | disable_req.dst_mac_addr_hi[0] = ctlr->dest_addr[1]; |
448 | disable_req.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0]; | 451 | disable_req.dst_mac_addr_hi[1] = ctlr->dest_addr[0]; |
449 | 452 | ||
450 | port_id = tgt->sid; | 453 | port_id = tgt->sid; |
451 | disable_req.s_id[0] = (port_id & 0x000000FF); | 454 | disable_req.s_id[0] = (port_id & 0x000000FF); |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index e897ce975bb8..4f7453b9e41e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c | |||
@@ -810,8 +810,22 @@ retry_tmf: | |||
810 | spin_lock_bh(&tgt->tgt_lock); | 810 | spin_lock_bh(&tgt->tgt_lock); |
811 | 811 | ||
812 | io_req->wait_for_comp = 0; | 812 | io_req->wait_for_comp = 0; |
813 | if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) | 813 | if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) { |
814 | set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags); | 814 | set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags); |
815 | if (io_req->on_tmf_queue) { | ||
816 | list_del_init(&io_req->link); | ||
817 | io_req->on_tmf_queue = 0; | ||
818 | } | ||
819 | io_req->wait_for_comp = 1; | ||
820 | bnx2fc_initiate_cleanup(io_req); | ||
821 | spin_unlock_bh(&tgt->tgt_lock); | ||
822 | rc = wait_for_completion_timeout(&io_req->tm_done, | ||
823 | BNX2FC_FW_TIMEOUT); | ||
824 | spin_lock_bh(&tgt->tgt_lock); | ||
825 | io_req->wait_for_comp = 0; | ||
826 | if (!rc) | ||
827 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | ||
828 | } | ||
815 | 829 | ||
816 | spin_unlock_bh(&tgt->tgt_lock); | 830 | spin_unlock_bh(&tgt->tgt_lock); |
817 | 831 | ||
@@ -1089,6 +1103,48 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd) | |||
1089 | return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); | 1103 | return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); |
1090 | } | 1104 | } |
1091 | 1105 | ||
1106 | int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req) | ||
1107 | { | ||
1108 | struct bnx2fc_rport *tgt = io_req->tgt; | ||
1109 | struct fc_rport_priv *rdata = tgt->rdata; | ||
1110 | int logo_issued; | ||
1111 | int rc = SUCCESS; | ||
1112 | int wait_cnt = 0; | ||
1113 | |||
1114 | BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n", | ||
1115 | tgt->flags); | ||
1116 | logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO, | ||
1117 | &tgt->flags); | ||
1118 | io_req->wait_for_comp = 1; | ||
1119 | bnx2fc_initiate_cleanup(io_req); | ||
1120 | |||
1121 | spin_unlock_bh(&tgt->tgt_lock); | ||
1122 | |||
1123 | wait_for_completion(&io_req->tm_done); | ||
1124 | |||
1125 | io_req->wait_for_comp = 0; | ||
1126 | /* | ||
1127 | * release the reference taken in eh_abort to allow the | ||
1128 | * target to re-login after flushing IOs | ||
1129 | */ | ||
1130 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | ||
1131 | |||
1132 | if (!logo_issued) { | ||
1133 | clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags); | ||
1134 | mutex_lock(&lport->disc.disc_mutex); | ||
1135 | lport->tt.rport_logoff(rdata); | ||
1136 | mutex_unlock(&lport->disc.disc_mutex); | ||
1137 | do { | ||
1138 | msleep(BNX2FC_RELOGIN_WAIT_TIME); | ||
1139 | if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) { | ||
1140 | rc = FAILED; | ||
1141 | break; | ||
1142 | } | ||
1143 | } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)); | ||
1144 | } | ||
1145 | spin_lock_bh(&tgt->tgt_lock); | ||
1146 | return rc; | ||
1147 | } | ||
1092 | /** | 1148 | /** |
1093 | * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding | 1149 | * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding |
1094 | * SCSI command | 1150 | * SCSI command |
@@ -1103,10 +1159,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) | |||
1103 | struct fc_rport_libfc_priv *rp = rport->dd_data; | 1159 | struct fc_rport_libfc_priv *rp = rport->dd_data; |
1104 | struct bnx2fc_cmd *io_req; | 1160 | struct bnx2fc_cmd *io_req; |
1105 | struct fc_lport *lport; | 1161 | struct fc_lport *lport; |
1106 | struct fc_rport_priv *rdata; | ||
1107 | struct bnx2fc_rport *tgt; | 1162 | struct bnx2fc_rport *tgt; |
1108 | int logo_issued; | ||
1109 | int wait_cnt = 0; | ||
1110 | int rc = FAILED; | 1163 | int rc = FAILED; |
1111 | 1164 | ||
1112 | 1165 | ||
@@ -1183,58 +1236,31 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) | |||
1183 | list_add_tail(&io_req->link, &tgt->io_retire_queue); | 1236 | list_add_tail(&io_req->link, &tgt->io_retire_queue); |
1184 | 1237 | ||
1185 | init_completion(&io_req->tm_done); | 1238 | init_completion(&io_req->tm_done); |
1186 | io_req->wait_for_comp = 1; | ||
1187 | 1239 | ||
1188 | if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) { | 1240 | if (test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) { |
1189 | /* Cancel the current timer running on this io_req */ | ||
1190 | if (cancel_delayed_work(&io_req->timeout_work)) | ||
1191 | kref_put(&io_req->refcount, | ||
1192 | bnx2fc_cmd_release); /* drop timer hold */ | ||
1193 | set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags); | ||
1194 | rc = bnx2fc_initiate_abts(io_req); | ||
1195 | } else { | ||
1196 | printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) " | 1241 | printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) " |
1197 | "already in abts processing\n", io_req->xid); | 1242 | "already in abts processing\n", io_req->xid); |
1198 | if (cancel_delayed_work(&io_req->timeout_work)) | 1243 | if (cancel_delayed_work(&io_req->timeout_work)) |
1199 | kref_put(&io_req->refcount, | 1244 | kref_put(&io_req->refcount, |
1200 | bnx2fc_cmd_release); /* drop timer hold */ | 1245 | bnx2fc_cmd_release); /* drop timer hold */ |
1201 | bnx2fc_initiate_cleanup(io_req); | 1246 | rc = bnx2fc_expl_logo(lport, io_req); |
1247 | goto out; | ||
1248 | } | ||
1202 | 1249 | ||
1250 | /* Cancel the current timer running on this io_req */ | ||
1251 | if (cancel_delayed_work(&io_req->timeout_work)) | ||
1252 | kref_put(&io_req->refcount, | ||
1253 | bnx2fc_cmd_release); /* drop timer hold */ | ||
1254 | set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags); | ||
1255 | io_req->wait_for_comp = 1; | ||
1256 | rc = bnx2fc_initiate_abts(io_req); | ||
1257 | if (rc == FAILED) { | ||
1258 | bnx2fc_initiate_cleanup(io_req); | ||
1203 | spin_unlock_bh(&tgt->tgt_lock); | 1259 | spin_unlock_bh(&tgt->tgt_lock); |
1204 | |||
1205 | wait_for_completion(&io_req->tm_done); | 1260 | wait_for_completion(&io_req->tm_done); |
1206 | |||
1207 | spin_lock_bh(&tgt->tgt_lock); | 1261 | spin_lock_bh(&tgt->tgt_lock); |
1208 | io_req->wait_for_comp = 0; | 1262 | io_req->wait_for_comp = 0; |
1209 | rdata = io_req->tgt->rdata; | 1263 | goto done; |
1210 | logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO, | ||
1211 | &tgt->flags); | ||
1212 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | ||
1213 | spin_unlock_bh(&tgt->tgt_lock); | ||
1214 | |||
1215 | if (!logo_issued) { | ||
1216 | BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n", | ||
1217 | tgt->flags); | ||
1218 | mutex_lock(&lport->disc.disc_mutex); | ||
1219 | lport->tt.rport_logoff(rdata); | ||
1220 | mutex_unlock(&lport->disc.disc_mutex); | ||
1221 | do { | ||
1222 | msleep(BNX2FC_RELOGIN_WAIT_TIME); | ||
1223 | /* | ||
1224 | * If session not recovered, let SCSI-ml | ||
1225 | * escalate error recovery. | ||
1226 | */ | ||
1227 | if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) | ||
1228 | return FAILED; | ||
1229 | } while (!test_bit(BNX2FC_FLAG_SESSION_READY, | ||
1230 | &tgt->flags)); | ||
1231 | } | ||
1232 | return SUCCESS; | ||
1233 | } | ||
1234 | if (rc == FAILED) { | ||
1235 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | ||
1236 | spin_unlock_bh(&tgt->tgt_lock); | ||
1237 | return rc; | ||
1238 | } | 1264 | } |
1239 | spin_unlock_bh(&tgt->tgt_lock); | 1265 | spin_unlock_bh(&tgt->tgt_lock); |
1240 | 1266 | ||
@@ -1247,7 +1273,8 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) | |||
1247 | /* Let the scsi-ml try to recover this command */ | 1273 | /* Let the scsi-ml try to recover this command */ |
1248 | printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", | 1274 | printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", |
1249 | io_req->xid); | 1275 | io_req->xid); |
1250 | rc = FAILED; | 1276 | rc = bnx2fc_expl_logo(lport, io_req); |
1277 | goto out; | ||
1251 | } else { | 1278 | } else { |
1252 | /* | 1279 | /* |
1253 | * We come here even when there was a race condition | 1280 | * We come here even when there was a race condition |
@@ -1259,9 +1286,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) | |||
1259 | bnx2fc_scsi_done(io_req, DID_ABORT); | 1286 | bnx2fc_scsi_done(io_req, DID_ABORT); |
1260 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | 1287 | kref_put(&io_req->refcount, bnx2fc_cmd_release); |
1261 | } | 1288 | } |
1262 | 1289 | done: | |
1263 | /* release the reference taken in eh_abort */ | 1290 | /* release the reference taken in eh_abort */ |
1264 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | 1291 | kref_put(&io_req->refcount, bnx2fc_cmd_release); |
1292 | out: | ||
1265 | spin_unlock_bh(&tgt->tgt_lock); | 1293 | spin_unlock_bh(&tgt->tgt_lock); |
1266 | return rc; | 1294 | return rc; |
1267 | } | 1295 | } |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index c1800b531270..082a25c3117e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c | |||
@@ -185,6 +185,16 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt) | |||
185 | BUG_ON(rc); | 185 | BUG_ON(rc); |
186 | } | 186 | } |
187 | 187 | ||
188 | list_for_each_safe(list, tmp, &tgt->active_tm_queue) { | ||
189 | i++; | ||
190 | io_req = (struct bnx2fc_cmd *)list; | ||
191 | list_del_init(&io_req->link); | ||
192 | io_req->on_tmf_queue = 0; | ||
193 | BNX2FC_IO_DBG(io_req, "tm_queue cleanup\n"); | ||
194 | if (io_req->wait_for_comp) | ||
195 | complete(&io_req->tm_done); | ||
196 | } | ||
197 | |||
188 | list_for_each_safe(list, tmp, &tgt->els_queue) { | 198 | list_for_each_safe(list, tmp, &tgt->els_queue) { |
189 | i++; | 199 | i++; |
190 | io_req = (struct bnx2fc_cmd *)list; | 200 | io_req = (struct bnx2fc_cmd *)list; |
@@ -213,8 +223,17 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt) | |||
213 | 223 | ||
214 | BNX2FC_IO_DBG(io_req, "retire_queue flush\n"); | 224 | BNX2FC_IO_DBG(io_req, "retire_queue flush\n"); |
215 | 225 | ||
216 | if (cancel_delayed_work(&io_req->timeout_work)) | 226 | if (cancel_delayed_work(&io_req->timeout_work)) { |
227 | if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT, | ||
228 | &io_req->req_flags)) { | ||
229 | /* Handle eh_abort timeout */ | ||
230 | BNX2FC_IO_DBG(io_req, "eh_abort for IO " | ||
231 | "in retire_q\n"); | ||
232 | if (io_req->wait_for_comp) | ||
233 | complete(&io_req->tm_done); | ||
234 | } | ||
217 | kref_put(&io_req->refcount, bnx2fc_cmd_release); | 235 | kref_put(&io_req->refcount, bnx2fc_cmd_release); |
236 | } | ||
218 | 237 | ||
219 | clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags); | 238 | clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags); |
220 | } | 239 | } |
diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile index f6d37d0271f7..aed0f5db3668 100644 --- a/drivers/scsi/fcoe/Makefile +++ b/drivers/scsi/fcoe/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-$(CONFIG_FCOE) += fcoe.o | 1 | obj-$(CONFIG_FCOE) += fcoe.o |
2 | obj-$(CONFIG_LIBFCOE) += libfcoe.o | 2 | obj-$(CONFIG_LIBFCOE) += libfcoe.o |
3 | 3 | ||
4 | libfcoe-objs := fcoe_ctlr.o fcoe_transport.o | 4 | libfcoe-objs := fcoe_ctlr.o fcoe_transport.o fcoe_sysfs.o |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 76e3d0b5bfa6..fe30b1b65e1d 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <scsi/fc/fc_encaps.h> | 42 | #include <scsi/fc/fc_encaps.h> |
43 | #include <scsi/fc/fc_fip.h> | 43 | #include <scsi/fc/fc_fip.h> |
44 | #include <scsi/fc/fc_fcoe.h> | ||
44 | 45 | ||
45 | #include <scsi/libfc.h> | 46 | #include <scsi/libfc.h> |
46 | #include <scsi/fc_frame.h> | 47 | #include <scsi/fc_frame.h> |
@@ -150,6 +151,21 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled); | |||
150 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | 151 | static int fcoe_vport_disable(struct fc_vport *, bool disable); |
151 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 152 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); |
152 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); | 153 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); |
154 | static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *); | ||
155 | static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *); | ||
156 | |||
157 | static struct fcoe_sysfs_function_template fcoe_sysfs_templ = { | ||
158 | .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode, | ||
159 | .get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb, | ||
160 | .get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb, | ||
161 | .get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb, | ||
162 | .get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb, | ||
163 | .get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb, | ||
164 | .get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb, | ||
165 | |||
166 | .get_fcoe_fcf_selected = fcoe_fcf_get_selected, | ||
167 | .get_fcoe_fcf_vlan_id = fcoe_fcf_get_vlan_id, | ||
168 | }; | ||
153 | 169 | ||
154 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 170 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
155 | .frame_send = fcoe_xmit, | 171 | .frame_send = fcoe_xmit, |
@@ -282,7 +298,7 @@ static struct scsi_host_template fcoe_shost_template = { | |||
282 | static int fcoe_interface_setup(struct fcoe_interface *fcoe, | 298 | static int fcoe_interface_setup(struct fcoe_interface *fcoe, |
283 | struct net_device *netdev) | 299 | struct net_device *netdev) |
284 | { | 300 | { |
285 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 301 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
286 | struct netdev_hw_addr *ha; | 302 | struct netdev_hw_addr *ha; |
287 | struct net_device *real_dev; | 303 | struct net_device *real_dev; |
288 | u8 flogi_maddr[ETH_ALEN]; | 304 | u8 flogi_maddr[ETH_ALEN]; |
@@ -366,7 +382,10 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, | |||
366 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | 382 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, |
367 | enum fip_state fip_mode) | 383 | enum fip_state fip_mode) |
368 | { | 384 | { |
385 | struct fcoe_ctlr_device *ctlr_dev; | ||
386 | struct fcoe_ctlr *ctlr; | ||
369 | struct fcoe_interface *fcoe; | 387 | struct fcoe_interface *fcoe; |
388 | int size; | ||
370 | int err; | 389 | int err; |
371 | 390 | ||
372 | if (!try_module_get(THIS_MODULE)) { | 391 | if (!try_module_get(THIS_MODULE)) { |
@@ -376,27 +395,32 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
376 | goto out; | 395 | goto out; |
377 | } | 396 | } |
378 | 397 | ||
379 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | 398 | size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface); |
380 | if (!fcoe) { | 399 | ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &fcoe_sysfs_templ, |
381 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | 400 | size); |
401 | if (!ctlr_dev) { | ||
402 | FCOE_DBG("Failed to add fcoe_ctlr_device\n"); | ||
382 | fcoe = ERR_PTR(-ENOMEM); | 403 | fcoe = ERR_PTR(-ENOMEM); |
383 | goto out_putmod; | 404 | goto out_putmod; |
384 | } | 405 | } |
385 | 406 | ||
407 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
408 | fcoe = fcoe_ctlr_priv(ctlr); | ||
409 | |||
386 | dev_hold(netdev); | 410 | dev_hold(netdev); |
387 | 411 | ||
388 | /* | 412 | /* |
389 | * Initialize FIP. | 413 | * Initialize FIP. |
390 | */ | 414 | */ |
391 | fcoe_ctlr_init(&fcoe->ctlr, fip_mode); | 415 | fcoe_ctlr_init(ctlr, fip_mode); |
392 | fcoe->ctlr.send = fcoe_fip_send; | 416 | ctlr->send = fcoe_fip_send; |
393 | fcoe->ctlr.update_mac = fcoe_update_src_mac; | 417 | ctlr->update_mac = fcoe_update_src_mac; |
394 | fcoe->ctlr.get_src_addr = fcoe_get_src_mac; | 418 | ctlr->get_src_addr = fcoe_get_src_mac; |
395 | 419 | ||
396 | err = fcoe_interface_setup(fcoe, netdev); | 420 | err = fcoe_interface_setup(fcoe, netdev); |
397 | if (err) { | 421 | if (err) { |
398 | fcoe_ctlr_destroy(&fcoe->ctlr); | 422 | fcoe_ctlr_destroy(ctlr); |
399 | kfree(fcoe); | 423 | fcoe_ctlr_device_delete(ctlr_dev); |
400 | dev_put(netdev); | 424 | dev_put(netdev); |
401 | fcoe = ERR_PTR(err); | 425 | fcoe = ERR_PTR(err); |
402 | goto out_putmod; | 426 | goto out_putmod; |
@@ -419,7 +443,7 @@ out: | |||
419 | static void fcoe_interface_remove(struct fcoe_interface *fcoe) | 443 | static void fcoe_interface_remove(struct fcoe_interface *fcoe) |
420 | { | 444 | { |
421 | struct net_device *netdev = fcoe->netdev; | 445 | struct net_device *netdev = fcoe->netdev; |
422 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 446 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
423 | u8 flogi_maddr[ETH_ALEN]; | 447 | u8 flogi_maddr[ETH_ALEN]; |
424 | const struct net_device_ops *ops; | 448 | const struct net_device_ops *ops; |
425 | 449 | ||
@@ -462,7 +486,8 @@ static void fcoe_interface_remove(struct fcoe_interface *fcoe) | |||
462 | static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | 486 | static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) |
463 | { | 487 | { |
464 | struct net_device *netdev = fcoe->netdev; | 488 | struct net_device *netdev = fcoe->netdev; |
465 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 489 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
490 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | ||
466 | 491 | ||
467 | rtnl_lock(); | 492 | rtnl_lock(); |
468 | if (!fcoe->removed) | 493 | if (!fcoe->removed) |
@@ -472,8 +497,8 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
472 | /* Release the self-reference taken during fcoe_interface_create() */ | 497 | /* Release the self-reference taken during fcoe_interface_create() */ |
473 | /* tear-down the FCoE controller */ | 498 | /* tear-down the FCoE controller */ |
474 | fcoe_ctlr_destroy(fip); | 499 | fcoe_ctlr_destroy(fip); |
475 | scsi_host_put(fcoe->ctlr.lp->host); | 500 | scsi_host_put(fip->lp->host); |
476 | kfree(fcoe); | 501 | fcoe_ctlr_device_delete(ctlr_dev); |
477 | dev_put(netdev); | 502 | dev_put(netdev); |
478 | module_put(THIS_MODULE); | 503 | module_put(THIS_MODULE); |
479 | } | 504 | } |
@@ -493,9 +518,11 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev, | |||
493 | struct net_device *orig_dev) | 518 | struct net_device *orig_dev) |
494 | { | 519 | { |
495 | struct fcoe_interface *fcoe; | 520 | struct fcoe_interface *fcoe; |
521 | struct fcoe_ctlr *ctlr; | ||
496 | 522 | ||
497 | fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type); | 523 | fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type); |
498 | fcoe_ctlr_recv(&fcoe->ctlr, skb); | 524 | ctlr = fcoe_to_ctlr(fcoe); |
525 | fcoe_ctlr_recv(ctlr, skb); | ||
499 | return 0; | 526 | return 0; |
500 | } | 527 | } |
501 | 528 | ||
@@ -645,11 +672,13 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
645 | u32 mfs; | 672 | u32 mfs; |
646 | u64 wwnn, wwpn; | 673 | u64 wwnn, wwpn; |
647 | struct fcoe_interface *fcoe; | 674 | struct fcoe_interface *fcoe; |
675 | struct fcoe_ctlr *ctlr; | ||
648 | struct fcoe_port *port; | 676 | struct fcoe_port *port; |
649 | 677 | ||
650 | /* Setup lport private data to point to fcoe softc */ | 678 | /* Setup lport private data to point to fcoe softc */ |
651 | port = lport_priv(lport); | 679 | port = lport_priv(lport); |
652 | fcoe = port->priv; | 680 | fcoe = port->priv; |
681 | ctlr = fcoe_to_ctlr(fcoe); | ||
653 | 682 | ||
654 | /* | 683 | /* |
655 | * Determine max frame size based on underlying device and optional | 684 | * Determine max frame size based on underlying device and optional |
@@ -676,10 +705,10 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
676 | 705 | ||
677 | if (!lport->vport) { | 706 | if (!lport->vport) { |
678 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) | 707 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) |
679 | wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0); | 708 | wwnn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, 1, 0); |
680 | fc_set_wwnn(lport, wwnn); | 709 | fc_set_wwnn(lport, wwnn); |
681 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) | 710 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) |
682 | wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, | 711 | wwpn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, |
683 | 2, 0); | 712 | 2, 0); |
684 | fc_set_wwpn(lport, wwpn); | 713 | fc_set_wwpn(lport, wwpn); |
685 | } | 714 | } |
@@ -1056,6 +1085,7 @@ static int fcoe_ddp_done(struct fc_lport *lport, u16 xid) | |||
1056 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | 1085 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, |
1057 | struct device *parent, int npiv) | 1086 | struct device *parent, int npiv) |
1058 | { | 1087 | { |
1088 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
1059 | struct net_device *netdev = fcoe->netdev; | 1089 | struct net_device *netdev = fcoe->netdev; |
1060 | struct fc_lport *lport, *n_port; | 1090 | struct fc_lport *lport, *n_port; |
1061 | struct fcoe_port *port; | 1091 | struct fcoe_port *port; |
@@ -1119,7 +1149,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
1119 | } | 1149 | } |
1120 | 1150 | ||
1121 | /* Initialize the library */ | 1151 | /* Initialize the library */ |
1122 | rc = fcoe_libfc_config(lport, &fcoe->ctlr, &fcoe_libfc_fcn_templ, 1); | 1152 | rc = fcoe_libfc_config(lport, ctlr, &fcoe_libfc_fcn_templ, 1); |
1123 | if (rc) { | 1153 | if (rc) { |
1124 | FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " | 1154 | FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " |
1125 | "interface\n"); | 1155 | "interface\n"); |
@@ -1386,6 +1416,7 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1386 | { | 1416 | { |
1387 | struct fc_lport *lport; | 1417 | struct fc_lport *lport; |
1388 | struct fcoe_rcv_info *fr; | 1418 | struct fcoe_rcv_info *fr; |
1419 | struct fcoe_ctlr *ctlr; | ||
1389 | struct fcoe_interface *fcoe; | 1420 | struct fcoe_interface *fcoe; |
1390 | struct fc_frame_header *fh; | 1421 | struct fc_frame_header *fh; |
1391 | struct fcoe_percpu_s *fps; | 1422 | struct fcoe_percpu_s *fps; |
@@ -1393,7 +1424,8 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1393 | unsigned int cpu; | 1424 | unsigned int cpu; |
1394 | 1425 | ||
1395 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); | 1426 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); |
1396 | lport = fcoe->ctlr.lp; | 1427 | ctlr = fcoe_to_ctlr(fcoe); |
1428 | lport = ctlr->lp; | ||
1397 | if (unlikely(!lport)) { | 1429 | if (unlikely(!lport)) { |
1398 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); | 1430 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); |
1399 | goto err2; | 1431 | goto err2; |
@@ -1409,8 +1441,8 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1409 | 1441 | ||
1410 | eh = eth_hdr(skb); | 1442 | eh = eth_hdr(skb); |
1411 | 1443 | ||
1412 | if (is_fip_mode(&fcoe->ctlr) && | 1444 | if (is_fip_mode(ctlr) && |
1413 | compare_ether_addr(eh->h_source, fcoe->ctlr.dest_addr)) { | 1445 | compare_ether_addr(eh->h_source, ctlr->dest_addr)) { |
1414 | FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", | 1446 | FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", |
1415 | eh->h_source); | 1447 | eh->h_source); |
1416 | goto err; | 1448 | goto err; |
@@ -1544,6 +1576,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1544 | unsigned int elen; /* eth header, may include vlan */ | 1576 | unsigned int elen; /* eth header, may include vlan */ |
1545 | struct fcoe_port *port = lport_priv(lport); | 1577 | struct fcoe_port *port = lport_priv(lport); |
1546 | struct fcoe_interface *fcoe = port->priv; | 1578 | struct fcoe_interface *fcoe = port->priv; |
1579 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
1547 | u8 sof, eof; | 1580 | u8 sof, eof; |
1548 | struct fcoe_hdr *hp; | 1581 | struct fcoe_hdr *hp; |
1549 | 1582 | ||
@@ -1559,7 +1592,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1559 | } | 1592 | } |
1560 | 1593 | ||
1561 | if (unlikely(fh->fh_type == FC_TYPE_ELS) && | 1594 | if (unlikely(fh->fh_type == FC_TYPE_ELS) && |
1562 | fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) | 1595 | fcoe_ctlr_els_send(ctlr, lport, skb)) |
1563 | return 0; | 1596 | return 0; |
1564 | 1597 | ||
1565 | sof = fr_sof(fp); | 1598 | sof = fr_sof(fp); |
@@ -1623,12 +1656,12 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1623 | /* fill up mac and fcoe headers */ | 1656 | /* fill up mac and fcoe headers */ |
1624 | eh = eth_hdr(skb); | 1657 | eh = eth_hdr(skb); |
1625 | eh->h_proto = htons(ETH_P_FCOE); | 1658 | eh->h_proto = htons(ETH_P_FCOE); |
1626 | memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); | 1659 | memcpy(eh->h_dest, ctlr->dest_addr, ETH_ALEN); |
1627 | if (fcoe->ctlr.map_dest) | 1660 | if (ctlr->map_dest) |
1628 | memcpy(eh->h_dest + 3, fh->fh_d_id, 3); | 1661 | memcpy(eh->h_dest + 3, fh->fh_d_id, 3); |
1629 | 1662 | ||
1630 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) | 1663 | if (unlikely(ctlr->flogi_oxid != FC_XID_UNKNOWN)) |
1631 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); | 1664 | memcpy(eh->h_source, ctlr->ctl_src_addr, ETH_ALEN); |
1632 | else | 1665 | else |
1633 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); | 1666 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); |
1634 | 1667 | ||
@@ -1677,6 +1710,7 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb) | |||
1677 | static inline int fcoe_filter_frames(struct fc_lport *lport, | 1710 | static inline int fcoe_filter_frames(struct fc_lport *lport, |
1678 | struct fc_frame *fp) | 1711 | struct fc_frame *fp) |
1679 | { | 1712 | { |
1713 | struct fcoe_ctlr *ctlr; | ||
1680 | struct fcoe_interface *fcoe; | 1714 | struct fcoe_interface *fcoe; |
1681 | struct fc_frame_header *fh; | 1715 | struct fc_frame_header *fh; |
1682 | struct sk_buff *skb = (struct sk_buff *)fp; | 1716 | struct sk_buff *skb = (struct sk_buff *)fp; |
@@ -1698,7 +1732,8 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, | |||
1698 | return 0; | 1732 | return 0; |
1699 | 1733 | ||
1700 | fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; | 1734 | fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; |
1701 | if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && | 1735 | ctlr = fcoe_to_ctlr(fcoe); |
1736 | if (is_fip_mode(ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && | ||
1702 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { | 1737 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { |
1703 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); | 1738 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); |
1704 | return -EINVAL; | 1739 | return -EINVAL; |
@@ -1877,6 +1912,7 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, | |||
1877 | ulong event, void *ptr) | 1912 | ulong event, void *ptr) |
1878 | { | 1913 | { |
1879 | struct dcb_app_type *entry = ptr; | 1914 | struct dcb_app_type *entry = ptr; |
1915 | struct fcoe_ctlr *ctlr; | ||
1880 | struct fcoe_interface *fcoe; | 1916 | struct fcoe_interface *fcoe; |
1881 | struct net_device *netdev; | 1917 | struct net_device *netdev; |
1882 | struct fcoe_port *port; | 1918 | struct fcoe_port *port; |
@@ -1894,6 +1930,8 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, | |||
1894 | if (!fcoe) | 1930 | if (!fcoe) |
1895 | return NOTIFY_OK; | 1931 | return NOTIFY_OK; |
1896 | 1932 | ||
1933 | ctlr = fcoe_to_ctlr(fcoe); | ||
1934 | |||
1897 | if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) | 1935 | if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) |
1898 | prio = ffs(entry->app.priority) - 1; | 1936 | prio = ffs(entry->app.priority) - 1; |
1899 | else | 1937 | else |
@@ -1904,10 +1942,10 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, | |||
1904 | 1942 | ||
1905 | if (entry->app.protocol == ETH_P_FIP || | 1943 | if (entry->app.protocol == ETH_P_FIP || |
1906 | entry->app.protocol == ETH_P_FCOE) | 1944 | entry->app.protocol == ETH_P_FCOE) |
1907 | fcoe->ctlr.priority = prio; | 1945 | ctlr->priority = prio; |
1908 | 1946 | ||
1909 | if (entry->app.protocol == ETH_P_FCOE) { | 1947 | if (entry->app.protocol == ETH_P_FCOE) { |
1910 | port = lport_priv(fcoe->ctlr.lp); | 1948 | port = lport_priv(ctlr->lp); |
1911 | port->priority = prio; | 1949 | port->priority = prio; |
1912 | } | 1950 | } |
1913 | 1951 | ||
@@ -1929,6 +1967,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1929 | { | 1967 | { |
1930 | struct fc_lport *lport = NULL; | 1968 | struct fc_lport *lport = NULL; |
1931 | struct net_device *netdev = ptr; | 1969 | struct net_device *netdev = ptr; |
1970 | struct fcoe_ctlr *ctlr; | ||
1932 | struct fcoe_interface *fcoe; | 1971 | struct fcoe_interface *fcoe; |
1933 | struct fcoe_port *port; | 1972 | struct fcoe_port *port; |
1934 | struct fcoe_dev_stats *stats; | 1973 | struct fcoe_dev_stats *stats; |
@@ -1938,7 +1977,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1938 | 1977 | ||
1939 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { | 1978 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { |
1940 | if (fcoe->netdev == netdev) { | 1979 | if (fcoe->netdev == netdev) { |
1941 | lport = fcoe->ctlr.lp; | 1980 | ctlr = fcoe_to_ctlr(fcoe); |
1981 | lport = ctlr->lp; | ||
1942 | break; | 1982 | break; |
1943 | } | 1983 | } |
1944 | } | 1984 | } |
@@ -1967,7 +2007,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1967 | break; | 2007 | break; |
1968 | case NETDEV_UNREGISTER: | 2008 | case NETDEV_UNREGISTER: |
1969 | list_del(&fcoe->list); | 2009 | list_del(&fcoe->list); |
1970 | port = lport_priv(fcoe->ctlr.lp); | 2010 | port = lport_priv(ctlr->lp); |
1971 | queue_work(fcoe_wq, &port->destroy_work); | 2011 | queue_work(fcoe_wq, &port->destroy_work); |
1972 | goto out; | 2012 | goto out; |
1973 | break; | 2013 | break; |
@@ -1982,8 +2022,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1982 | fcoe_link_speed_update(lport); | 2022 | fcoe_link_speed_update(lport); |
1983 | 2023 | ||
1984 | if (link_possible && !fcoe_link_ok(lport)) | 2024 | if (link_possible && !fcoe_link_ok(lport)) |
1985 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2025 | fcoe_ctlr_link_up(ctlr); |
1986 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { | 2026 | else if (fcoe_ctlr_link_down(ctlr)) { |
1987 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); | 2027 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
1988 | stats->LinkFailureCount++; | 2028 | stats->LinkFailureCount++; |
1989 | put_cpu(); | 2029 | put_cpu(); |
@@ -2003,6 +2043,7 @@ out: | |||
2003 | */ | 2043 | */ |
2004 | static int fcoe_disable(struct net_device *netdev) | 2044 | static int fcoe_disable(struct net_device *netdev) |
2005 | { | 2045 | { |
2046 | struct fcoe_ctlr *ctlr; | ||
2006 | struct fcoe_interface *fcoe; | 2047 | struct fcoe_interface *fcoe; |
2007 | int rc = 0; | 2048 | int rc = 0; |
2008 | 2049 | ||
@@ -2013,8 +2054,9 @@ static int fcoe_disable(struct net_device *netdev) | |||
2013 | rtnl_unlock(); | 2054 | rtnl_unlock(); |
2014 | 2055 | ||
2015 | if (fcoe) { | 2056 | if (fcoe) { |
2016 | fcoe_ctlr_link_down(&fcoe->ctlr); | 2057 | ctlr = fcoe_to_ctlr(fcoe); |
2017 | fcoe_clean_pending_queue(fcoe->ctlr.lp); | 2058 | fcoe_ctlr_link_down(ctlr); |
2059 | fcoe_clean_pending_queue(ctlr->lp); | ||
2018 | } else | 2060 | } else |
2019 | rc = -ENODEV; | 2061 | rc = -ENODEV; |
2020 | 2062 | ||
@@ -2032,6 +2074,7 @@ static int fcoe_disable(struct net_device *netdev) | |||
2032 | */ | 2074 | */ |
2033 | static int fcoe_enable(struct net_device *netdev) | 2075 | static int fcoe_enable(struct net_device *netdev) |
2034 | { | 2076 | { |
2077 | struct fcoe_ctlr *ctlr; | ||
2035 | struct fcoe_interface *fcoe; | 2078 | struct fcoe_interface *fcoe; |
2036 | int rc = 0; | 2079 | int rc = 0; |
2037 | 2080 | ||
@@ -2040,11 +2083,17 @@ static int fcoe_enable(struct net_device *netdev) | |||
2040 | fcoe = fcoe_hostlist_lookup_port(netdev); | 2083 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2041 | rtnl_unlock(); | 2084 | rtnl_unlock(); |
2042 | 2085 | ||
2043 | if (!fcoe) | 2086 | if (!fcoe) { |
2044 | rc = -ENODEV; | 2087 | rc = -ENODEV; |
2045 | else if (!fcoe_link_ok(fcoe->ctlr.lp)) | 2088 | goto out; |
2046 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2089 | } |
2090 | |||
2091 | ctlr = fcoe_to_ctlr(fcoe); | ||
2092 | |||
2093 | if (!fcoe_link_ok(ctlr->lp)) | ||
2094 | fcoe_ctlr_link_up(ctlr); | ||
2047 | 2095 | ||
2096 | out: | ||
2048 | mutex_unlock(&fcoe_config_mutex); | 2097 | mutex_unlock(&fcoe_config_mutex); |
2049 | return rc; | 2098 | return rc; |
2050 | } | 2099 | } |
@@ -2059,6 +2108,7 @@ static int fcoe_enable(struct net_device *netdev) | |||
2059 | */ | 2108 | */ |
2060 | static int fcoe_destroy(struct net_device *netdev) | 2109 | static int fcoe_destroy(struct net_device *netdev) |
2061 | { | 2110 | { |
2111 | struct fcoe_ctlr *ctlr; | ||
2062 | struct fcoe_interface *fcoe; | 2112 | struct fcoe_interface *fcoe; |
2063 | struct fc_lport *lport; | 2113 | struct fc_lport *lport; |
2064 | struct fcoe_port *port; | 2114 | struct fcoe_port *port; |
@@ -2071,7 +2121,8 @@ static int fcoe_destroy(struct net_device *netdev) | |||
2071 | rc = -ENODEV; | 2121 | rc = -ENODEV; |
2072 | goto out_nodev; | 2122 | goto out_nodev; |
2073 | } | 2123 | } |
2074 | lport = fcoe->ctlr.lp; | 2124 | ctlr = fcoe_to_ctlr(fcoe); |
2125 | lport = ctlr->lp; | ||
2075 | port = lport_priv(lport); | 2126 | port = lport_priv(lport); |
2076 | list_del(&fcoe->list); | 2127 | list_del(&fcoe->list); |
2077 | queue_work(fcoe_wq, &port->destroy_work); | 2128 | queue_work(fcoe_wq, &port->destroy_work); |
@@ -2126,7 +2177,8 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2126 | int dcbx; | 2177 | int dcbx; |
2127 | u8 fup, up; | 2178 | u8 fup, up; |
2128 | struct net_device *netdev = fcoe->realdev; | 2179 | struct net_device *netdev = fcoe->realdev; |
2129 | struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); | 2180 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); |
2181 | struct fcoe_port *port = lport_priv(ctlr->lp); | ||
2130 | struct dcb_app app = { | 2182 | struct dcb_app app = { |
2131 | .priority = 0, | 2183 | .priority = 0, |
2132 | .protocol = ETH_P_FCOE | 2184 | .protocol = ETH_P_FCOE |
@@ -2149,7 +2201,7 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2149 | } | 2201 | } |
2150 | 2202 | ||
2151 | port->priority = ffs(up) ? ffs(up) - 1 : 0; | 2203 | port->priority = ffs(up) ? ffs(up) - 1 : 0; |
2152 | fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority; | 2204 | ctlr->priority = ffs(fup) ? ffs(fup) - 1 : port->priority; |
2153 | } | 2205 | } |
2154 | #endif | 2206 | #endif |
2155 | } | 2207 | } |
@@ -2166,6 +2218,8 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2166 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | 2218 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) |
2167 | { | 2219 | { |
2168 | int rc = 0; | 2220 | int rc = 0; |
2221 | struct fcoe_ctlr_device *ctlr_dev; | ||
2222 | struct fcoe_ctlr *ctlr; | ||
2169 | struct fcoe_interface *fcoe; | 2223 | struct fcoe_interface *fcoe; |
2170 | struct fc_lport *lport; | 2224 | struct fc_lport *lport; |
2171 | 2225 | ||
@@ -2184,7 +2238,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2184 | goto out_nodev; | 2238 | goto out_nodev; |
2185 | } | 2239 | } |
2186 | 2240 | ||
2187 | lport = fcoe_if_create(fcoe, &netdev->dev, 0); | 2241 | ctlr = fcoe_to_ctlr(fcoe); |
2242 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); | ||
2243 | lport = fcoe_if_create(fcoe, &ctlr_dev->dev, 0); | ||
2188 | if (IS_ERR(lport)) { | 2244 | if (IS_ERR(lport)) { |
2189 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", | 2245 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", |
2190 | netdev->name); | 2246 | netdev->name); |
@@ -2195,7 +2251,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2195 | } | 2251 | } |
2196 | 2252 | ||
2197 | /* Make this the "master" N_Port */ | 2253 | /* Make this the "master" N_Port */ |
2198 | fcoe->ctlr.lp = lport; | 2254 | ctlr->lp = lport; |
2199 | 2255 | ||
2200 | /* setup DCB priority attributes. */ | 2256 | /* setup DCB priority attributes. */ |
2201 | fcoe_dcb_create(fcoe); | 2257 | fcoe_dcb_create(fcoe); |
@@ -2208,7 +2264,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2208 | fc_fabric_login(lport); | 2264 | fc_fabric_login(lport); |
2209 | if (!fcoe_link_ok(lport)) { | 2265 | if (!fcoe_link_ok(lport)) { |
2210 | rtnl_unlock(); | 2266 | rtnl_unlock(); |
2211 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2267 | fcoe_ctlr_link_up(ctlr); |
2212 | mutex_unlock(&fcoe_config_mutex); | 2268 | mutex_unlock(&fcoe_config_mutex); |
2213 | return rc; | 2269 | return rc; |
2214 | } | 2270 | } |
@@ -2320,11 +2376,12 @@ static int fcoe_reset(struct Scsi_Host *shost) | |||
2320 | struct fc_lport *lport = shost_priv(shost); | 2376 | struct fc_lport *lport = shost_priv(shost); |
2321 | struct fcoe_port *port = lport_priv(lport); | 2377 | struct fcoe_port *port = lport_priv(lport); |
2322 | struct fcoe_interface *fcoe = port->priv; | 2378 | struct fcoe_interface *fcoe = port->priv; |
2379 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
2323 | 2380 | ||
2324 | fcoe_ctlr_link_down(&fcoe->ctlr); | 2381 | fcoe_ctlr_link_down(ctlr); |
2325 | fcoe_clean_pending_queue(fcoe->ctlr.lp); | 2382 | fcoe_clean_pending_queue(ctlr->lp); |
2326 | if (!fcoe_link_ok(fcoe->ctlr.lp)) | 2383 | if (!fcoe_link_ok(ctlr->lp)) |
2327 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2384 | fcoe_ctlr_link_up(ctlr); |
2328 | return 0; | 2385 | return 0; |
2329 | } | 2386 | } |
2330 | 2387 | ||
@@ -2359,10 +2416,12 @@ fcoe_hostlist_lookup_port(const struct net_device *netdev) | |||
2359 | */ | 2416 | */ |
2360 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) | 2417 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) |
2361 | { | 2418 | { |
2419 | struct fcoe_ctlr *ctlr; | ||
2362 | struct fcoe_interface *fcoe; | 2420 | struct fcoe_interface *fcoe; |
2363 | 2421 | ||
2364 | fcoe = fcoe_hostlist_lookup_port(netdev); | 2422 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2365 | return (fcoe) ? fcoe->ctlr.lp : NULL; | 2423 | ctlr = fcoe_to_ctlr(fcoe); |
2424 | return (fcoe) ? ctlr->lp : NULL; | ||
2366 | } | 2425 | } |
2367 | 2426 | ||
2368 | /** | 2427 | /** |
@@ -2466,6 +2525,7 @@ module_init(fcoe_init); | |||
2466 | static void __exit fcoe_exit(void) | 2525 | static void __exit fcoe_exit(void) |
2467 | { | 2526 | { |
2468 | struct fcoe_interface *fcoe, *tmp; | 2527 | struct fcoe_interface *fcoe, *tmp; |
2528 | struct fcoe_ctlr *ctlr; | ||
2469 | struct fcoe_port *port; | 2529 | struct fcoe_port *port; |
2470 | unsigned int cpu; | 2530 | unsigned int cpu; |
2471 | 2531 | ||
@@ -2477,7 +2537,8 @@ static void __exit fcoe_exit(void) | |||
2477 | rtnl_lock(); | 2537 | rtnl_lock(); |
2478 | list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { | 2538 | list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { |
2479 | list_del(&fcoe->list); | 2539 | list_del(&fcoe->list); |
2480 | port = lport_priv(fcoe->ctlr.lp); | 2540 | ctlr = fcoe_to_ctlr(fcoe); |
2541 | port = lport_priv(ctlr->lp); | ||
2481 | queue_work(fcoe_wq, &port->destroy_work); | 2542 | queue_work(fcoe_wq, &port->destroy_work); |
2482 | } | 2543 | } |
2483 | rtnl_unlock(); | 2544 | rtnl_unlock(); |
@@ -2573,7 +2634,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, | |||
2573 | { | 2634 | { |
2574 | struct fcoe_port *port = lport_priv(lport); | 2635 | struct fcoe_port *port = lport_priv(lport); |
2575 | struct fcoe_interface *fcoe = port->priv; | 2636 | struct fcoe_interface *fcoe = port->priv; |
2576 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 2637 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); |
2577 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 2638 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
2578 | 2639 | ||
2579 | switch (op) { | 2640 | switch (op) { |
@@ -2730,6 +2791,40 @@ static void fcoe_get_lesb(struct fc_lport *lport, | |||
2730 | __fcoe_get_lesb(lport, fc_lesb, netdev); | 2791 | __fcoe_get_lesb(lport, fc_lesb, netdev); |
2731 | } | 2792 | } |
2732 | 2793 | ||
2794 | static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) | ||
2795 | { | ||
2796 | struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); | ||
2797 | struct net_device *netdev = fcoe_netdev(fip->lp); | ||
2798 | struct fcoe_fc_els_lesb *fcoe_lesb; | ||
2799 | struct fc_els_lesb fc_lesb; | ||
2800 | |||
2801 | __fcoe_get_lesb(fip->lp, &fc_lesb, netdev); | ||
2802 | fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb); | ||
2803 | |||
2804 | ctlr_dev->lesb.lesb_link_fail = | ||
2805 | ntohl(fcoe_lesb->lesb_link_fail); | ||
2806 | ctlr_dev->lesb.lesb_vlink_fail = | ||
2807 | ntohl(fcoe_lesb->lesb_vlink_fail); | ||
2808 | ctlr_dev->lesb.lesb_miss_fka = | ||
2809 | ntohl(fcoe_lesb->lesb_miss_fka); | ||
2810 | ctlr_dev->lesb.lesb_symb_err = | ||
2811 | ntohl(fcoe_lesb->lesb_symb_err); | ||
2812 | ctlr_dev->lesb.lesb_err_block = | ||
2813 | ntohl(fcoe_lesb->lesb_err_block); | ||
2814 | ctlr_dev->lesb.lesb_fcs_error = | ||
2815 | ntohl(fcoe_lesb->lesb_fcs_error); | ||
2816 | } | ||
2817 | |||
2818 | static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) | ||
2819 | { | ||
2820 | struct fcoe_ctlr_device *ctlr_dev = | ||
2821 | fcoe_fcf_dev_to_ctlr_dev(fcf_dev); | ||
2822 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
2823 | struct fcoe_interface *fcoe = fcoe_ctlr_priv(ctlr); | ||
2824 | |||
2825 | fcf_dev->vlan_id = vlan_dev_vlan_id(fcoe->netdev); | ||
2826 | } | ||
2827 | |||
2733 | /** | 2828 | /** |
2734 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. | 2829 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. |
2735 | * @lport: the local port | 2830 | * @lport: the local port |
@@ -2747,7 +2842,8 @@ static void fcoe_set_port_id(struct fc_lport *lport, | |||
2747 | { | 2842 | { |
2748 | struct fcoe_port *port = lport_priv(lport); | 2843 | struct fcoe_port *port = lport_priv(lport); |
2749 | struct fcoe_interface *fcoe = port->priv; | 2844 | struct fcoe_interface *fcoe = port->priv; |
2845 | struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | ||
2750 | 2846 | ||
2751 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | 2847 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) |
2752 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | 2848 | fcoe_ctlr_recv_flogi(ctlr, lport, fp); |
2753 | } | 2849 | } |
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index 96ac938d39cc..a624add4f8ec 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
@@ -68,7 +68,6 @@ do { \ | |||
68 | * @netdev: The associated net device | 68 | * @netdev: The associated net device |
69 | * @fcoe_packet_type: FCoE packet type | 69 | * @fcoe_packet_type: FCoE packet type |
70 | * @fip_packet_type: FIP packet type | 70 | * @fip_packet_type: FIP packet type |
71 | * @ctlr: The FCoE controller (for FIP) | ||
72 | * @oem: The offload exchange manager for all local port | 71 | * @oem: The offload exchange manager for all local port |
73 | * instances associated with this port | 72 | * instances associated with this port |
74 | * @removed: Indicates fcoe interface removed from net device | 73 | * @removed: Indicates fcoe interface removed from net device |
@@ -80,12 +79,15 @@ struct fcoe_interface { | |||
80 | struct net_device *realdev; | 79 | struct net_device *realdev; |
81 | struct packet_type fcoe_packet_type; | 80 | struct packet_type fcoe_packet_type; |
82 | struct packet_type fip_packet_type; | 81 | struct packet_type fip_packet_type; |
83 | struct fcoe_ctlr ctlr; | ||
84 | struct fc_exch_mgr *oem; | 82 | struct fc_exch_mgr *oem; |
85 | u8 removed; | 83 | u8 removed; |
86 | }; | 84 | }; |
87 | 85 | ||
88 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) | 86 | #define fcoe_to_ctlr(x) \ |
87 | (struct fcoe_ctlr *)(((struct fcoe_ctlr *)(x)) - 1) | ||
88 | |||
89 | #define fcoe_from_ctlr(x) \ | ||
90 | ((struct fcoe_interface *)((x) + 1)) | ||
89 | 91 | ||
90 | /** | 92 | /** |
91 | * fcoe_netdev() - Return the net device associated with a local port | 93 | * fcoe_netdev() - Return the net device associated with a local port |
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 5a4c7250aa77..d68d57241ee6 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -160,6 +160,76 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) | |||
160 | } | 160 | } |
161 | EXPORT_SYMBOL(fcoe_ctlr_init); | 161 | EXPORT_SYMBOL(fcoe_ctlr_init); |
162 | 162 | ||
163 | static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) | ||
164 | { | ||
165 | struct fcoe_ctlr *fip = new->fip; | ||
166 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | ||
167 | struct fcoe_fcf_device temp, *fcf_dev; | ||
168 | int rc = 0; | ||
169 | |||
170 | LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", | ||
171 | new->fabric_name, new->fcf_mac); | ||
172 | |||
173 | mutex_lock(&ctlr_dev->lock); | ||
174 | |||
175 | temp.fabric_name = new->fabric_name; | ||
176 | temp.switch_name = new->switch_name; | ||
177 | temp.fc_map = new->fc_map; | ||
178 | temp.vfid = new->vfid; | ||
179 | memcpy(temp.mac, new->fcf_mac, ETH_ALEN); | ||
180 | temp.priority = new->pri; | ||
181 | temp.fka_period = new->fka_period; | ||
182 | temp.selected = 0; /* default to unselected */ | ||
183 | |||
184 | fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp); | ||
185 | if (unlikely(!fcf_dev)) { | ||
186 | rc = -ENOMEM; | ||
187 | goto out; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * The fcoe_sysfs layer can return a CONNECTED fcf that | ||
192 | * has a priv (fcf was never deleted) or a CONNECTED fcf | ||
193 | * that doesn't have a priv (fcf was deleted). However, | ||
194 | * libfcoe will always delete FCFs before trying to add | ||
195 | * them. This is ensured because both recv_adv and | ||
196 | * age_fcfs are protected by the the fcoe_ctlr's mutex. | ||
197 | * This means that we should never get a FCF with a | ||
198 | * non-NULL priv pointer. | ||
199 | */ | ||
200 | BUG_ON(fcf_dev->priv); | ||
201 | |||
202 | fcf_dev->priv = new; | ||
203 | new->fcf_dev = fcf_dev; | ||
204 | |||
205 | list_add(&new->list, &fip->fcfs); | ||
206 | fip->fcf_count++; | ||
207 | |||
208 | out: | ||
209 | mutex_unlock(&ctlr_dev->lock); | ||
210 | return rc; | ||
211 | } | ||
212 | |||
213 | static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) | ||
214 | { | ||
215 | struct fcoe_ctlr *fip = new->fip; | ||
216 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | ||
217 | struct fcoe_fcf_device *fcf_dev; | ||
218 | |||
219 | list_del(&new->list); | ||
220 | fip->fcf_count--; | ||
221 | |||
222 | mutex_lock(&ctlr_dev->lock); | ||
223 | |||
224 | fcf_dev = fcoe_fcf_to_fcf_dev(new); | ||
225 | WARN_ON(!fcf_dev); | ||
226 | new->fcf_dev = NULL; | ||
227 | fcoe_fcf_device_delete(fcf_dev); | ||
228 | kfree(new); | ||
229 | |||
230 | mutex_unlock(&ctlr_dev->lock); | ||
231 | } | ||
232 | |||
163 | /** | 233 | /** |
164 | * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller | 234 | * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller |
165 | * @fip: The FCoE controller whose FCFs are to be reset | 235 | * @fip: The FCoE controller whose FCFs are to be reset |
@@ -173,10 +243,10 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) | |||
173 | 243 | ||
174 | fip->sel_fcf = NULL; | 244 | fip->sel_fcf = NULL; |
175 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 245 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
176 | list_del(&fcf->list); | 246 | fcoe_sysfs_fcf_del(fcf); |
177 | kfree(fcf); | ||
178 | } | 247 | } |
179 | fip->fcf_count = 0; | 248 | WARN_ON(fip->fcf_count); |
249 | |||
180 | fip->sel_time = 0; | 250 | fip->sel_time = 0; |
181 | } | 251 | } |
182 | 252 | ||
@@ -717,8 +787,11 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
717 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | 787 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); |
718 | unsigned long deadline; | 788 | unsigned long deadline; |
719 | unsigned long sel_time = 0; | 789 | unsigned long sel_time = 0; |
790 | struct list_head del_list; | ||
720 | struct fcoe_dev_stats *stats; | 791 | struct fcoe_dev_stats *stats; |
721 | 792 | ||
793 | INIT_LIST_HEAD(&del_list); | ||
794 | |||
722 | stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); | 795 | stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); |
723 | 796 | ||
724 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 797 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
@@ -739,10 +812,13 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
739 | if (time_after_eq(jiffies, deadline)) { | 812 | if (time_after_eq(jiffies, deadline)) { |
740 | if (fip->sel_fcf == fcf) | 813 | if (fip->sel_fcf == fcf) |
741 | fip->sel_fcf = NULL; | 814 | fip->sel_fcf = NULL; |
815 | /* | ||
816 | * Move to delete list so we can call | ||
817 | * fcoe_sysfs_fcf_del (which can sleep) | ||
818 | * after the put_cpu(). | ||
819 | */ | ||
742 | list_del(&fcf->list); | 820 | list_del(&fcf->list); |
743 | WARN_ON(!fip->fcf_count); | 821 | list_add(&fcf->list, &del_list); |
744 | fip->fcf_count--; | ||
745 | kfree(fcf); | ||
746 | stats->VLinkFailureCount++; | 822 | stats->VLinkFailureCount++; |
747 | } else { | 823 | } else { |
748 | if (time_after(next_timer, deadline)) | 824 | if (time_after(next_timer, deadline)) |
@@ -753,6 +829,12 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
753 | } | 829 | } |
754 | } | 830 | } |
755 | put_cpu(); | 831 | put_cpu(); |
832 | |||
833 | list_for_each_entry_safe(fcf, next, &del_list, list) { | ||
834 | /* Removes fcf from current list */ | ||
835 | fcoe_sysfs_fcf_del(fcf); | ||
836 | } | ||
837 | |||
756 | if (sel_time && !fip->sel_fcf && !fip->sel_time) { | 838 | if (sel_time && !fip->sel_fcf && !fip->sel_time) { |
757 | sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); | 839 | sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); |
758 | fip->sel_time = sel_time; | 840 | fip->sel_time = sel_time; |
@@ -903,23 +985,23 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
903 | { | 985 | { |
904 | struct fcoe_fcf *fcf; | 986 | struct fcoe_fcf *fcf; |
905 | struct fcoe_fcf new; | 987 | struct fcoe_fcf new; |
906 | struct fcoe_fcf *found; | ||
907 | unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); | 988 | unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); |
908 | int first = 0; | 989 | int first = 0; |
909 | int mtu_valid; | 990 | int mtu_valid; |
991 | int found = 0; | ||
992 | int rc = 0; | ||
910 | 993 | ||
911 | if (fcoe_ctlr_parse_adv(fip, skb, &new)) | 994 | if (fcoe_ctlr_parse_adv(fip, skb, &new)) |
912 | return; | 995 | return; |
913 | 996 | ||
914 | mutex_lock(&fip->ctlr_mutex); | 997 | mutex_lock(&fip->ctlr_mutex); |
915 | first = list_empty(&fip->fcfs); | 998 | first = list_empty(&fip->fcfs); |
916 | found = NULL; | ||
917 | list_for_each_entry(fcf, &fip->fcfs, list) { | 999 | list_for_each_entry(fcf, &fip->fcfs, list) { |
918 | if (fcf->switch_name == new.switch_name && | 1000 | if (fcf->switch_name == new.switch_name && |
919 | fcf->fabric_name == new.fabric_name && | 1001 | fcf->fabric_name == new.fabric_name && |
920 | fcf->fc_map == new.fc_map && | 1002 | fcf->fc_map == new.fc_map && |
921 | compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { | 1003 | compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { |
922 | found = fcf; | 1004 | found = 1; |
923 | break; | 1005 | break; |
924 | } | 1006 | } |
925 | } | 1007 | } |
@@ -931,9 +1013,16 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
931 | if (!fcf) | 1013 | if (!fcf) |
932 | goto out; | 1014 | goto out; |
933 | 1015 | ||
934 | fip->fcf_count++; | ||
935 | memcpy(fcf, &new, sizeof(new)); | 1016 | memcpy(fcf, &new, sizeof(new)); |
936 | list_add(&fcf->list, &fip->fcfs); | 1017 | fcf->fip = fip; |
1018 | rc = fcoe_sysfs_fcf_add(fcf); | ||
1019 | if (rc) { | ||
1020 | printk(KERN_ERR "Failed to allocate sysfs instance " | ||
1021 | "for FCF, fab %16.16llx mac %pM\n", | ||
1022 | new.fabric_name, new.fcf_mac); | ||
1023 | kfree(fcf); | ||
1024 | goto out; | ||
1025 | } | ||
937 | } else { | 1026 | } else { |
938 | /* | 1027 | /* |
939 | * Update the FCF's keep-alive descriptor flags. | 1028 | * Update the FCF's keep-alive descriptor flags. |
@@ -954,6 +1043,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
954 | fcf->fka_period = new.fka_period; | 1043 | fcf->fka_period = new.fka_period; |
955 | memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); | 1044 | memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); |
956 | } | 1045 | } |
1046 | |||
957 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); | 1047 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); |
958 | fcf->time = jiffies; | 1048 | fcf->time = jiffies; |
959 | if (!found) | 1049 | if (!found) |
@@ -996,6 +1086,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
996 | time_before(fip->sel_time, fip->timer.expires)) | 1086 | time_before(fip->sel_time, fip->timer.expires)) |
997 | mod_timer(&fip->timer, fip->sel_time); | 1087 | mod_timer(&fip->timer, fip->sel_time); |
998 | } | 1088 | } |
1089 | |||
999 | out: | 1090 | out: |
1000 | mutex_unlock(&fip->ctlr_mutex); | 1091 | mutex_unlock(&fip->ctlr_mutex); |
1001 | } | 1092 | } |
@@ -2718,9 +2809,9 @@ unlock: | |||
2718 | 2809 | ||
2719 | /** | 2810 | /** |
2720 | * fcoe_libfc_config() - Sets up libfc related properties for local port | 2811 | * fcoe_libfc_config() - Sets up libfc related properties for local port |
2721 | * @lp: The local port to configure libfc for | 2812 | * @lport: The local port to configure libfc for |
2722 | * @fip: The FCoE controller in use by the local port | 2813 | * @fip: The FCoE controller in use by the local port |
2723 | * @tt: The libfc function template | 2814 | * @tt: The libfc function template |
2724 | * @init_fcp: If non-zero, the FCP portion of libfc should be initialized | 2815 | * @init_fcp: If non-zero, the FCP portion of libfc should be initialized |
2725 | * | 2816 | * |
2726 | * Returns : 0 for success | 2817 | * Returns : 0 for success |
@@ -2753,3 +2844,43 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, | |||
2753 | return 0; | 2844 | return 0; |
2754 | } | 2845 | } |
2755 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); | 2846 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); |
2847 | |||
2848 | void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev) | ||
2849 | { | ||
2850 | struct fcoe_ctlr_device *ctlr_dev = fcoe_fcf_dev_to_ctlr_dev(fcf_dev); | ||
2851 | struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); | ||
2852 | struct fcoe_fcf *fcf; | ||
2853 | |||
2854 | mutex_lock(&fip->ctlr_mutex); | ||
2855 | mutex_lock(&ctlr_dev->lock); | ||
2856 | |||
2857 | fcf = fcoe_fcf_device_priv(fcf_dev); | ||
2858 | if (fcf) | ||
2859 | fcf_dev->selected = (fcf == fip->sel_fcf) ? 1 : 0; | ||
2860 | else | ||
2861 | fcf_dev->selected = 0; | ||
2862 | |||
2863 | mutex_unlock(&ctlr_dev->lock); | ||
2864 | mutex_unlock(&fip->ctlr_mutex); | ||
2865 | } | ||
2866 | EXPORT_SYMBOL(fcoe_fcf_get_selected); | ||
2867 | |||
2868 | void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *ctlr_dev) | ||
2869 | { | ||
2870 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
2871 | |||
2872 | mutex_lock(&ctlr->ctlr_mutex); | ||
2873 | switch (ctlr->mode) { | ||
2874 | case FIP_MODE_FABRIC: | ||
2875 | ctlr_dev->mode = FIP_CONN_TYPE_FABRIC; | ||
2876 | break; | ||
2877 | case FIP_MODE_VN2VN: | ||
2878 | ctlr_dev->mode = FIP_CONN_TYPE_VN2VN; | ||
2879 | break; | ||
2880 | default: | ||
2881 | ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN; | ||
2882 | break; | ||
2883 | } | ||
2884 | mutex_unlock(&ctlr->ctlr_mutex); | ||
2885 | } | ||
2886 | EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode); | ||
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c new file mode 100644 index 000000000000..2bc163198d33 --- /dev/null +++ b/drivers/scsi/fcoe/fcoe_sysfs.c | |||
@@ -0,0 +1,832 @@ | |||
1 | /* | ||
2 | * Copyright(c) 2011 - 2012 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
16 | * | ||
17 | * Maintained at www.Open-FCoE.org | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/etherdevice.h> | ||
24 | |||
25 | #include <scsi/fcoe_sysfs.h> | ||
26 | |||
27 | static atomic_t ctlr_num; | ||
28 | static atomic_t fcf_num; | ||
29 | |||
30 | /* | ||
31 | * fcoe_fcf_dev_loss_tmo: the default number of seconds that fcoe sysfs | ||
32 | * should insulate the loss of a fcf. | ||
33 | */ | ||
34 | static unsigned int fcoe_fcf_dev_loss_tmo = 1800; /* seconds */ | ||
35 | |||
36 | module_param_named(fcf_dev_loss_tmo, fcoe_fcf_dev_loss_tmo, | ||
37 | uint, S_IRUGO|S_IWUSR); | ||
38 | MODULE_PARM_DESC(fcf_dev_loss_tmo, | ||
39 | "Maximum number of seconds that libfcoe should" | ||
40 | " insulate the loss of a fcf. Once this value is" | ||
41 | " exceeded, the fcf is removed."); | ||
42 | |||
43 | /* | ||
44 | * These are used by the fcoe_*_show_function routines, they | ||
45 | * are intentionally placed in the .c file as they're not intended | ||
46 | * for use throughout the code. | ||
47 | */ | ||
48 | #define fcoe_ctlr_id(x) \ | ||
49 | ((x)->id) | ||
50 | #define fcoe_ctlr_work_q_name(x) \ | ||
51 | ((x)->work_q_name) | ||
52 | #define fcoe_ctlr_work_q(x) \ | ||
53 | ((x)->work_q) | ||
54 | #define fcoe_ctlr_devloss_work_q_name(x) \ | ||
55 | ((x)->devloss_work_q_name) | ||
56 | #define fcoe_ctlr_devloss_work_q(x) \ | ||
57 | ((x)->devloss_work_q) | ||
58 | #define fcoe_ctlr_mode(x) \ | ||
59 | ((x)->mode) | ||
60 | #define fcoe_ctlr_fcf_dev_loss_tmo(x) \ | ||
61 | ((x)->fcf_dev_loss_tmo) | ||
62 | #define fcoe_ctlr_link_fail(x) \ | ||
63 | ((x)->lesb.lesb_link_fail) | ||
64 | #define fcoe_ctlr_vlink_fail(x) \ | ||
65 | ((x)->lesb.lesb_vlink_fail) | ||
66 | #define fcoe_ctlr_miss_fka(x) \ | ||
67 | ((x)->lesb.lesb_miss_fka) | ||
68 | #define fcoe_ctlr_symb_err(x) \ | ||
69 | ((x)->lesb.lesb_symb_err) | ||
70 | #define fcoe_ctlr_err_block(x) \ | ||
71 | ((x)->lesb.lesb_err_block) | ||
72 | #define fcoe_ctlr_fcs_error(x) \ | ||
73 | ((x)->lesb.lesb_fcs_error) | ||
74 | #define fcoe_fcf_state(x) \ | ||
75 | ((x)->state) | ||
76 | #define fcoe_fcf_fabric_name(x) \ | ||
77 | ((x)->fabric_name) | ||
78 | #define fcoe_fcf_switch_name(x) \ | ||
79 | ((x)->switch_name) | ||
80 | #define fcoe_fcf_fc_map(x) \ | ||
81 | ((x)->fc_map) | ||
82 | #define fcoe_fcf_vfid(x) \ | ||
83 | ((x)->vfid) | ||
84 | #define fcoe_fcf_mac(x) \ | ||
85 | ((x)->mac) | ||
86 | #define fcoe_fcf_priority(x) \ | ||
87 | ((x)->priority) | ||
88 | #define fcoe_fcf_fka_period(x) \ | ||
89 | ((x)->fka_period) | ||
90 | #define fcoe_fcf_dev_loss_tmo(x) \ | ||
91 | ((x)->dev_loss_tmo) | ||
92 | #define fcoe_fcf_selected(x) \ | ||
93 | ((x)->selected) | ||
94 | #define fcoe_fcf_vlan_id(x) \ | ||
95 | ((x)->vlan_id) | ||
96 | |||
97 | /* | ||
98 | * dev_loss_tmo attribute | ||
99 | */ | ||
100 | static int fcoe_str_to_dev_loss(const char *buf, unsigned long *val) | ||
101 | { | ||
102 | int ret; | ||
103 | |||
104 | ret = kstrtoul(buf, 0, val); | ||
105 | if (ret || *val < 0) | ||
106 | return -EINVAL; | ||
107 | /* | ||
108 | * Check for overflow; dev_loss_tmo is u32 | ||
109 | */ | ||
110 | if (*val > UINT_MAX) | ||
111 | return -EINVAL; | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int fcoe_fcf_set_dev_loss_tmo(struct fcoe_fcf_device *fcf, | ||
117 | unsigned long val) | ||
118 | { | ||
119 | if ((fcf->state == FCOE_FCF_STATE_UNKNOWN) || | ||
120 | (fcf->state == FCOE_FCF_STATE_DISCONNECTED) || | ||
121 | (fcf->state == FCOE_FCF_STATE_DELETED)) | ||
122 | return -EBUSY; | ||
123 | /* | ||
124 | * Check for overflow; dev_loss_tmo is u32 | ||
125 | */ | ||
126 | if (val > UINT_MAX) | ||
127 | return -EINVAL; | ||
128 | |||
129 | fcoe_fcf_dev_loss_tmo(fcf) = val; | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | #define FCOE_DEVICE_ATTR(_prefix, _name, _mode, _show, _store) \ | ||
134 | struct device_attribute device_attr_fcoe_##_prefix##_##_name = \ | ||
135 | __ATTR(_name, _mode, _show, _store) | ||
136 | |||
137 | #define fcoe_ctlr_show_function(field, format_string, sz, cast) \ | ||
138 | static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \ | ||
139 | struct device_attribute *attr, \ | ||
140 | char *buf) \ | ||
141 | { \ | ||
142 | struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \ | ||
143 | if (ctlr->f->get_fcoe_ctlr_##field) \ | ||
144 | ctlr->f->get_fcoe_ctlr_##field(ctlr); \ | ||
145 | return snprintf(buf, sz, format_string, \ | ||
146 | cast fcoe_ctlr_##field(ctlr)); \ | ||
147 | } | ||
148 | |||
149 | #define fcoe_fcf_show_function(field, format_string, sz, cast) \ | ||
150 | static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \ | ||
151 | struct device_attribute *attr, \ | ||
152 | char *buf) \ | ||
153 | { \ | ||
154 | struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \ | ||
155 | struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); \ | ||
156 | if (ctlr->f->get_fcoe_fcf_##field) \ | ||
157 | ctlr->f->get_fcoe_fcf_##field(fcf); \ | ||
158 | return snprintf(buf, sz, format_string, \ | ||
159 | cast fcoe_fcf_##field(fcf)); \ | ||
160 | } | ||
161 | |||
162 | #define fcoe_ctlr_private_show_function(field, format_string, sz, cast) \ | ||
163 | static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \ | ||
164 | struct device_attribute *attr, \ | ||
165 | char *buf) \ | ||
166 | { \ | ||
167 | struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \ | ||
168 | return snprintf(buf, sz, format_string, cast fcoe_ctlr_##field(ctlr)); \ | ||
169 | } | ||
170 | |||
171 | #define fcoe_fcf_private_show_function(field, format_string, sz, cast) \ | ||
172 | static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \ | ||
173 | struct device_attribute *attr, \ | ||
174 | char *buf) \ | ||
175 | { \ | ||
176 | struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \ | ||
177 | return snprintf(buf, sz, format_string, cast fcoe_fcf_##field(fcf)); \ | ||
178 | } | ||
179 | |||
180 | #define fcoe_ctlr_private_rd_attr(field, format_string, sz) \ | ||
181 | fcoe_ctlr_private_show_function(field, format_string, sz, ) \ | ||
182 | static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ | ||
183 | show_fcoe_ctlr_device_##field, NULL) | ||
184 | |||
185 | #define fcoe_ctlr_rd_attr(field, format_string, sz) \ | ||
186 | fcoe_ctlr_show_function(field, format_string, sz, ) \ | ||
187 | static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ | ||
188 | show_fcoe_ctlr_device_##field, NULL) | ||
189 | |||
190 | #define fcoe_fcf_rd_attr(field, format_string, sz) \ | ||
191 | fcoe_fcf_show_function(field, format_string, sz, ) \ | ||
192 | static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ | ||
193 | show_fcoe_fcf_device_##field, NULL) | ||
194 | |||
195 | #define fcoe_fcf_private_rd_attr(field, format_string, sz) \ | ||
196 | fcoe_fcf_private_show_function(field, format_string, sz, ) \ | ||
197 | static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ | ||
198 | show_fcoe_fcf_device_##field, NULL) | ||
199 | |||
200 | #define fcoe_ctlr_private_rd_attr_cast(field, format_string, sz, cast) \ | ||
201 | fcoe_ctlr_private_show_function(field, format_string, sz, (cast)) \ | ||
202 | static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ | ||
203 | show_fcoe_ctlr_device_##field, NULL) | ||
204 | |||
205 | #define fcoe_fcf_private_rd_attr_cast(field, format_string, sz, cast) \ | ||
206 | fcoe_fcf_private_show_function(field, format_string, sz, (cast)) \ | ||
207 | static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ | ||
208 | show_fcoe_fcf_device_##field, NULL) | ||
209 | |||
210 | #define fcoe_enum_name_search(title, table_type, table) \ | ||
211 | static const char *get_fcoe_##title##_name(enum table_type table_key) \ | ||
212 | { \ | ||
213 | int i; \ | ||
214 | char *name = NULL; \ | ||
215 | \ | ||
216 | for (i = 0; i < ARRAY_SIZE(table); i++) { \ | ||
217 | if (table[i].value == table_key) { \ | ||
218 | name = table[i].name; \ | ||
219 | break; \ | ||
220 | } \ | ||
221 | } \ | ||
222 | return name; \ | ||
223 | } | ||
224 | |||
225 | static struct { | ||
226 | enum fcf_state value; | ||
227 | char *name; | ||
228 | } fcf_state_names[] = { | ||
229 | { FCOE_FCF_STATE_UNKNOWN, "Unknown" }, | ||
230 | { FCOE_FCF_STATE_DISCONNECTED, "Disconnected" }, | ||
231 | { FCOE_FCF_STATE_CONNECTED, "Connected" }, | ||
232 | }; | ||
233 | fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names) | ||
234 | #define FCOE_FCF_STATE_MAX_NAMELEN 50 | ||
235 | |||
236 | static ssize_t show_fcf_state(struct device *dev, | ||
237 | struct device_attribute *attr, | ||
238 | char *buf) | ||
239 | { | ||
240 | struct fcoe_fcf_device *fcf = dev_to_fcf(dev); | ||
241 | const char *name; | ||
242 | name = get_fcoe_fcf_state_name(fcf->state); | ||
243 | if (!name) | ||
244 | return -EINVAL; | ||
245 | return snprintf(buf, FCOE_FCF_STATE_MAX_NAMELEN, "%s\n", name); | ||
246 | } | ||
247 | static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL); | ||
248 | |||
249 | static struct { | ||
250 | enum fip_conn_type value; | ||
251 | char *name; | ||
252 | } fip_conn_type_names[] = { | ||
253 | { FIP_CONN_TYPE_UNKNOWN, "Unknown" }, | ||
254 | { FIP_CONN_TYPE_FABRIC, "Fabric" }, | ||
255 | { FIP_CONN_TYPE_VN2VN, "VN2VN" }, | ||
256 | }; | ||
257 | fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names) | ||
258 | #define FCOE_CTLR_MODE_MAX_NAMELEN 50 | ||
259 | |||
260 | static ssize_t show_ctlr_mode(struct device *dev, | ||
261 | struct device_attribute *attr, | ||
262 | char *buf) | ||
263 | { | ||
264 | struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); | ||
265 | const char *name; | ||
266 | |||
267 | if (ctlr->f->get_fcoe_ctlr_mode) | ||
268 | ctlr->f->get_fcoe_ctlr_mode(ctlr); | ||
269 | |||
270 | name = get_fcoe_ctlr_mode_name(ctlr->mode); | ||
271 | if (!name) | ||
272 | return -EINVAL; | ||
273 | return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN, | ||
274 | "%s\n", name); | ||
275 | } | ||
276 | static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO, | ||
277 | show_ctlr_mode, NULL); | ||
278 | |||
279 | static ssize_t | ||
280 | store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, | ||
281 | struct device_attribute *attr, | ||
282 | const char *buf, size_t count) | ||
283 | { | ||
284 | struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); | ||
285 | struct fcoe_fcf_device *fcf; | ||
286 | unsigned long val; | ||
287 | int rc; | ||
288 | |||
289 | rc = fcoe_str_to_dev_loss(buf, &val); | ||
290 | if (rc) | ||
291 | return rc; | ||
292 | |||
293 | fcoe_ctlr_fcf_dev_loss_tmo(ctlr) = val; | ||
294 | mutex_lock(&ctlr->lock); | ||
295 | list_for_each_entry(fcf, &ctlr->fcfs, peers) | ||
296 | fcoe_fcf_set_dev_loss_tmo(fcf, val); | ||
297 | mutex_unlock(&ctlr->lock); | ||
298 | return count; | ||
299 | } | ||
300 | fcoe_ctlr_private_show_function(fcf_dev_loss_tmo, "%d\n", 20, ); | ||
301 | static FCOE_DEVICE_ATTR(ctlr, fcf_dev_loss_tmo, S_IRUGO | S_IWUSR, | ||
302 | show_fcoe_ctlr_device_fcf_dev_loss_tmo, | ||
303 | store_private_fcoe_ctlr_fcf_dev_loss_tmo); | ||
304 | |||
305 | /* Link Error Status Block (LESB) */ | ||
306 | fcoe_ctlr_rd_attr(link_fail, "%u\n", 20); | ||
307 | fcoe_ctlr_rd_attr(vlink_fail, "%u\n", 20); | ||
308 | fcoe_ctlr_rd_attr(miss_fka, "%u\n", 20); | ||
309 | fcoe_ctlr_rd_attr(symb_err, "%u\n", 20); | ||
310 | fcoe_ctlr_rd_attr(err_block, "%u\n", 20); | ||
311 | fcoe_ctlr_rd_attr(fcs_error, "%u\n", 20); | ||
312 | |||
313 | fcoe_fcf_private_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); | ||
314 | fcoe_fcf_private_rd_attr_cast(switch_name, "0x%llx\n", 20, unsigned long long); | ||
315 | fcoe_fcf_private_rd_attr(priority, "%u\n", 20); | ||
316 | fcoe_fcf_private_rd_attr(fc_map, "0x%x\n", 20); | ||
317 | fcoe_fcf_private_rd_attr(vfid, "%u\n", 20); | ||
318 | fcoe_fcf_private_rd_attr(mac, "%pM\n", 20); | ||
319 | fcoe_fcf_private_rd_attr(fka_period, "%u\n", 20); | ||
320 | fcoe_fcf_rd_attr(selected, "%u\n", 20); | ||
321 | fcoe_fcf_rd_attr(vlan_id, "%u\n", 20); | ||
322 | |||
323 | fcoe_fcf_private_show_function(dev_loss_tmo, "%d\n", 20, ) | ||
324 | static ssize_t | ||
325 | store_fcoe_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr, | ||
326 | const char *buf, size_t count) | ||
327 | { | ||
328 | struct fcoe_fcf_device *fcf = dev_to_fcf(dev); | ||
329 | unsigned long val; | ||
330 | int rc; | ||
331 | |||
332 | rc = fcoe_str_to_dev_loss(buf, &val); | ||
333 | if (rc) | ||
334 | return rc; | ||
335 | |||
336 | rc = fcoe_fcf_set_dev_loss_tmo(fcf, val); | ||
337 | if (rc) | ||
338 | return rc; | ||
339 | return count; | ||
340 | } | ||
341 | static FCOE_DEVICE_ATTR(fcf, dev_loss_tmo, S_IRUGO | S_IWUSR, | ||
342 | show_fcoe_fcf_device_dev_loss_tmo, | ||
343 | store_fcoe_fcf_dev_loss_tmo); | ||
344 | |||
345 | static struct attribute *fcoe_ctlr_lesb_attrs[] = { | ||
346 | &device_attr_fcoe_ctlr_link_fail.attr, | ||
347 | &device_attr_fcoe_ctlr_vlink_fail.attr, | ||
348 | &device_attr_fcoe_ctlr_miss_fka.attr, | ||
349 | &device_attr_fcoe_ctlr_symb_err.attr, | ||
350 | &device_attr_fcoe_ctlr_err_block.attr, | ||
351 | &device_attr_fcoe_ctlr_fcs_error.attr, | ||
352 | NULL, | ||
353 | }; | ||
354 | |||
355 | static struct attribute_group fcoe_ctlr_lesb_attr_group = { | ||
356 | .name = "lesb", | ||
357 | .attrs = fcoe_ctlr_lesb_attrs, | ||
358 | }; | ||
359 | |||
360 | static struct attribute *fcoe_ctlr_attrs[] = { | ||
361 | &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, | ||
362 | &device_attr_fcoe_ctlr_mode.attr, | ||
363 | NULL, | ||
364 | }; | ||
365 | |||
366 | static struct attribute_group fcoe_ctlr_attr_group = { | ||
367 | .attrs = fcoe_ctlr_attrs, | ||
368 | }; | ||
369 | |||
370 | static const struct attribute_group *fcoe_ctlr_attr_groups[] = { | ||
371 | &fcoe_ctlr_attr_group, | ||
372 | &fcoe_ctlr_lesb_attr_group, | ||
373 | NULL, | ||
374 | }; | ||
375 | |||
376 | static struct attribute *fcoe_fcf_attrs[] = { | ||
377 | &device_attr_fcoe_fcf_fabric_name.attr, | ||
378 | &device_attr_fcoe_fcf_switch_name.attr, | ||
379 | &device_attr_fcoe_fcf_dev_loss_tmo.attr, | ||
380 | &device_attr_fcoe_fcf_fc_map.attr, | ||
381 | &device_attr_fcoe_fcf_vfid.attr, | ||
382 | &device_attr_fcoe_fcf_mac.attr, | ||
383 | &device_attr_fcoe_fcf_priority.attr, | ||
384 | &device_attr_fcoe_fcf_fka_period.attr, | ||
385 | &device_attr_fcoe_fcf_state.attr, | ||
386 | &device_attr_fcoe_fcf_selected.attr, | ||
387 | &device_attr_fcoe_fcf_vlan_id.attr, | ||
388 | NULL | ||
389 | }; | ||
390 | |||
391 | static struct attribute_group fcoe_fcf_attr_group = { | ||
392 | .attrs = fcoe_fcf_attrs, | ||
393 | }; | ||
394 | |||
395 | static const struct attribute_group *fcoe_fcf_attr_groups[] = { | ||
396 | &fcoe_fcf_attr_group, | ||
397 | NULL, | ||
398 | }; | ||
399 | |||
400 | struct bus_type fcoe_bus_type; | ||
401 | |||
402 | static int fcoe_bus_match(struct device *dev, | ||
403 | struct device_driver *drv) | ||
404 | { | ||
405 | if (dev->bus == &fcoe_bus_type) | ||
406 | return 1; | ||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | /** | ||
411 | * fcoe_ctlr_device_release() - Release the FIP ctlr memory | ||
412 | * @dev: Pointer to the FIP ctlr's embedded device | ||
413 | * | ||
414 | * Called when the last FIP ctlr reference is released. | ||
415 | */ | ||
416 | static void fcoe_ctlr_device_release(struct device *dev) | ||
417 | { | ||
418 | struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); | ||
419 | kfree(ctlr); | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * fcoe_fcf_device_release() - Release the FIP fcf memory | ||
424 | * @dev: Pointer to the fcf's embedded device | ||
425 | * | ||
426 | * Called when the last FIP fcf reference is released. | ||
427 | */ | ||
428 | static void fcoe_fcf_device_release(struct device *dev) | ||
429 | { | ||
430 | struct fcoe_fcf_device *fcf = dev_to_fcf(dev); | ||
431 | kfree(fcf); | ||
432 | } | ||
433 | |||
434 | struct device_type fcoe_ctlr_device_type = { | ||
435 | .name = "fcoe_ctlr", | ||
436 | .groups = fcoe_ctlr_attr_groups, | ||
437 | .release = fcoe_ctlr_device_release, | ||
438 | }; | ||
439 | |||
440 | struct device_type fcoe_fcf_device_type = { | ||
441 | .name = "fcoe_fcf", | ||
442 | .groups = fcoe_fcf_attr_groups, | ||
443 | .release = fcoe_fcf_device_release, | ||
444 | }; | ||
445 | |||
446 | struct bus_type fcoe_bus_type = { | ||
447 | .name = "fcoe", | ||
448 | .match = &fcoe_bus_match, | ||
449 | }; | ||
450 | |||
451 | /** | ||
452 | * fcoe_ctlr_device_flush_work() - Flush a FIP ctlr's workqueue | ||
453 | * @ctlr: Pointer to the FIP ctlr whose workqueue is to be flushed | ||
454 | */ | ||
455 | void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr) | ||
456 | { | ||
457 | if (!fcoe_ctlr_work_q(ctlr)) { | ||
458 | printk(KERN_ERR | ||
459 | "ERROR: FIP Ctlr '%d' attempted to flush work, " | ||
460 | "when no workqueue created.\n", ctlr->id); | ||
461 | dump_stack(); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | flush_workqueue(fcoe_ctlr_work_q(ctlr)); | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * fcoe_ctlr_device_queue_work() - Schedule work for a FIP ctlr's workqueue | ||
470 | * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue | ||
471 | * @work: Work to queue for execution | ||
472 | * | ||
473 | * Return value: | ||
474 | * 1 on success / 0 already queued / < 0 for error | ||
475 | */ | ||
476 | int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr, | ||
477 | struct work_struct *work) | ||
478 | { | ||
479 | if (unlikely(!fcoe_ctlr_work_q(ctlr))) { | ||
480 | printk(KERN_ERR | ||
481 | "ERROR: FIP Ctlr '%d' attempted to queue work, " | ||
482 | "when no workqueue created.\n", ctlr->id); | ||
483 | dump_stack(); | ||
484 | |||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
488 | return queue_work(fcoe_ctlr_work_q(ctlr), work); | ||
489 | } | ||
490 | |||
491 | /** | ||
492 | * fcoe_ctlr_device_flush_devloss() - Flush a FIP ctlr's devloss workqueue | ||
493 | * @ctlr: Pointer to FIP ctlr whose workqueue is to be flushed | ||
494 | */ | ||
495 | void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr) | ||
496 | { | ||
497 | if (!fcoe_ctlr_devloss_work_q(ctlr)) { | ||
498 | printk(KERN_ERR | ||
499 | "ERROR: FIP Ctlr '%d' attempted to flush work, " | ||
500 | "when no workqueue created.\n", ctlr->id); | ||
501 | dump_stack(); | ||
502 | return; | ||
503 | } | ||
504 | |||
505 | flush_workqueue(fcoe_ctlr_devloss_work_q(ctlr)); | ||
506 | } | ||
507 | |||
508 | /** | ||
509 | * fcoe_ctlr_device_queue_devloss_work() - Schedule work for a FIP ctlr's devloss workqueue | ||
510 | * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue | ||
511 | * @work: Work to queue for execution | ||
512 | * @delay: jiffies to delay the work queuing | ||
513 | * | ||
514 | * Return value: | ||
515 | * 1 on success / 0 already queued / < 0 for error | ||
516 | */ | ||
517 | int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr, | ||
518 | struct delayed_work *work, | ||
519 | unsigned long delay) | ||
520 | { | ||
521 | if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) { | ||
522 | printk(KERN_ERR | ||
523 | "ERROR: FIP Ctlr '%d' attempted to queue work, " | ||
524 | "when no workqueue created.\n", ctlr->id); | ||
525 | dump_stack(); | ||
526 | |||
527 | return -EINVAL; | ||
528 | } | ||
529 | |||
530 | return queue_delayed_work(fcoe_ctlr_devloss_work_q(ctlr), work, delay); | ||
531 | } | ||
532 | |||
533 | static int fcoe_fcf_device_match(struct fcoe_fcf_device *new, | ||
534 | struct fcoe_fcf_device *old) | ||
535 | { | ||
536 | if (new->switch_name == old->switch_name && | ||
537 | new->fabric_name == old->fabric_name && | ||
538 | new->fc_map == old->fc_map && | ||
539 | compare_ether_addr(new->mac, old->mac) == 0) | ||
540 | return 1; | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * fcoe_ctlr_device_add() - Add a FIP ctlr to sysfs | ||
546 | * @parent: The parent device to which the fcoe_ctlr instance | ||
547 | * should be attached | ||
548 | * @f: The LLD's FCoE sysfs function template pointer | ||
549 | * @priv_size: Size to be allocated with the fcoe_ctlr_device for the LLD | ||
550 | * | ||
551 | * This routine allocates a FIP ctlr object with some additional memory | ||
552 | * for the LLD. The FIP ctlr is initialized, added to sysfs and then | ||
553 | * attributes are added to it. | ||
554 | */ | ||
555 | struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent, | ||
556 | struct fcoe_sysfs_function_template *f, | ||
557 | int priv_size) | ||
558 | { | ||
559 | struct fcoe_ctlr_device *ctlr; | ||
560 | int error = 0; | ||
561 | |||
562 | ctlr = kzalloc(sizeof(struct fcoe_ctlr_device) + priv_size, | ||
563 | GFP_KERNEL); | ||
564 | if (!ctlr) | ||
565 | goto out; | ||
566 | |||
567 | ctlr->id = atomic_inc_return(&ctlr_num) - 1; | ||
568 | ctlr->f = f; | ||
569 | INIT_LIST_HEAD(&ctlr->fcfs); | ||
570 | mutex_init(&ctlr->lock); | ||
571 | ctlr->dev.parent = parent; | ||
572 | ctlr->dev.bus = &fcoe_bus_type; | ||
573 | ctlr->dev.type = &fcoe_ctlr_device_type; | ||
574 | |||
575 | ctlr->fcf_dev_loss_tmo = fcoe_fcf_dev_loss_tmo; | ||
576 | |||
577 | snprintf(ctlr->work_q_name, sizeof(ctlr->work_q_name), | ||
578 | "ctlr_wq_%d", ctlr->id); | ||
579 | ctlr->work_q = create_singlethread_workqueue( | ||
580 | ctlr->work_q_name); | ||
581 | if (!ctlr->work_q) | ||
582 | goto out_del; | ||
583 | |||
584 | snprintf(ctlr->devloss_work_q_name, | ||
585 | sizeof(ctlr->devloss_work_q_name), | ||
586 | "ctlr_dl_wq_%d", ctlr->id); | ||
587 | ctlr->devloss_work_q = create_singlethread_workqueue( | ||
588 | ctlr->devloss_work_q_name); | ||
589 | if (!ctlr->devloss_work_q) | ||
590 | goto out_del_q; | ||
591 | |||
592 | dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id); | ||
593 | error = device_register(&ctlr->dev); | ||
594 | if (error) | ||
595 | goto out_del_q2; | ||
596 | |||
597 | return ctlr; | ||
598 | |||
599 | out_del_q2: | ||
600 | destroy_workqueue(ctlr->devloss_work_q); | ||
601 | ctlr->devloss_work_q = NULL; | ||
602 | out_del_q: | ||
603 | destroy_workqueue(ctlr->work_q); | ||
604 | ctlr->work_q = NULL; | ||
605 | out_del: | ||
606 | kfree(ctlr); | ||
607 | out: | ||
608 | return NULL; | ||
609 | } | ||
610 | EXPORT_SYMBOL_GPL(fcoe_ctlr_device_add); | ||
611 | |||
612 | /** | ||
613 | * fcoe_ctlr_device_delete() - Delete a FIP ctlr and its subtree from sysfs | ||
614 | * @ctlr: A pointer to the ctlr to be deleted | ||
615 | * | ||
616 | * Deletes a FIP ctlr and any fcfs attached | ||
617 | * to it. Deleting fcfs will cause their childen | ||
618 | * to be deleted as well. | ||
619 | * | ||
620 | * The ctlr is detached from sysfs and it's resources | ||
621 | * are freed (work q), but the memory is not freed | ||
622 | * until its last reference is released. | ||
623 | * | ||
624 | * This routine expects no locks to be held before | ||
625 | * calling. | ||
626 | * | ||
627 | * TODO: Currently there are no callbacks to clean up LLD data | ||
628 | * for a fcoe_fcf_device. LLDs must keep this in mind as they need | ||
629 | * to clean up each of their LLD data for all fcoe_fcf_device before | ||
630 | * calling fcoe_ctlr_device_delete. | ||
631 | */ | ||
632 | void fcoe_ctlr_device_delete(struct fcoe_ctlr_device *ctlr) | ||
633 | { | ||
634 | struct fcoe_fcf_device *fcf, *next; | ||
635 | /* Remove any attached fcfs */ | ||
636 | mutex_lock(&ctlr->lock); | ||
637 | list_for_each_entry_safe(fcf, next, | ||
638 | &ctlr->fcfs, peers) { | ||
639 | list_del(&fcf->peers); | ||
640 | fcf->state = FCOE_FCF_STATE_DELETED; | ||
641 | fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work); | ||
642 | } | ||
643 | mutex_unlock(&ctlr->lock); | ||
644 | |||
645 | fcoe_ctlr_device_flush_work(ctlr); | ||
646 | |||
647 | destroy_workqueue(ctlr->devloss_work_q); | ||
648 | ctlr->devloss_work_q = NULL; | ||
649 | destroy_workqueue(ctlr->work_q); | ||
650 | ctlr->work_q = NULL; | ||
651 | |||
652 | device_unregister(&ctlr->dev); | ||
653 | } | ||
654 | EXPORT_SYMBOL_GPL(fcoe_ctlr_device_delete); | ||
655 | |||
656 | /** | ||
657 | * fcoe_fcf_device_final_delete() - Final delete routine | ||
658 | * @work: The FIP fcf's embedded work struct | ||
659 | * | ||
660 | * It is expected that the fcf has been removed from | ||
661 | * the FIP ctlr's list before calling this routine. | ||
662 | */ | ||
663 | static void fcoe_fcf_device_final_delete(struct work_struct *work) | ||
664 | { | ||
665 | struct fcoe_fcf_device *fcf = | ||
666 | container_of(work, struct fcoe_fcf_device, delete_work); | ||
667 | struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); | ||
668 | |||
669 | /* | ||
670 | * Cancel any outstanding timers. These should really exist | ||
671 | * only when rmmod'ing the LLDD and we're asking for | ||
672 | * immediate termination of the rports | ||
673 | */ | ||
674 | if (!cancel_delayed_work(&fcf->dev_loss_work)) | ||
675 | fcoe_ctlr_device_flush_devloss(ctlr); | ||
676 | |||
677 | device_unregister(&fcf->dev); | ||
678 | } | ||
679 | |||
680 | /** | ||
681 | * fip_timeout_deleted_fcf() - Delete a fcf when the devloss timer fires | ||
682 | * @work: The FIP fcf's embedded work struct | ||
683 | * | ||
684 | * Removes the fcf from the FIP ctlr's list of fcfs and | ||
685 | * queues the final deletion. | ||
686 | */ | ||
687 | static void fip_timeout_deleted_fcf(struct work_struct *work) | ||
688 | { | ||
689 | struct fcoe_fcf_device *fcf = | ||
690 | container_of(work, struct fcoe_fcf_device, dev_loss_work.work); | ||
691 | struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); | ||
692 | |||
693 | mutex_lock(&ctlr->lock); | ||
694 | |||
695 | /* | ||
696 | * If the fcf is deleted or reconnected before the timer | ||
697 | * fires the devloss queue will be flushed, but the state will | ||
698 | * either be CONNECTED or DELETED. If that is the case we | ||
699 | * cancel deleting the fcf. | ||
700 | */ | ||
701 | if (fcf->state != FCOE_FCF_STATE_DISCONNECTED) | ||
702 | goto out; | ||
703 | |||
704 | dev_printk(KERN_ERR, &fcf->dev, | ||
705 | "FIP fcf connection time out: removing fcf\n"); | ||
706 | |||
707 | list_del(&fcf->peers); | ||
708 | fcf->state = FCOE_FCF_STATE_DELETED; | ||
709 | fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work); | ||
710 | |||
711 | out: | ||
712 | mutex_unlock(&ctlr->lock); | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * fcoe_fcf_device_delete() - Delete a FIP fcf | ||
717 | * @fcf: Pointer to the fcf which is to be deleted | ||
718 | * | ||
719 | * Queues the FIP fcf on the devloss workqueue | ||
720 | * | ||
721 | * Expects the ctlr_attrs mutex to be held for fcf | ||
722 | * state change. | ||
723 | */ | ||
724 | void fcoe_fcf_device_delete(struct fcoe_fcf_device *fcf) | ||
725 | { | ||
726 | struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); | ||
727 | int timeout = fcf->dev_loss_tmo; | ||
728 | |||
729 | if (fcf->state != FCOE_FCF_STATE_CONNECTED) | ||
730 | return; | ||
731 | |||
732 | fcf->state = FCOE_FCF_STATE_DISCONNECTED; | ||
733 | |||
734 | /* | ||
735 | * FCF will only be re-connected by the LLD calling | ||
736 | * fcoe_fcf_device_add, and it should be setting up | ||
737 | * priv then. | ||
738 | */ | ||
739 | fcf->priv = NULL; | ||
740 | |||
741 | fcoe_ctlr_device_queue_devloss_work(ctlr, &fcf->dev_loss_work, | ||
742 | timeout * HZ); | ||
743 | } | ||
744 | EXPORT_SYMBOL_GPL(fcoe_fcf_device_delete); | ||
745 | |||
746 | /** | ||
747 | * fcoe_fcf_device_add() - Add a FCoE sysfs fcoe_fcf_device to the system | ||
748 | * @ctlr: The fcoe_ctlr_device that will be the fcoe_fcf_device parent | ||
749 | * @new_fcf: A temporary FCF used for lookups on the current list of fcfs | ||
750 | * | ||
751 | * Expects to be called with the ctlr->lock held | ||
752 | */ | ||
753 | struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr, | ||
754 | struct fcoe_fcf_device *new_fcf) | ||
755 | { | ||
756 | struct fcoe_fcf_device *fcf; | ||
757 | int error = 0; | ||
758 | |||
759 | list_for_each_entry(fcf, &ctlr->fcfs, peers) { | ||
760 | if (fcoe_fcf_device_match(new_fcf, fcf)) { | ||
761 | if (fcf->state == FCOE_FCF_STATE_CONNECTED) | ||
762 | return fcf; | ||
763 | |||
764 | fcf->state = FCOE_FCF_STATE_CONNECTED; | ||
765 | |||
766 | if (!cancel_delayed_work(&fcf->dev_loss_work)) | ||
767 | fcoe_ctlr_device_flush_devloss(ctlr); | ||
768 | |||
769 | return fcf; | ||
770 | } | ||
771 | } | ||
772 | |||
773 | fcf = kzalloc(sizeof(struct fcoe_fcf_device), GFP_ATOMIC); | ||
774 | if (unlikely(!fcf)) | ||
775 | goto out; | ||
776 | |||
777 | INIT_WORK(&fcf->delete_work, fcoe_fcf_device_final_delete); | ||
778 | INIT_DELAYED_WORK(&fcf->dev_loss_work, fip_timeout_deleted_fcf); | ||
779 | |||
780 | fcf->dev.parent = &ctlr->dev; | ||
781 | fcf->dev.bus = &fcoe_bus_type; | ||
782 | fcf->dev.type = &fcoe_fcf_device_type; | ||
783 | fcf->id = atomic_inc_return(&fcf_num) - 1; | ||
784 | fcf->state = FCOE_FCF_STATE_UNKNOWN; | ||
785 | |||
786 | fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo; | ||
787 | |||
788 | dev_set_name(&fcf->dev, "fcf_%d", fcf->id); | ||
789 | |||
790 | fcf->fabric_name = new_fcf->fabric_name; | ||
791 | fcf->switch_name = new_fcf->switch_name; | ||
792 | fcf->fc_map = new_fcf->fc_map; | ||
793 | fcf->vfid = new_fcf->vfid; | ||
794 | memcpy(fcf->mac, new_fcf->mac, ETH_ALEN); | ||
795 | fcf->priority = new_fcf->priority; | ||
796 | fcf->fka_period = new_fcf->fka_period; | ||
797 | fcf->selected = new_fcf->selected; | ||
798 | |||
799 | error = device_register(&fcf->dev); | ||
800 | if (error) | ||
801 | goto out_del; | ||
802 | |||
803 | fcf->state = FCOE_FCF_STATE_CONNECTED; | ||
804 | list_add_tail(&fcf->peers, &ctlr->fcfs); | ||
805 | |||
806 | return fcf; | ||
807 | |||
808 | out_del: | ||
809 | kfree(fcf); | ||
810 | out: | ||
811 | return NULL; | ||
812 | } | ||
813 | EXPORT_SYMBOL_GPL(fcoe_fcf_device_add); | ||
814 | |||
815 | int __init fcoe_sysfs_setup(void) | ||
816 | { | ||
817 | int error; | ||
818 | |||
819 | atomic_set(&ctlr_num, 0); | ||
820 | atomic_set(&fcf_num, 0); | ||
821 | |||
822 | error = bus_register(&fcoe_bus_type); | ||
823 | if (error) | ||
824 | return error; | ||
825 | |||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | void __exit fcoe_sysfs_teardown(void) | ||
830 | { | ||
831 | bus_unregister(&fcoe_bus_type); | ||
832 | } | ||
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index 710e149d41b6..b46f43dced78 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c | |||
@@ -815,9 +815,17 @@ out_nodev: | |||
815 | */ | 815 | */ |
816 | static int __init libfcoe_init(void) | 816 | static int __init libfcoe_init(void) |
817 | { | 817 | { |
818 | fcoe_transport_init(); | 818 | int rc = 0; |
819 | 819 | ||
820 | return 0; | 820 | rc = fcoe_transport_init(); |
821 | if (rc) | ||
822 | return rc; | ||
823 | |||
824 | rc = fcoe_sysfs_setup(); | ||
825 | if (rc) | ||
826 | fcoe_transport_exit(); | ||
827 | |||
828 | return rc; | ||
821 | } | 829 | } |
822 | module_init(libfcoe_init); | 830 | module_init(libfcoe_init); |
823 | 831 | ||
@@ -826,6 +834,7 @@ module_init(libfcoe_init); | |||
826 | */ | 834 | */ |
827 | static void __exit libfcoe_exit(void) | 835 | static void __exit libfcoe_exit(void) |
828 | { | 836 | { |
837 | fcoe_sysfs_teardown(); | ||
829 | fcoe_transport_exit(); | 838 | fcoe_transport_exit(); |
830 | } | 839 | } |
831 | module_exit(libfcoe_exit); | 840 | module_exit(libfcoe_exit); |
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 6208d562890d..317a7fdc3b82 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig | |||
@@ -25,3 +25,12 @@ config SCSI_QLA_FC | |||
25 | Firmware images can be retrieved from: | 25 | Firmware images can be retrieved from: |
26 | 26 | ||
27 | ftp://ftp.qlogic.com/outgoing/linux/firmware/ | 27 | ftp://ftp.qlogic.com/outgoing/linux/firmware/ |
28 | |||
29 | config TCM_QLA2XXX | ||
30 | tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" | ||
31 | depends on SCSI_QLA_FC && TARGET_CORE | ||
32 | select LIBFC | ||
33 | select BTREE | ||
34 | default n | ||
35 | ---help--- | ||
36 | Say Y here to enable the TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs | ||
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 5df782f4a097..dce7d788cdc9 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ | 1 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ |
2 | qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \ | 2 | qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \ |
3 | qla_nx.o | 3 | qla_nx.o qla_target.o |
4 | 4 | ||
5 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o | 5 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o |
6 | obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o | ||
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 5926f5a87ea8..5ab953029f8d 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_target.h" | ||
8 | 9 | ||
9 | #include <linux/kthread.h> | 10 | #include <linux/kthread.h> |
10 | #include <linux/vmalloc.h> | 11 | #include <linux/vmalloc.h> |
@@ -576,6 +577,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, | |||
576 | scsi_block_requests(vha->host); | 577 | scsi_block_requests(vha->host); |
577 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 578 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
578 | if (IS_QLA82XX(ha)) { | 579 | if (IS_QLA82XX(ha)) { |
580 | ha->flags.isp82xx_no_md_cap = 1; | ||
579 | qla82xx_idc_lock(ha); | 581 | qla82xx_idc_lock(ha); |
580 | qla82xx_set_reset_owner(vha); | 582 | qla82xx_set_reset_owner(vha); |
581 | qla82xx_idc_unlock(ha); | 583 | qla82xx_idc_unlock(ha); |
@@ -585,7 +587,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, | |||
585 | scsi_unblock_requests(vha->host); | 587 | scsi_unblock_requests(vha->host); |
586 | break; | 588 | break; |
587 | case 0x2025d: | 589 | case 0x2025d: |
588 | if (!IS_QLA81XX(ha)) | 590 | if (!IS_QLA81XX(ha) || !IS_QLA8031(ha)) |
589 | return -EPERM; | 591 | return -EPERM; |
590 | 592 | ||
591 | ql_log(ql_log_info, vha, 0x706f, | 593 | ql_log(ql_log_info, vha, 0x706f, |
@@ -1105,9 +1107,8 @@ qla2x00_total_isp_aborts_show(struct device *dev, | |||
1105 | struct device_attribute *attr, char *buf) | 1107 | struct device_attribute *attr, char *buf) |
1106 | { | 1108 | { |
1107 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | 1109 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); |
1108 | struct qla_hw_data *ha = vha->hw; | ||
1109 | return snprintf(buf, PAGE_SIZE, "%d\n", | 1110 | return snprintf(buf, PAGE_SIZE, "%d\n", |
1110 | ha->qla_stats.total_isp_aborts); | 1111 | vha->qla_stats.total_isp_aborts); |
1111 | } | 1112 | } |
1112 | 1113 | ||
1113 | static ssize_t | 1114 | static ssize_t |
@@ -1154,7 +1155,7 @@ qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr, | |||
1154 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | 1155 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); |
1155 | struct qla_hw_data *ha = vha->hw; | 1156 | struct qla_hw_data *ha = vha->hw; |
1156 | 1157 | ||
1157 | if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) | 1158 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) |
1158 | return snprintf(buf, PAGE_SIZE, "\n"); | 1159 | return snprintf(buf, PAGE_SIZE, "\n"); |
1159 | 1160 | ||
1160 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", | 1161 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", |
@@ -1537,7 +1538,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
1537 | dma_addr_t stats_dma; | 1538 | dma_addr_t stats_dma; |
1538 | struct fc_host_statistics *pfc_host_stat; | 1539 | struct fc_host_statistics *pfc_host_stat; |
1539 | 1540 | ||
1540 | pfc_host_stat = &ha->fc_host_stat; | 1541 | pfc_host_stat = &vha->fc_host_stat; |
1541 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); | 1542 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); |
1542 | 1543 | ||
1543 | if (test_bit(UNLOADING, &vha->dpc_flags)) | 1544 | if (test_bit(UNLOADING, &vha->dpc_flags)) |
@@ -1580,8 +1581,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
1580 | pfc_host_stat->dumped_frames = stats->dumped_frames; | 1581 | pfc_host_stat->dumped_frames = stats->dumped_frames; |
1581 | pfc_host_stat->nos_count = stats->nos_rcvd; | 1582 | pfc_host_stat->nos_count = stats->nos_rcvd; |
1582 | } | 1583 | } |
1583 | pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20; | 1584 | pfc_host_stat->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; |
1584 | pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20; | 1585 | pfc_host_stat->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; |
1585 | 1586 | ||
1586 | done_free: | 1587 | done_free: |
1587 | dma_pool_free(ha->s_dma_pool, stats, stats_dma); | 1588 | dma_pool_free(ha->s_dma_pool, stats, stats_dma); |
@@ -1737,6 +1738,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1737 | fc_host_supported_speeds(vha->host) = | 1738 | fc_host_supported_speeds(vha->host) = |
1738 | fc_host_supported_speeds(base_vha->host); | 1739 | fc_host_supported_speeds(base_vha->host); |
1739 | 1740 | ||
1741 | qlt_vport_create(vha, ha); | ||
1740 | qla24xx_vport_disable(fc_vport, disable); | 1742 | qla24xx_vport_disable(fc_vport, disable); |
1741 | 1743 | ||
1742 | if (ha->flags.cpu_affinity_enabled) { | 1744 | if (ha->flags.cpu_affinity_enabled) { |
@@ -1951,12 +1953,16 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) | |||
1951 | fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; | 1953 | fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; |
1952 | fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); | 1954 | fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); |
1953 | fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); | 1955 | fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); |
1954 | fc_host_supported_classes(vha->host) = FC_COS_CLASS3; | 1956 | fc_host_supported_classes(vha->host) = ha->tgt.enable_class_2 ? |
1957 | (FC_COS_CLASS2|FC_COS_CLASS3) : FC_COS_CLASS3; | ||
1955 | fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; | 1958 | fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; |
1956 | fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; | 1959 | fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; |
1957 | 1960 | ||
1958 | if (IS_CNA_CAPABLE(ha)) | 1961 | if (IS_CNA_CAPABLE(ha)) |
1959 | speed = FC_PORTSPEED_10GBIT; | 1962 | speed = FC_PORTSPEED_10GBIT; |
1963 | else if (IS_QLA2031(ha)) | ||
1964 | speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT | | ||
1965 | FC_PORTSPEED_4GBIT; | ||
1960 | else if (IS_QLA25XX(ha)) | 1966 | else if (IS_QLA25XX(ha)) |
1961 | speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | | 1967 | speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | |
1962 | FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; | 1968 | FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; |
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index bc3cc6d91117..c68883806c54 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c | |||
@@ -297,7 +297,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) | |||
297 | 297 | ||
298 | /* Initialize all required fields of fcport */ | 298 | /* Initialize all required fields of fcport */ |
299 | fcport->vha = vha; | 299 | fcport->vha = vha; |
300 | fcport->vp_idx = vha->vp_idx; | ||
301 | fcport->d_id.b.al_pa = | 300 | fcport->d_id.b.al_pa = |
302 | bsg_job->request->rqst_data.h_els.port_id[0]; | 301 | bsg_job->request->rqst_data.h_els.port_id[0]; |
303 | fcport->d_id.b.area = | 302 | fcport->d_id.b.area = |
@@ -483,7 +482,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) | |||
483 | 482 | ||
484 | /* Initialize all required fields of fcport */ | 483 | /* Initialize all required fields of fcport */ |
485 | fcport->vha = vha; | 484 | fcport->vha = vha; |
486 | fcport->vp_idx = vha->vp_idx; | ||
487 | fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; | 485 | fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; |
488 | fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; | 486 | fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; |
489 | fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; | 487 | fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; |
@@ -544,7 +542,7 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, | |||
544 | int rval = 0; | 542 | int rval = 0; |
545 | struct qla_hw_data *ha = vha->hw; | 543 | struct qla_hw_data *ha = vha->hw; |
546 | 544 | ||
547 | if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) | 545 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) |
548 | goto done_set_internal; | 546 | goto done_set_internal; |
549 | 547 | ||
550 | new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1); | 548 | new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1); |
@@ -586,7 +584,7 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, | |||
586 | uint16_t new_config[4]; | 584 | uint16_t new_config[4]; |
587 | struct qla_hw_data *ha = vha->hw; | 585 | struct qla_hw_data *ha = vha->hw; |
588 | 586 | ||
589 | if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) | 587 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) |
590 | goto done_reset_internal; | 588 | goto done_reset_internal; |
591 | 589 | ||
592 | memset(new_config, 0 , sizeof(new_config)); | 590 | memset(new_config, 0 , sizeof(new_config)); |
@@ -710,8 +708,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) | |||
710 | elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | 708 | elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; |
711 | 709 | ||
712 | if ((ha->current_topology == ISP_CFG_F || | 710 | if ((ha->current_topology == ISP_CFG_F || |
713 | (atomic_read(&vha->loop_state) == LOOP_DOWN) || | 711 | ((IS_QLA81XX(ha) || IS_QLA8031(ha)) && |
714 | ((IS_QLA81XX(ha) || IS_QLA83XX(ha)) && | ||
715 | le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE | 712 | le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE |
716 | && req_data_len == MAX_ELS_FRAME_PAYLOAD)) && | 713 | && req_data_len == MAX_ELS_FRAME_PAYLOAD)) && |
717 | elreq.options == EXTERNAL_LOOPBACK) { | 714 | elreq.options == EXTERNAL_LOOPBACK) { |
@@ -1402,6 +1399,9 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job) | |||
1402 | if (rval) | 1399 | if (rval) |
1403 | return rval; | 1400 | return rval; |
1404 | 1401 | ||
1402 | /* Set the isp82xx_no_md_cap not to capture minidump */ | ||
1403 | ha->flags.isp82xx_no_md_cap = 1; | ||
1404 | |||
1405 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | 1405 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, |
1406 | bsg_job->request_payload.sg_cnt, ha->optrom_buffer, | 1406 | bsg_job->request_payload.sg_cnt, ha->optrom_buffer, |
1407 | ha->optrom_region_size); | 1407 | ha->optrom_region_size); |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 62324a1d5573..fdee5611f3e2 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -11,27 +11,31 @@ | |||
11 | * ---------------------------------------------------------------------- | 11 | * ---------------------------------------------------------------------- |
12 | * | Level | Last Value Used | Holes | | 12 | * | Level | Last Value Used | Holes | |
13 | * ---------------------------------------------------------------------- | 13 | * ---------------------------------------------------------------------- |
14 | * | Module Init and Probe | 0x0120 | 0x4b,0xba,0xfa | | 14 | * | Module Init and Probe | 0x0122 | 0x4b,0xba,0xfa | |
15 | * | Mailbox commands | 0x113e | 0x112c-0x112e | | 15 | * | Mailbox commands | 0x1140 | 0x111a-0x111b | |
16 | * | | | 0x112c-0x112e | | ||
16 | * | | | 0x113a | | 17 | * | | | 0x113a | |
17 | * | Device Discovery | 0x2086 | 0x2020-0x2022 | | 18 | * | Device Discovery | 0x2086 | 0x2020-0x2022 | |
18 | * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | | 19 | * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | |
19 | * | | | 0x302d-0x302e | | 20 | * | | | 0x302d-0x302e | |
20 | * | DPC Thread | 0x401c | | | 21 | * | DPC Thread | 0x401c | 0x4002,0x4013 | |
21 | * | Async Events | 0x505d | 0x502b-0x502f | | 22 | * | Async Events | 0x505f | 0x502b-0x502f | |
22 | * | | | 0x5047,0x5052 | | 23 | * | | | 0x5047,0x5052 | |
23 | * | Timer Routines | 0x6011 | 0x600e-0x600f | | 24 | * | Timer Routines | 0x6011 | | |
24 | * | User Space Interactions | 0x709f | 0x7018,0x702e, | | 25 | * | User Space Interactions | 0x709f | 0x7018,0x702e, | |
25 | * | | | 0x7039,0x7045, | | 26 | * | | | 0x7039,0x7045, | |
26 | * | | | 0x7073-0x7075, | | 27 | * | | | 0x7073-0x7075, | |
27 | * | | | 0x708c | | 28 | * | | | 0x708c | |
28 | * | Task Management | 0x803c | 0x8025-0x8026 | | 29 | * | Task Management | 0x803c | 0x8025-0x8026 | |
29 | * | | | 0x800b,0x8039 | | 30 | * | | | 0x800b,0x8039 | |
30 | * | AER/EEH | 0x900f | | | 31 | * | AER/EEH | 0x9011 | | |
31 | * | Virtual Port | 0xa007 | | | 32 | * | Virtual Port | 0xa007 | | |
32 | * | ISP82XX Specific | 0xb054 | 0xb053 | | 33 | * | ISP82XX Specific | 0xb054 | 0xb024 | |
33 | * | MultiQ | 0xc00c | | | 34 | * | MultiQ | 0xc00c | | |
34 | * | Misc | 0xd010 | | | 35 | * | Misc | 0xd010 | | |
36 | * | Target Mode | 0xe06f | | | ||
37 | * | Target Mode Management | 0xf071 | | | ||
38 | * | Target Mode Task Management | 0x1000b | | | ||
35 | * ---------------------------------------------------------------------- | 39 | * ---------------------------------------------------------------------- |
36 | */ | 40 | */ |
37 | 41 | ||
@@ -379,6 +383,54 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) | |||
379 | } | 383 | } |
380 | 384 | ||
381 | static inline void * | 385 | static inline void * |
386 | qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr, | ||
387 | uint32_t **last_chain) | ||
388 | { | ||
389 | struct qla2xxx_mqueue_chain *q; | ||
390 | struct qla2xxx_mqueue_header *qh; | ||
391 | uint32_t num_queues; | ||
392 | int que; | ||
393 | struct { | ||
394 | int length; | ||
395 | void *ring; | ||
396 | } aq, *aqp; | ||
397 | |||
398 | if (!ha->tgt.atio_q_length) | ||
399 | return ptr; | ||
400 | |||
401 | num_queues = 1; | ||
402 | aqp = &aq; | ||
403 | aqp->length = ha->tgt.atio_q_length; | ||
404 | aqp->ring = ha->tgt.atio_ring; | ||
405 | |||
406 | for (que = 0; que < num_queues; que++) { | ||
407 | /* aqp = ha->atio_q_map[que]; */ | ||
408 | q = ptr; | ||
409 | *last_chain = &q->type; | ||
410 | q->type = __constant_htonl(DUMP_CHAIN_QUEUE); | ||
411 | q->chain_size = htonl( | ||
412 | sizeof(struct qla2xxx_mqueue_chain) + | ||
413 | sizeof(struct qla2xxx_mqueue_header) + | ||
414 | (aqp->length * sizeof(request_t))); | ||
415 | ptr += sizeof(struct qla2xxx_mqueue_chain); | ||
416 | |||
417 | /* Add header. */ | ||
418 | qh = ptr; | ||
419 | qh->queue = __constant_htonl(TYPE_ATIO_QUEUE); | ||
420 | qh->number = htonl(que); | ||
421 | qh->size = htonl(aqp->length * sizeof(request_t)); | ||
422 | ptr += sizeof(struct qla2xxx_mqueue_header); | ||
423 | |||
424 | /* Add data. */ | ||
425 | memcpy(ptr, aqp->ring, aqp->length * sizeof(request_t)); | ||
426 | |||
427 | ptr += aqp->length * sizeof(request_t); | ||
428 | } | ||
429 | |||
430 | return ptr; | ||
431 | } | ||
432 | |||
433 | static inline void * | ||
382 | qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) | 434 | qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) |
383 | { | 435 | { |
384 | struct qla2xxx_mqueue_chain *q; | 436 | struct qla2xxx_mqueue_chain *q; |
@@ -873,6 +925,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
873 | struct qla24xx_fw_dump *fw; | 925 | struct qla24xx_fw_dump *fw; |
874 | uint32_t ext_mem_cnt; | 926 | uint32_t ext_mem_cnt; |
875 | void *nxt; | 927 | void *nxt; |
928 | void *nxt_chain; | ||
929 | uint32_t *last_chain = NULL; | ||
876 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 930 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
877 | 931 | ||
878 | if (IS_QLA82XX(ha)) | 932 | if (IS_QLA82XX(ha)) |
@@ -1091,6 +1145,16 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1091 | 1145 | ||
1092 | qla24xx_copy_eft(ha, nxt); | 1146 | qla24xx_copy_eft(ha, nxt); |
1093 | 1147 | ||
1148 | nxt_chain = (void *)ha->fw_dump + ha->chain_offset; | ||
1149 | nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); | ||
1150 | if (last_chain) { | ||
1151 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); | ||
1152 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); | ||
1153 | } | ||
1154 | |||
1155 | /* Adjust valid length. */ | ||
1156 | ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump); | ||
1157 | |||
1094 | qla24xx_fw_dump_failed_0: | 1158 | qla24xx_fw_dump_failed_0: |
1095 | qla2xxx_dump_post_process(base_vha, rval); | 1159 | qla2xxx_dump_post_process(base_vha, rval); |
1096 | 1160 | ||
@@ -1399,6 +1463,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1399 | /* Chain entries -- started with MQ. */ | 1463 | /* Chain entries -- started with MQ. */ |
1400 | nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); | 1464 | nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); |
1401 | nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); | 1465 | nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); |
1466 | nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); | ||
1402 | if (last_chain) { | 1467 | if (last_chain) { |
1403 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); | 1468 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); |
1404 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); | 1469 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); |
@@ -1717,6 +1782,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1717 | /* Chain entries -- started with MQ. */ | 1782 | /* Chain entries -- started with MQ. */ |
1718 | nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); | 1783 | nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); |
1719 | nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); | 1784 | nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); |
1785 | nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); | ||
1720 | if (last_chain) { | 1786 | if (last_chain) { |
1721 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); | 1787 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); |
1722 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); | 1788 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); |
@@ -2218,6 +2284,7 @@ copy_queue: | |||
2218 | /* Chain entries -- started with MQ. */ | 2284 | /* Chain entries -- started with MQ. */ |
2219 | nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); | 2285 | nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); |
2220 | nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); | 2286 | nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); |
2287 | nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); | ||
2221 | if (last_chain) { | 2288 | if (last_chain) { |
2222 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); | 2289 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); |
2223 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); | 2290 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 2157bdf1569a..f278df8cce0f 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -244,6 +244,7 @@ struct qla2xxx_mqueue_header { | |||
244 | uint32_t queue; | 244 | uint32_t queue; |
245 | #define TYPE_REQUEST_QUEUE 0x1 | 245 | #define TYPE_REQUEST_QUEUE 0x1 |
246 | #define TYPE_RESPONSE_QUEUE 0x2 | 246 | #define TYPE_RESPONSE_QUEUE 0x2 |
247 | #define TYPE_ATIO_QUEUE 0x3 | ||
247 | uint32_t number; | 248 | uint32_t number; |
248 | uint32_t size; | 249 | uint32_t size; |
249 | }; | 250 | }; |
@@ -339,3 +340,11 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); | |||
339 | #define ql_dbg_misc 0x00010000 /* For dumping everything that is not | 340 | #define ql_dbg_misc 0x00010000 /* For dumping everything that is not |
340 | * not covered by upper categories | 341 | * not covered by upper categories |
341 | */ | 342 | */ |
343 | #define ql_dbg_verbose 0x00008000 /* More verbosity for each level | ||
344 | * This is to be used with other levels where | ||
345 | * more verbosity is required. It might not | ||
346 | * be applicable to all the levels. | ||
347 | */ | ||
348 | #define ql_dbg_tgt 0x00004000 /* Target mode */ | ||
349 | #define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */ | ||
350 | #define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */ | ||
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a2443031dbe7..39007f53aec0 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -186,6 +186,7 @@ | |||
186 | #define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/ | 186 | #define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/ |
187 | #define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/ | 187 | #define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/ |
188 | #define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/ | 188 | #define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/ |
189 | #define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */ | ||
189 | 190 | ||
190 | struct req_que; | 191 | struct req_que; |
191 | 192 | ||
@@ -1234,11 +1235,27 @@ typedef struct { | |||
1234 | * ISP queue - response queue entry definition. | 1235 | * ISP queue - response queue entry definition. |
1235 | */ | 1236 | */ |
1236 | typedef struct { | 1237 | typedef struct { |
1237 | uint8_t data[60]; | 1238 | uint8_t entry_type; /* Entry type. */ |
1239 | uint8_t entry_count; /* Entry count. */ | ||
1240 | uint8_t sys_define; /* System defined. */ | ||
1241 | uint8_t entry_status; /* Entry Status. */ | ||
1242 | uint32_t handle; /* System defined handle */ | ||
1243 | uint8_t data[52]; | ||
1238 | uint32_t signature; | 1244 | uint32_t signature; |
1239 | #define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */ | 1245 | #define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */ |
1240 | } response_t; | 1246 | } response_t; |
1241 | 1247 | ||
1248 | /* | ||
1249 | * ISP queue - ATIO queue entry definition. | ||
1250 | */ | ||
1251 | struct atio { | ||
1252 | uint8_t entry_type; /* Entry type. */ | ||
1253 | uint8_t entry_count; /* Entry count. */ | ||
1254 | uint8_t data[58]; | ||
1255 | uint32_t signature; | ||
1256 | #define ATIO_PROCESSED 0xDEADDEAD /* Signature */ | ||
1257 | }; | ||
1258 | |||
1242 | typedef union { | 1259 | typedef union { |
1243 | uint16_t extended; | 1260 | uint16_t extended; |
1244 | struct { | 1261 | struct { |
@@ -1719,11 +1736,13 @@ typedef struct fc_port { | |||
1719 | struct fc_rport *rport, *drport; | 1736 | struct fc_rport *rport, *drport; |
1720 | u32 supported_classes; | 1737 | u32 supported_classes; |
1721 | 1738 | ||
1722 | uint16_t vp_idx; | ||
1723 | uint8_t fc4_type; | 1739 | uint8_t fc4_type; |
1724 | uint8_t scan_state; | 1740 | uint8_t scan_state; |
1725 | } fc_port_t; | 1741 | } fc_port_t; |
1726 | 1742 | ||
1743 | #define QLA_FCPORT_SCAN_NONE 0 | ||
1744 | #define QLA_FCPORT_SCAN_FOUND 1 | ||
1745 | |||
1727 | /* | 1746 | /* |
1728 | * Fibre channel port/lun states. | 1747 | * Fibre channel port/lun states. |
1729 | */ | 1748 | */ |
@@ -1747,6 +1766,7 @@ static const char * const port_state_str[] = { | |||
1747 | #define FCF_LOGIN_NEEDED BIT_1 | 1766 | #define FCF_LOGIN_NEEDED BIT_1 |
1748 | #define FCF_FCP2_DEVICE BIT_2 | 1767 | #define FCF_FCP2_DEVICE BIT_2 |
1749 | #define FCF_ASYNC_SENT BIT_3 | 1768 | #define FCF_ASYNC_SENT BIT_3 |
1769 | #define FCF_CONF_COMP_SUPPORTED BIT_4 | ||
1750 | 1770 | ||
1751 | /* No loop ID flag. */ | 1771 | /* No loop ID flag. */ |
1752 | #define FC_NO_LOOP_ID 0x1000 | 1772 | #define FC_NO_LOOP_ID 0x1000 |
@@ -2419,6 +2439,40 @@ struct qlfc_fw { | |||
2419 | uint32_t len; | 2439 | uint32_t len; |
2420 | }; | 2440 | }; |
2421 | 2441 | ||
2442 | struct qlt_hw_data { | ||
2443 | /* Protected by hw lock */ | ||
2444 | uint32_t enable_class_2:1; | ||
2445 | uint32_t enable_explicit_conf:1; | ||
2446 | uint32_t ini_mode_force_reverse:1; | ||
2447 | uint32_t node_name_set:1; | ||
2448 | |||
2449 | dma_addr_t atio_dma; /* Physical address. */ | ||
2450 | struct atio *atio_ring; /* Base virtual address */ | ||
2451 | struct atio *atio_ring_ptr; /* Current address. */ | ||
2452 | uint16_t atio_ring_index; /* Current index. */ | ||
2453 | uint16_t atio_q_length; | ||
2454 | |||
2455 | void *target_lport_ptr; | ||
2456 | struct qla_tgt_func_tmpl *tgt_ops; | ||
2457 | struct qla_tgt *qla_tgt; | ||
2458 | struct qla_tgt_cmd *cmds[MAX_OUTSTANDING_COMMANDS]; | ||
2459 | uint16_t current_handle; | ||
2460 | |||
2461 | struct qla_tgt_vp_map *tgt_vp_map; | ||
2462 | struct mutex tgt_mutex; | ||
2463 | struct mutex tgt_host_action_mutex; | ||
2464 | |||
2465 | int saved_set; | ||
2466 | uint16_t saved_exchange_count; | ||
2467 | uint32_t saved_firmware_options_1; | ||
2468 | uint32_t saved_firmware_options_2; | ||
2469 | uint32_t saved_firmware_options_3; | ||
2470 | uint8_t saved_firmware_options[2]; | ||
2471 | uint8_t saved_add_firmware_options[2]; | ||
2472 | |||
2473 | uint8_t tgt_node_name[WWN_SIZE]; | ||
2474 | }; | ||
2475 | |||
2422 | /* | 2476 | /* |
2423 | * Qlogic host adapter specific data structure. | 2477 | * Qlogic host adapter specific data structure. |
2424 | */ | 2478 | */ |
@@ -2460,7 +2514,9 @@ struct qla_hw_data { | |||
2460 | uint32_t thermal_supported:1; | 2514 | uint32_t thermal_supported:1; |
2461 | uint32_t isp82xx_reset_hdlr_active:1; | 2515 | uint32_t isp82xx_reset_hdlr_active:1; |
2462 | uint32_t isp82xx_reset_owner:1; | 2516 | uint32_t isp82xx_reset_owner:1; |
2463 | /* 28 bits */ | 2517 | uint32_t isp82xx_no_md_cap:1; |
2518 | uint32_t host_shutting_down:1; | ||
2519 | /* 30 bits */ | ||
2464 | } flags; | 2520 | } flags; |
2465 | 2521 | ||
2466 | /* This spinlock is used to protect "io transactions", you must | 2522 | /* This spinlock is used to protect "io transactions", you must |
@@ -2804,7 +2860,6 @@ struct qla_hw_data { | |||
2804 | /* ISP2322: red, green, amber. */ | 2860 | /* ISP2322: red, green, amber. */ |
2805 | uint16_t zio_mode; | 2861 | uint16_t zio_mode; |
2806 | uint16_t zio_timer; | 2862 | uint16_t zio_timer; |
2807 | struct fc_host_statistics fc_host_stat; | ||
2808 | 2863 | ||
2809 | struct qla_msix_entry *msix_entries; | 2864 | struct qla_msix_entry *msix_entries; |
2810 | 2865 | ||
@@ -2817,7 +2872,6 @@ struct qla_hw_data { | |||
2817 | int cur_vport_count; | 2872 | int cur_vport_count; |
2818 | 2873 | ||
2819 | struct qla_chip_state_84xx *cs84xx; | 2874 | struct qla_chip_state_84xx *cs84xx; |
2820 | struct qla_statistics qla_stats; | ||
2821 | struct isp_operations *isp_ops; | 2875 | struct isp_operations *isp_ops; |
2822 | struct workqueue_struct *wq; | 2876 | struct workqueue_struct *wq; |
2823 | struct qlfc_fw fw_buf; | 2877 | struct qlfc_fw fw_buf; |
@@ -2863,6 +2917,8 @@ struct qla_hw_data { | |||
2863 | dma_addr_t md_tmplt_hdr_dma; | 2917 | dma_addr_t md_tmplt_hdr_dma; |
2864 | void *md_dump; | 2918 | void *md_dump; |
2865 | uint32_t md_dump_size; | 2919 | uint32_t md_dump_size; |
2920 | |||
2921 | struct qlt_hw_data tgt; | ||
2866 | }; | 2922 | }; |
2867 | 2923 | ||
2868 | /* | 2924 | /* |
@@ -2920,6 +2976,7 @@ typedef struct scsi_qla_host { | |||
2920 | #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ | 2976 | #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ |
2921 | #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ | 2977 | #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ |
2922 | #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ | 2978 | #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ |
2979 | #define SCR_PENDING 21 /* SCR in target mode */ | ||
2923 | 2980 | ||
2924 | uint32_t device_flags; | 2981 | uint32_t device_flags; |
2925 | #define SWITCH_FOUND BIT_0 | 2982 | #define SWITCH_FOUND BIT_0 |
@@ -2979,10 +3036,21 @@ typedef struct scsi_qla_host { | |||
2979 | struct req_que *req; | 3036 | struct req_que *req; |
2980 | int fw_heartbeat_counter; | 3037 | int fw_heartbeat_counter; |
2981 | int seconds_since_last_heartbeat; | 3038 | int seconds_since_last_heartbeat; |
3039 | struct fc_host_statistics fc_host_stat; | ||
3040 | struct qla_statistics qla_stats; | ||
2982 | 3041 | ||
2983 | atomic_t vref_count; | 3042 | atomic_t vref_count; |
2984 | } scsi_qla_host_t; | 3043 | } scsi_qla_host_t; |
2985 | 3044 | ||
3045 | #define SET_VP_IDX 1 | ||
3046 | #define SET_AL_PA 2 | ||
3047 | #define RESET_VP_IDX 3 | ||
3048 | #define RESET_AL_PA 4 | ||
3049 | struct qla_tgt_vp_map { | ||
3050 | uint8_t idx; | ||
3051 | scsi_qla_host_t *vha; | ||
3052 | }; | ||
3053 | |||
2986 | /* | 3054 | /* |
2987 | * Macros to help code, maintain, etc. | 3055 | * Macros to help code, maintain, etc. |
2988 | */ | 3056 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 9f065804bd12..9eacd2df111b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -175,6 +175,7 @@ extern int qla2x00_vp_abort_isp(scsi_qla_host_t *); | |||
175 | /* | 175 | /* |
176 | * Global Function Prototypes in qla_iocb.c source file. | 176 | * Global Function Prototypes in qla_iocb.c source file. |
177 | */ | 177 | */ |
178 | |||
178 | extern uint16_t qla2x00_calc_iocbs_32(uint16_t); | 179 | extern uint16_t qla2x00_calc_iocbs_32(uint16_t); |
179 | extern uint16_t qla2x00_calc_iocbs_64(uint16_t); | 180 | extern uint16_t qla2x00_calc_iocbs_64(uint16_t); |
180 | extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t); | 181 | extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t); |
@@ -188,6 +189,8 @@ extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t); | |||
188 | extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); | 189 | extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); |
189 | extern int qla24xx_dif_start_scsi(srb_t *); | 190 | extern int qla24xx_dif_start_scsi(srb_t *); |
190 | 191 | ||
192 | extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); | ||
193 | extern int qla2x00_issue_marker(scsi_qla_host_t *, int); | ||
191 | 194 | ||
192 | /* | 195 | /* |
193 | * Global Function Prototypes in qla_mbx.c source file. | 196 | * Global Function Prototypes in qla_mbx.c source file. |
@@ -239,6 +242,9 @@ extern int | |||
239 | qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); | 242 | qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); |
240 | 243 | ||
241 | extern int | 244 | extern int |
245 | qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *); | ||
246 | |||
247 | extern int | ||
242 | qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); | 248 | qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); |
243 | 249 | ||
244 | extern int | 250 | extern int |
@@ -383,6 +389,8 @@ extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *); | |||
383 | extern void qla2x00_free_irqs(scsi_qla_host_t *); | 389 | extern void qla2x00_free_irqs(scsi_qla_host_t *); |
384 | 390 | ||
385 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); | 391 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); |
392 | extern char *qla2x00_get_link_speed_str(struct qla_hw_data *); | ||
393 | |||
386 | /* | 394 | /* |
387 | * Global Function Prototypes in qla_sup.c source file. | 395 | * Global Function Prototypes in qla_sup.c source file. |
388 | */ | 396 | */ |
@@ -546,6 +554,7 @@ extern void qla2x00_sp_free(void *, void *); | |||
546 | extern void qla2x00_sp_timeout(unsigned long); | 554 | extern void qla2x00_sp_timeout(unsigned long); |
547 | extern void qla2x00_bsg_job_done(void *, void *, int); | 555 | extern void qla2x00_bsg_job_done(void *, void *, int); |
548 | extern void qla2x00_bsg_sp_free(void *, void *); | 556 | extern void qla2x00_bsg_sp_free(void *, void *); |
557 | extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *); | ||
549 | 558 | ||
550 | /* Interrupt related */ | 559 | /* Interrupt related */ |
551 | extern irqreturn_t qla82xx_intr_handler(int, void *); | 560 | extern irqreturn_t qla82xx_intr_handler(int, void *); |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 3128f80441f5..05260d25fe46 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_target.h" | ||
8 | 9 | ||
9 | static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *); | 10 | static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *); |
10 | static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *); | 11 | static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *); |
@@ -556,7 +557,8 @@ qla2x00_rff_id(scsi_qla_host_t *vha) | |||
556 | ct_req->req.rff_id.port_id[1] = vha->d_id.b.area; | 557 | ct_req->req.rff_id.port_id[1] = vha->d_id.b.area; |
557 | ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa; | 558 | ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa; |
558 | 559 | ||
559 | ct_req->req.rff_id.fc4_feature = BIT_1; | 560 | qlt_rff_id(vha, ct_req); |
561 | |||
560 | ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ | 562 | ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ |
561 | 563 | ||
562 | /* Execute MS IOCB */ | 564 | /* Execute MS IOCB */ |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b9465643396b..ca5084743135 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -17,6 +17,9 @@ | |||
17 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #include <target/target_core_base.h> | ||
21 | #include "qla_target.h" | ||
22 | |||
20 | /* | 23 | /* |
21 | * QLogic ISP2x00 Hardware Support Function Prototypes. | 24 | * QLogic ISP2x00 Hardware Support Function Prototypes. |
22 | */ | 25 | */ |
@@ -518,7 +521,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
518 | return QLA_FUNCTION_FAILED; | 521 | return QLA_FUNCTION_FAILED; |
519 | } | 522 | } |
520 | } | 523 | } |
521 | rval = qla2x00_init_rings(vha); | 524 | |
525 | if (qla_ini_mode_enabled(vha)) | ||
526 | rval = qla2x00_init_rings(vha); | ||
527 | |||
522 | ha->flags.chip_reset_done = 1; | 528 | ha->flags.chip_reset_done = 1; |
523 | 529 | ||
524 | if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { | 530 | if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { |
@@ -1233,6 +1239,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
1233 | mq_size += ha->max_rsp_queues * | 1239 | mq_size += ha->max_rsp_queues * |
1234 | (rsp->length * sizeof(response_t)); | 1240 | (rsp->length * sizeof(response_t)); |
1235 | } | 1241 | } |
1242 | if (ha->tgt.atio_q_length) | ||
1243 | mq_size += ha->tgt.atio_q_length * sizeof(request_t); | ||
1236 | /* Allocate memory for Fibre Channel Event Buffer. */ | 1244 | /* Allocate memory for Fibre Channel Event Buffer. */ |
1237 | if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha)) | 1245 | if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha)) |
1238 | goto try_eft; | 1246 | goto try_eft; |
@@ -1696,6 +1704,12 @@ qla24xx_config_rings(struct scsi_qla_host *vha) | |||
1696 | icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); | 1704 | icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); |
1697 | icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); | 1705 | icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); |
1698 | 1706 | ||
1707 | /* Setup ATIO queue dma pointers for target mode */ | ||
1708 | icb->atio_q_inpointer = __constant_cpu_to_le16(0); | ||
1709 | icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length); | ||
1710 | icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma)); | ||
1711 | icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma)); | ||
1712 | |||
1699 | if (ha->mqenable || IS_QLA83XX(ha)) { | 1713 | if (ha->mqenable || IS_QLA83XX(ha)) { |
1700 | icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); | 1714 | icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); |
1701 | icb->rid = __constant_cpu_to_le16(rid); | 1715 | icb->rid = __constant_cpu_to_le16(rid); |
@@ -1739,6 +1753,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha) | |||
1739 | WRT_REG_DWORD(®->isp24.rsp_q_in, 0); | 1753 | WRT_REG_DWORD(®->isp24.rsp_q_in, 0); |
1740 | WRT_REG_DWORD(®->isp24.rsp_q_out, 0); | 1754 | WRT_REG_DWORD(®->isp24.rsp_q_out, 0); |
1741 | } | 1755 | } |
1756 | qlt_24xx_config_rings(vha, reg); | ||
1757 | |||
1742 | /* PCI posting */ | 1758 | /* PCI posting */ |
1743 | RD_REG_DWORD(&ioreg->hccr); | 1759 | RD_REG_DWORD(&ioreg->hccr); |
1744 | } | 1760 | } |
@@ -1794,6 +1810,11 @@ qla2x00_init_rings(scsi_qla_host_t *vha) | |||
1794 | 1810 | ||
1795 | spin_unlock(&ha->vport_slock); | 1811 | spin_unlock(&ha->vport_slock); |
1796 | 1812 | ||
1813 | ha->tgt.atio_ring_ptr = ha->tgt.atio_ring; | ||
1814 | ha->tgt.atio_ring_index = 0; | ||
1815 | /* Initialize ATIO queue entries */ | ||
1816 | qlt_init_atio_q_entries(vha); | ||
1817 | |||
1797 | ha->isp_ops->config_rings(vha); | 1818 | ha->isp_ops->config_rings(vha); |
1798 | 1819 | ||
1799 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1820 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -2051,6 +2072,10 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) | |||
2051 | vha->d_id.b.area = area; | 2072 | vha->d_id.b.area = area; |
2052 | vha->d_id.b.al_pa = al_pa; | 2073 | vha->d_id.b.al_pa = al_pa; |
2053 | 2074 | ||
2075 | spin_lock(&ha->vport_slock); | ||
2076 | qlt_update_vp_map(vha, SET_AL_PA); | ||
2077 | spin_unlock(&ha->vport_slock); | ||
2078 | |||
2054 | if (!vha->flags.init_done) | 2079 | if (!vha->flags.init_done) |
2055 | ql_log(ql_log_info, vha, 0x2010, | 2080 | ql_log(ql_log_info, vha, 0x2010, |
2056 | "Topology - %s, Host Loop address 0x%x.\n", | 2081 | "Topology - %s, Host Loop address 0x%x.\n", |
@@ -2185,7 +2210,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) | |||
2185 | nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { | 2210 | nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { |
2186 | /* Reset NVRAM data. */ | 2211 | /* Reset NVRAM data. */ |
2187 | ql_log(ql_log_warn, vha, 0x0064, | 2212 | ql_log(ql_log_warn, vha, 0x0064, |
2188 | "Inconisistent NVRAM " | 2213 | "Inconsistent NVRAM " |
2189 | "detected: checksum=0x%x id=%c version=0x%x.\n", | 2214 | "detected: checksum=0x%x id=%c version=0x%x.\n", |
2190 | chksum, nv->id[0], nv->nvram_version); | 2215 | chksum, nv->id[0], nv->nvram_version); |
2191 | ql_log(ql_log_warn, vha, 0x0065, | 2216 | ql_log(ql_log_warn, vha, 0x0065, |
@@ -2270,7 +2295,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) | |||
2270 | if (IS_QLA23XX(ha)) { | 2295 | if (IS_QLA23XX(ha)) { |
2271 | nv->firmware_options[0] |= BIT_2; | 2296 | nv->firmware_options[0] |= BIT_2; |
2272 | nv->firmware_options[0] &= ~BIT_3; | 2297 | nv->firmware_options[0] &= ~BIT_3; |
2273 | nv->firmware_options[0] &= ~BIT_6; | 2298 | nv->special_options[0] &= ~BIT_6; |
2274 | nv->add_firmware_options[1] |= BIT_5 | BIT_4; | 2299 | nv->add_firmware_options[1] |= BIT_5 | BIT_4; |
2275 | 2300 | ||
2276 | if (IS_QLA2300(ha)) { | 2301 | if (IS_QLA2300(ha)) { |
@@ -2467,14 +2492,21 @@ qla2x00_rport_del(void *data) | |||
2467 | { | 2492 | { |
2468 | fc_port_t *fcport = data; | 2493 | fc_port_t *fcport = data; |
2469 | struct fc_rport *rport; | 2494 | struct fc_rport *rport; |
2495 | scsi_qla_host_t *vha = fcport->vha; | ||
2470 | unsigned long flags; | 2496 | unsigned long flags; |
2471 | 2497 | ||
2472 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); | 2498 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); |
2473 | rport = fcport->drport ? fcport->drport: fcport->rport; | 2499 | rport = fcport->drport ? fcport->drport: fcport->rport; |
2474 | fcport->drport = NULL; | 2500 | fcport->drport = NULL; |
2475 | spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); | 2501 | spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); |
2476 | if (rport) | 2502 | if (rport) { |
2477 | fc_remote_port_delete(rport); | 2503 | fc_remote_port_delete(rport); |
2504 | /* | ||
2505 | * Release the target mode FC NEXUS in qla_target.c code | ||
2506 | * if target mod is enabled. | ||
2507 | */ | ||
2508 | qlt_fc_port_deleted(vha, fcport); | ||
2509 | } | ||
2478 | } | 2510 | } |
2479 | 2511 | ||
2480 | /** | 2512 | /** |
@@ -2495,11 +2527,11 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) | |||
2495 | 2527 | ||
2496 | /* Setup fcport template structure. */ | 2528 | /* Setup fcport template structure. */ |
2497 | fcport->vha = vha; | 2529 | fcport->vha = vha; |
2498 | fcport->vp_idx = vha->vp_idx; | ||
2499 | fcport->port_type = FCT_UNKNOWN; | 2530 | fcport->port_type = FCT_UNKNOWN; |
2500 | fcport->loop_id = FC_NO_LOOP_ID; | 2531 | fcport->loop_id = FC_NO_LOOP_ID; |
2501 | qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); | 2532 | qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); |
2502 | fcport->supported_classes = FC_COS_UNSPECIFIED; | 2533 | fcport->supported_classes = FC_COS_UNSPECIFIED; |
2534 | fcport->scan_state = QLA_FCPORT_SCAN_NONE; | ||
2503 | 2535 | ||
2504 | return fcport; | 2536 | return fcport; |
2505 | } | 2537 | } |
@@ -2726,7 +2758,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) | |||
2726 | new_fcport->d_id.b.area = area; | 2758 | new_fcport->d_id.b.area = area; |
2727 | new_fcport->d_id.b.al_pa = al_pa; | 2759 | new_fcport->d_id.b.al_pa = al_pa; |
2728 | new_fcport->loop_id = loop_id; | 2760 | new_fcport->loop_id = loop_id; |
2729 | new_fcport->vp_idx = vha->vp_idx; | ||
2730 | rval2 = qla2x00_get_port_database(vha, new_fcport, 0); | 2761 | rval2 = qla2x00_get_port_database(vha, new_fcport, 0); |
2731 | if (rval2 != QLA_SUCCESS) { | 2762 | if (rval2 != QLA_SUCCESS) { |
2732 | ql_dbg(ql_dbg_disc, vha, 0x201a, | 2763 | ql_dbg(ql_dbg_disc, vha, 0x201a, |
@@ -2760,10 +2791,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) | |||
2760 | 2791 | ||
2761 | if (!found) { | 2792 | if (!found) { |
2762 | /* New device, add to fcports list. */ | 2793 | /* New device, add to fcports list. */ |
2763 | if (vha->vp_idx) { | ||
2764 | new_fcport->vha = vha; | ||
2765 | new_fcport->vp_idx = vha->vp_idx; | ||
2766 | } | ||
2767 | list_add_tail(&new_fcport->list, &vha->vp_fcports); | 2794 | list_add_tail(&new_fcport->list, &vha->vp_fcports); |
2768 | 2795 | ||
2769 | /* Allocate a new replacement fcport. */ | 2796 | /* Allocate a new replacement fcport. */ |
@@ -2800,8 +2827,6 @@ cleanup_allocation: | |||
2800 | static void | 2827 | static void |
2801 | qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) | 2828 | qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) |
2802 | { | 2829 | { |
2803 | #define LS_UNKNOWN 2 | ||
2804 | static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" }; | ||
2805 | char *link_speed; | 2830 | char *link_speed; |
2806 | int rval; | 2831 | int rval; |
2807 | uint16_t mb[4]; | 2832 | uint16_t mb[4]; |
@@ -2829,11 +2854,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
2829 | fcport->port_name[6], fcport->port_name[7], rval, | 2854 | fcport->port_name[6], fcport->port_name[7], rval, |
2830 | fcport->fp_speed, mb[0], mb[1]); | 2855 | fcport->fp_speed, mb[0], mb[1]); |
2831 | } else { | 2856 | } else { |
2832 | link_speed = link_speeds[LS_UNKNOWN]; | 2857 | link_speed = qla2x00_get_link_speed_str(ha); |
2833 | if (fcport->fp_speed < 5) | ||
2834 | link_speed = link_speeds[fcport->fp_speed]; | ||
2835 | else if (fcport->fp_speed == 0x13) | ||
2836 | link_speed = link_speeds[5]; | ||
2837 | ql_dbg(ql_dbg_disc, vha, 0x2005, | 2858 | ql_dbg(ql_dbg_disc, vha, 0x2005, |
2838 | "iIDMA adjusted to %s GB/s " | 2859 | "iIDMA adjusted to %s GB/s " |
2839 | "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed, | 2860 | "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed, |
@@ -2864,6 +2885,12 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
2864 | "Unable to allocate fc remote port.\n"); | 2885 | "Unable to allocate fc remote port.\n"); |
2865 | return; | 2886 | return; |
2866 | } | 2887 | } |
2888 | /* | ||
2889 | * Create target mode FC NEXUS in qla_target.c if target mode is | ||
2890 | * enabled.. | ||
2891 | */ | ||
2892 | qlt_fc_port_added(vha, fcport); | ||
2893 | |||
2867 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); | 2894 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); |
2868 | *((fc_port_t **)rport->dd_data) = fcport; | 2895 | *((fc_port_t **)rport->dd_data) = fcport; |
2869 | spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); | 2896 | spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); |
@@ -2921,7 +2948,7 @@ static int | |||
2921 | qla2x00_configure_fabric(scsi_qla_host_t *vha) | 2948 | qla2x00_configure_fabric(scsi_qla_host_t *vha) |
2922 | { | 2949 | { |
2923 | int rval; | 2950 | int rval; |
2924 | fc_port_t *fcport, *fcptemp; | 2951 | fc_port_t *fcport; |
2925 | uint16_t next_loopid; | 2952 | uint16_t next_loopid; |
2926 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | 2953 | uint16_t mb[MAILBOX_REGISTER_COUNT]; |
2927 | uint16_t loop_id; | 2954 | uint16_t loop_id; |
@@ -2959,7 +2986,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
2959 | 0xfc, mb, BIT_1|BIT_0); | 2986 | 0xfc, mb, BIT_1|BIT_0); |
2960 | if (rval != QLA_SUCCESS) { | 2987 | if (rval != QLA_SUCCESS) { |
2961 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | 2988 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); |
2962 | return rval; | 2989 | break; |
2963 | } | 2990 | } |
2964 | if (mb[0] != MBS_COMMAND_COMPLETE) { | 2991 | if (mb[0] != MBS_COMMAND_COMPLETE) { |
2965 | ql_dbg(ql_dbg_disc, vha, 0x2042, | 2992 | ql_dbg(ql_dbg_disc, vha, 0x2042, |
@@ -2991,21 +3018,16 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
2991 | } | 3018 | } |
2992 | } | 3019 | } |
2993 | 3020 | ||
2994 | #define QLA_FCPORT_SCAN 1 | ||
2995 | #define QLA_FCPORT_FOUND 2 | ||
2996 | |||
2997 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
2998 | fcport->scan_state = QLA_FCPORT_SCAN; | ||
2999 | } | ||
3000 | |||
3001 | rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); | 3021 | rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); |
3002 | if (rval != QLA_SUCCESS) | 3022 | if (rval != QLA_SUCCESS) |
3003 | break; | 3023 | break; |
3004 | 3024 | ||
3005 | /* | 3025 | /* Add new ports to existing port list */ |
3006 | * Logout all previous fabric devices marked lost, except | 3026 | list_splice_tail_init(&new_fcports, &vha->vp_fcports); |
3007 | * FCP2 devices. | 3027 | |
3008 | */ | 3028 | /* Starting free loop ID. */ |
3029 | next_loopid = ha->min_external_loopid; | ||
3030 | |||
3009 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 3031 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
3010 | if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) | 3032 | if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) |
3011 | break; | 3033 | break; |
@@ -3013,7 +3035,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
3013 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) | 3035 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) |
3014 | continue; | 3036 | continue; |
3015 | 3037 | ||
3016 | if (fcport->scan_state == QLA_FCPORT_SCAN && | 3038 | /* Logout lost/gone fabric devices (non-FCP2) */ |
3039 | if (fcport->scan_state != QLA_FCPORT_SCAN_FOUND && | ||
3017 | atomic_read(&fcport->state) == FCS_ONLINE) { | 3040 | atomic_read(&fcport->state) == FCS_ONLINE) { |
3018 | qla2x00_mark_device_lost(vha, fcport, | 3041 | qla2x00_mark_device_lost(vha, fcport, |
3019 | ql2xplogiabsentdevice, 0); | 3042 | ql2xplogiabsentdevice, 0); |
@@ -3026,78 +3049,30 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
3026 | fcport->d_id.b.domain, | 3049 | fcport->d_id.b.domain, |
3027 | fcport->d_id.b.area, | 3050 | fcport->d_id.b.area, |
3028 | fcport->d_id.b.al_pa); | 3051 | fcport->d_id.b.al_pa); |
3029 | fcport->loop_id = FC_NO_LOOP_ID; | ||
3030 | } | 3052 | } |
3031 | } | ||
3032 | } | ||
3033 | |||
3034 | /* Starting free loop ID. */ | ||
3035 | next_loopid = ha->min_external_loopid; | ||
3036 | |||
3037 | /* | ||
3038 | * Scan through our port list and login entries that need to be | ||
3039 | * logged in. | ||
3040 | */ | ||
3041 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
3042 | if (atomic_read(&vha->loop_down_timer) || | ||
3043 | test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) | ||
3044 | break; | ||
3045 | |||
3046 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || | ||
3047 | (fcport->flags & FCF_LOGIN_NEEDED) == 0) | ||
3048 | continue; | 3053 | continue; |
3049 | |||
3050 | if (fcport->loop_id == FC_NO_LOOP_ID) { | ||
3051 | fcport->loop_id = next_loopid; | ||
3052 | rval = qla2x00_find_new_loop_id( | ||
3053 | base_vha, fcport); | ||
3054 | if (rval != QLA_SUCCESS) { | ||
3055 | /* Ran out of IDs to use */ | ||
3056 | break; | ||
3057 | } | ||
3058 | } | 3054 | } |
3059 | /* Login and update database */ | 3055 | fcport->scan_state = QLA_FCPORT_SCAN_NONE; |
3060 | qla2x00_fabric_dev_login(vha, fcport, &next_loopid); | 3056 | |
3061 | } | 3057 | /* Login fabric devices that need a login */ |
3062 | 3058 | if ((fcport->flags & FCF_LOGIN_NEEDED) != 0 && | |
3063 | /* Exit if out of loop IDs. */ | 3059 | atomic_read(&vha->loop_down_timer) == 0) { |
3064 | if (rval != QLA_SUCCESS) { | 3060 | if (fcport->loop_id == FC_NO_LOOP_ID) { |
3065 | break; | 3061 | fcport->loop_id = next_loopid; |
3066 | } | 3062 | rval = qla2x00_find_new_loop_id( |
3067 | 3063 | base_vha, fcport); | |
3068 | /* | 3064 | if (rval != QLA_SUCCESS) { |
3069 | * Login and add the new devices to our port list. | 3065 | /* Ran out of IDs to use */ |
3070 | */ | 3066 | continue; |
3071 | list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { | 3067 | } |
3072 | if (atomic_read(&vha->loop_down_timer) || | 3068 | } |
3073 | test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) | ||
3074 | break; | ||
3075 | |||
3076 | /* Find a new loop ID to use. */ | ||
3077 | fcport->loop_id = next_loopid; | ||
3078 | rval = qla2x00_find_new_loop_id(base_vha, fcport); | ||
3079 | if (rval != QLA_SUCCESS) { | ||
3080 | /* Ran out of IDs to use */ | ||
3081 | break; | ||
3082 | } | 3069 | } |
3083 | 3070 | ||
3084 | /* Login and update database */ | 3071 | /* Login and update database */ |
3085 | qla2x00_fabric_dev_login(vha, fcport, &next_loopid); | 3072 | qla2x00_fabric_dev_login(vha, fcport, &next_loopid); |
3086 | |||
3087 | if (vha->vp_idx) { | ||
3088 | fcport->vha = vha; | ||
3089 | fcport->vp_idx = vha->vp_idx; | ||
3090 | } | ||
3091 | list_move_tail(&fcport->list, &vha->vp_fcports); | ||
3092 | } | 3073 | } |
3093 | } while (0); | 3074 | } while (0); |
3094 | 3075 | ||
3095 | /* Free all new device structures not processed. */ | ||
3096 | list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { | ||
3097 | list_del(&fcport->list); | ||
3098 | kfree(fcport); | ||
3099 | } | ||
3100 | |||
3101 | if (rval) { | 3076 | if (rval) { |
3102 | ql_dbg(ql_dbg_disc, vha, 0x2068, | 3077 | ql_dbg(ql_dbg_disc, vha, 0x2068, |
3103 | "Configure fabric error exit rval=%d.\n", rval); | 3078 | "Configure fabric error exit rval=%d.\n", rval); |
@@ -3287,7 +3262,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
3287 | WWN_SIZE)) | 3262 | WWN_SIZE)) |
3288 | continue; | 3263 | continue; |
3289 | 3264 | ||
3290 | fcport->scan_state = QLA_FCPORT_FOUND; | 3265 | fcport->scan_state = QLA_FCPORT_SCAN_FOUND; |
3291 | 3266 | ||
3292 | found++; | 3267 | found++; |
3293 | 3268 | ||
@@ -3595,6 +3570,12 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
3595 | if (mb[10] & BIT_1) | 3570 | if (mb[10] & BIT_1) |
3596 | fcport->supported_classes |= FC_COS_CLASS3; | 3571 | fcport->supported_classes |= FC_COS_CLASS3; |
3597 | 3572 | ||
3573 | if (IS_FWI2_CAPABLE(ha)) { | ||
3574 | if (mb[10] & BIT_7) | ||
3575 | fcport->flags |= | ||
3576 | FCF_CONF_COMP_SUPPORTED; | ||
3577 | } | ||
3578 | |||
3598 | rval = QLA_SUCCESS; | 3579 | rval = QLA_SUCCESS; |
3599 | break; | 3580 | break; |
3600 | } else if (mb[0] == MBS_LOOP_ID_USED) { | 3581 | } else if (mb[0] == MBS_LOOP_ID_USED) { |
@@ -3841,7 +3822,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | |||
3841 | vha->flags.online = 0; | 3822 | vha->flags.online = 0; |
3842 | ha->flags.chip_reset_done = 0; | 3823 | ha->flags.chip_reset_done = 0; |
3843 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3824 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
3844 | ha->qla_stats.total_isp_aborts++; | 3825 | vha->qla_stats.total_isp_aborts++; |
3845 | 3826 | ||
3846 | ql_log(ql_log_info, vha, 0x00af, | 3827 | ql_log(ql_log_info, vha, 0x00af, |
3847 | "Performing ISP error recovery - ha=%p.\n", ha); | 3828 | "Performing ISP error recovery - ha=%p.\n", ha); |
@@ -4066,6 +4047,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha) | |||
4066 | struct qla_hw_data *ha = vha->hw; | 4047 | struct qla_hw_data *ha = vha->hw; |
4067 | struct req_que *req = ha->req_q_map[0]; | 4048 | struct req_que *req = ha->req_q_map[0]; |
4068 | struct rsp_que *rsp = ha->rsp_q_map[0]; | 4049 | struct rsp_que *rsp = ha->rsp_q_map[0]; |
4050 | unsigned long flags; | ||
4069 | 4051 | ||
4070 | /* If firmware needs to be loaded */ | 4052 | /* If firmware needs to be loaded */ |
4071 | if (qla2x00_isp_firmware(vha)) { | 4053 | if (qla2x00_isp_firmware(vha)) { |
@@ -4090,6 +4072,16 @@ qla2x00_restart_isp(scsi_qla_host_t *vha) | |||
4090 | qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); | 4072 | qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); |
4091 | 4073 | ||
4092 | vha->flags.online = 1; | 4074 | vha->flags.online = 1; |
4075 | |||
4076 | /* | ||
4077 | * Process any ATIO queue entries that came in | ||
4078 | * while we weren't online. | ||
4079 | */ | ||
4080 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4081 | if (qla_tgt_mode_enabled(vha)) | ||
4082 | qlt_24xx_process_atio_queue(vha); | ||
4083 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4084 | |||
4093 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ | 4085 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ |
4094 | wait_time = 256; | 4086 | wait_time = 256; |
4095 | do { | 4087 | do { |
@@ -4279,7 +4271,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
4279 | nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { | 4271 | nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { |
4280 | /* Reset NVRAM data. */ | 4272 | /* Reset NVRAM data. */ |
4281 | ql_log(ql_log_warn, vha, 0x006b, | 4273 | ql_log(ql_log_warn, vha, 0x006b, |
4282 | "Inconisistent NVRAM detected: checksum=0x%x id=%c " | 4274 | "Inconsistent NVRAM detected: checksum=0x%x id=%c " |
4283 | "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); | 4275 | "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); |
4284 | ql_log(ql_log_warn, vha, 0x006c, | 4276 | ql_log(ql_log_warn, vha, 0x006c, |
4285 | "Falling back to functioning (yet invalid -- WWPN) " | 4277 | "Falling back to functioning (yet invalid -- WWPN) " |
@@ -4330,6 +4322,15 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
4330 | rval = 1; | 4322 | rval = 1; |
4331 | } | 4323 | } |
4332 | 4324 | ||
4325 | if (!qla_ini_mode_enabled(vha)) { | ||
4326 | /* Don't enable full login after initial LIP */ | ||
4327 | nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); | ||
4328 | /* Don't enable LIP full login for initiator */ | ||
4329 | nv->host_p &= __constant_cpu_to_le32(~BIT_10); | ||
4330 | } | ||
4331 | |||
4332 | qlt_24xx_config_nvram_stage1(vha, nv); | ||
4333 | |||
4333 | /* Reset Initialization control block */ | 4334 | /* Reset Initialization control block */ |
4334 | memset(icb, 0, ha->init_cb_size); | 4335 | memset(icb, 0, ha->init_cb_size); |
4335 | 4336 | ||
@@ -4357,8 +4358,10 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
4357 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), | 4358 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), |
4358 | "QLA2462"); | 4359 | "QLA2462"); |
4359 | 4360 | ||
4360 | /* Use alternate WWN? */ | 4361 | qlt_24xx_config_nvram_stage2(vha, icb); |
4362 | |||
4361 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { | 4363 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { |
4364 | /* Use alternate WWN? */ | ||
4362 | memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); | 4365 | memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); |
4363 | memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); | 4366 | memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); |
4364 | } | 4367 | } |
@@ -5029,7 +5032,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
5029 | nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { | 5032 | nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { |
5030 | /* Reset NVRAM data. */ | 5033 | /* Reset NVRAM data. */ |
5031 | ql_log(ql_log_info, vha, 0x0073, | 5034 | ql_log(ql_log_info, vha, 0x0073, |
5032 | "Inconisistent NVRAM detected: checksum=0x%x id=%c " | 5035 | "Inconsistent NVRAM detected: checksum=0x%x id=%c " |
5033 | "version=0x%x.\n", chksum, nv->id[0], | 5036 | "version=0x%x.\n", chksum, nv->id[0], |
5034 | le16_to_cpu(nv->nvram_version)); | 5037 | le16_to_cpu(nv->nvram_version)); |
5035 | ql_log(ql_log_info, vha, 0x0074, | 5038 | ql_log(ql_log_info, vha, 0x0074, |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index eac950924497..70dbf53d9e0f 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_target.h" | ||
8 | 9 | ||
9 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
10 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
@@ -23,18 +24,17 @@ qla2x00_get_cmd_direction(srb_t *sp) | |||
23 | { | 24 | { |
24 | uint16_t cflags; | 25 | uint16_t cflags; |
25 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); | 26 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); |
27 | struct scsi_qla_host *vha = sp->fcport->vha; | ||
26 | 28 | ||
27 | cflags = 0; | 29 | cflags = 0; |
28 | 30 | ||
29 | /* Set transfer direction */ | 31 | /* Set transfer direction */ |
30 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 32 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
31 | cflags = CF_WRITE; | 33 | cflags = CF_WRITE; |
32 | sp->fcport->vha->hw->qla_stats.output_bytes += | 34 | vha->qla_stats.output_bytes += scsi_bufflen(cmd); |
33 | scsi_bufflen(cmd); | ||
34 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | 35 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { |
35 | cflags = CF_READ; | 36 | cflags = CF_READ; |
36 | sp->fcport->vha->hw->qla_stats.input_bytes += | 37 | vha->qla_stats.input_bytes += scsi_bufflen(cmd); |
37 | scsi_bufflen(cmd); | ||
38 | } | 38 | } |
39 | return (cflags); | 39 | return (cflags); |
40 | } | 40 | } |
@@ -385,9 +385,10 @@ qla2x00_start_scsi(srb_t *sp) | |||
385 | else | 385 | else |
386 | req->cnt = req->length - | 386 | req->cnt = req->length - |
387 | (req->ring_index - cnt); | 387 | (req->ring_index - cnt); |
388 | /* If still no head room then bail out */ | ||
389 | if (req->cnt < (req_cnt + 2)) | ||
390 | goto queuing_error; | ||
388 | } | 391 | } |
389 | if (req->cnt < (req_cnt + 2)) | ||
390 | goto queuing_error; | ||
391 | 392 | ||
392 | /* Build command packet */ | 393 | /* Build command packet */ |
393 | req->current_outstanding_cmd = handle; | 394 | req->current_outstanding_cmd = handle; |
@@ -470,7 +471,7 @@ queuing_error: | |||
470 | /** | 471 | /** |
471 | * qla2x00_start_iocbs() - Execute the IOCB command | 472 | * qla2x00_start_iocbs() - Execute the IOCB command |
472 | */ | 473 | */ |
473 | static void | 474 | void |
474 | qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) | 475 | qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) |
475 | { | 476 | { |
476 | struct qla_hw_data *ha = vha->hw; | 477 | struct qla_hw_data *ha = vha->hw; |
@@ -571,6 +572,29 @@ qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, | |||
571 | return (ret); | 572 | return (ret); |
572 | } | 573 | } |
573 | 574 | ||
575 | /* | ||
576 | * qla2x00_issue_marker | ||
577 | * | ||
578 | * Issue marker | ||
579 | * Caller CAN have hardware lock held as specified by ha_locked parameter. | ||
580 | * Might release it, then reaquire. | ||
581 | */ | ||
582 | int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked) | ||
583 | { | ||
584 | if (ha_locked) { | ||
585 | if (__qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0, | ||
586 | MK_SYNC_ALL) != QLA_SUCCESS) | ||
587 | return QLA_FUNCTION_FAILED; | ||
588 | } else { | ||
589 | if (qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0, | ||
590 | MK_SYNC_ALL) != QLA_SUCCESS) | ||
591 | return QLA_FUNCTION_FAILED; | ||
592 | } | ||
593 | vha->marker_needed = 0; | ||
594 | |||
595 | return QLA_SUCCESS; | ||
596 | } | ||
597 | |||
574 | /** | 598 | /** |
575 | * qla24xx_calc_iocbs() - Determine number of Command Type 3 and | 599 | * qla24xx_calc_iocbs() - Determine number of Command Type 3 and |
576 | * Continuation Type 1 IOCBs to allocate. | 600 | * Continuation Type 1 IOCBs to allocate. |
@@ -629,11 +653,11 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, | |||
629 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 653 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
630 | cmd_pkt->control_flags = | 654 | cmd_pkt->control_flags = |
631 | __constant_cpu_to_le16(CF_WRITE_DATA); | 655 | __constant_cpu_to_le16(CF_WRITE_DATA); |
632 | ha->qla_stats.output_bytes += scsi_bufflen(cmd); | 656 | vha->qla_stats.output_bytes += scsi_bufflen(cmd); |
633 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | 657 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { |
634 | cmd_pkt->control_flags = | 658 | cmd_pkt->control_flags = |
635 | __constant_cpu_to_le16(CF_READ_DATA); | 659 | __constant_cpu_to_le16(CF_READ_DATA); |
636 | ha->qla_stats.input_bytes += scsi_bufflen(cmd); | 660 | vha->qla_stats.input_bytes += scsi_bufflen(cmd); |
637 | } | 661 | } |
638 | 662 | ||
639 | cur_seg = scsi_sglist(cmd); | 663 | cur_seg = scsi_sglist(cmd); |
@@ -745,13 +769,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
745 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 769 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
746 | cmd_pkt->task_mgmt_flags = | 770 | cmd_pkt->task_mgmt_flags = |
747 | __constant_cpu_to_le16(TMF_WRITE_DATA); | 771 | __constant_cpu_to_le16(TMF_WRITE_DATA); |
748 | sp->fcport->vha->hw->qla_stats.output_bytes += | 772 | vha->qla_stats.output_bytes += scsi_bufflen(cmd); |
749 | scsi_bufflen(cmd); | ||
750 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | 773 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { |
751 | cmd_pkt->task_mgmt_flags = | 774 | cmd_pkt->task_mgmt_flags = |
752 | __constant_cpu_to_le16(TMF_READ_DATA); | 775 | __constant_cpu_to_le16(TMF_READ_DATA); |
753 | sp->fcport->vha->hw->qla_stats.input_bytes += | 776 | vha->qla_stats.input_bytes += scsi_bufflen(cmd); |
754 | scsi_bufflen(cmd); | ||
755 | } | 777 | } |
756 | 778 | ||
757 | /* One DSD is available in the Command Type 3 IOCB */ | 779 | /* One DSD is available in the Command Type 3 IOCB */ |
@@ -1245,7 +1267,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, | |||
1245 | return QLA_SUCCESS; | 1267 | return QLA_SUCCESS; |
1246 | } | 1268 | } |
1247 | 1269 | ||
1248 | cmd_pkt->vp_index = sp->fcport->vp_idx; | 1270 | cmd_pkt->vp_index = sp->fcport->vha->vp_idx; |
1249 | 1271 | ||
1250 | /* Set transfer direction */ | 1272 | /* Set transfer direction */ |
1251 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 1273 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
@@ -1502,9 +1524,9 @@ qla24xx_start_scsi(srb_t *sp) | |||
1502 | else | 1524 | else |
1503 | req->cnt = req->length - | 1525 | req->cnt = req->length - |
1504 | (req->ring_index - cnt); | 1526 | (req->ring_index - cnt); |
1527 | if (req->cnt < (req_cnt + 2)) | ||
1528 | goto queuing_error; | ||
1505 | } | 1529 | } |
1506 | if (req->cnt < (req_cnt + 2)) | ||
1507 | goto queuing_error; | ||
1508 | 1530 | ||
1509 | /* Build command packet. */ | 1531 | /* Build command packet. */ |
1510 | req->current_outstanding_cmd = handle; | 1532 | req->current_outstanding_cmd = handle; |
@@ -1527,7 +1549,7 @@ qla24xx_start_scsi(srb_t *sp) | |||
1527 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | 1549 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; |
1528 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | 1550 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; |
1529 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | 1551 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; |
1530 | cmd_pkt->vp_index = sp->fcport->vp_idx; | 1552 | cmd_pkt->vp_index = sp->fcport->vha->vp_idx; |
1531 | 1553 | ||
1532 | int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); | 1554 | int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); |
1533 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); | 1555 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); |
@@ -1717,11 +1739,10 @@ qla24xx_dif_start_scsi(srb_t *sp) | |||
1717 | else | 1739 | else |
1718 | req->cnt = req->length - | 1740 | req->cnt = req->length - |
1719 | (req->ring_index - cnt); | 1741 | (req->ring_index - cnt); |
1742 | if (req->cnt < (req_cnt + 2)) | ||
1743 | goto queuing_error; | ||
1720 | } | 1744 | } |
1721 | 1745 | ||
1722 | if (req->cnt < (req_cnt + 2)) | ||
1723 | goto queuing_error; | ||
1724 | |||
1725 | status |= QDSS_GOT_Q_SPACE; | 1746 | status |= QDSS_GOT_Q_SPACE; |
1726 | 1747 | ||
1727 | /* Build header part of command packet (excluding the OPCODE). */ | 1748 | /* Build header part of command packet (excluding the OPCODE). */ |
@@ -1898,7 +1919,7 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) | |||
1898 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | 1919 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; |
1899 | logio->port_id[1] = sp->fcport->d_id.b.area; | 1920 | logio->port_id[1] = sp->fcport->d_id.b.area; |
1900 | logio->port_id[2] = sp->fcport->d_id.b.domain; | 1921 | logio->port_id[2] = sp->fcport->d_id.b.domain; |
1901 | logio->vp_index = sp->fcport->vp_idx; | 1922 | logio->vp_index = sp->fcport->vha->vp_idx; |
1902 | } | 1923 | } |
1903 | 1924 | ||
1904 | static void | 1925 | static void |
@@ -1922,7 +1943,7 @@ qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) | |||
1922 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | 1943 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); |
1923 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | 1944 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | |
1924 | sp->fcport->d_id.b.al_pa); | 1945 | sp->fcport->d_id.b.al_pa); |
1925 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | 1946 | mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx); |
1926 | } | 1947 | } |
1927 | 1948 | ||
1928 | static void | 1949 | static void |
@@ -1935,7 +1956,7 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) | |||
1935 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | 1956 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; |
1936 | logio->port_id[1] = sp->fcport->d_id.b.area; | 1957 | logio->port_id[1] = sp->fcport->d_id.b.area; |
1937 | logio->port_id[2] = sp->fcport->d_id.b.domain; | 1958 | logio->port_id[2] = sp->fcport->d_id.b.domain; |
1938 | logio->vp_index = sp->fcport->vp_idx; | 1959 | logio->vp_index = sp->fcport->vha->vp_idx; |
1939 | } | 1960 | } |
1940 | 1961 | ||
1941 | static void | 1962 | static void |
@@ -1952,7 +1973,7 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | |||
1952 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | 1973 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); |
1953 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | 1974 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | |
1954 | sp->fcport->d_id.b.al_pa); | 1975 | sp->fcport->d_id.b.al_pa); |
1955 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | 1976 | mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx); |
1956 | /* Implicit: mbx->mbx10 = 0. */ | 1977 | /* Implicit: mbx->mbx10 = 0. */ |
1957 | } | 1978 | } |
1958 | 1979 | ||
@@ -1962,7 +1983,7 @@ qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio) | |||
1962 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | 1983 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; |
1963 | logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC); | 1984 | logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC); |
1964 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | 1985 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); |
1965 | logio->vp_index = sp->fcport->vp_idx; | 1986 | logio->vp_index = sp->fcport->vha->vp_idx; |
1966 | } | 1987 | } |
1967 | 1988 | ||
1968 | static void | 1989 | static void |
@@ -1983,7 +2004,7 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx) | |||
1983 | mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma)); | 2004 | mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma)); |
1984 | mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma))); | 2005 | mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma))); |
1985 | mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma))); | 2006 | mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma))); |
1986 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | 2007 | mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx); |
1987 | } | 2008 | } |
1988 | 2009 | ||
1989 | static void | 2010 | static void |
@@ -2009,7 +2030,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) | |||
2009 | tsk->port_id[0] = fcport->d_id.b.al_pa; | 2030 | tsk->port_id[0] = fcport->d_id.b.al_pa; |
2010 | tsk->port_id[1] = fcport->d_id.b.area; | 2031 | tsk->port_id[1] = fcport->d_id.b.area; |
2011 | tsk->port_id[2] = fcport->d_id.b.domain; | 2032 | tsk->port_id[2] = fcport->d_id.b.domain; |
2012 | tsk->vp_index = fcport->vp_idx; | 2033 | tsk->vp_index = fcport->vha->vp_idx; |
2013 | 2034 | ||
2014 | if (flags == TCF_LUN_RESET) { | 2035 | if (flags == TCF_LUN_RESET) { |
2015 | int_to_scsilun(lun, &tsk->lun); | 2036 | int_to_scsilun(lun, &tsk->lun); |
@@ -2030,7 +2051,7 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | |||
2030 | els_iocb->handle = sp->handle; | 2051 | els_iocb->handle = sp->handle; |
2031 | els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); | 2052 | els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); |
2032 | els_iocb->tx_dsd_count = __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); | 2053 | els_iocb->tx_dsd_count = __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); |
2033 | els_iocb->vp_index = sp->fcport->vp_idx; | 2054 | els_iocb->vp_index = sp->fcport->vha->vp_idx; |
2034 | els_iocb->sof_type = EST_SOFI3; | 2055 | els_iocb->sof_type = EST_SOFI3; |
2035 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); | 2056 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); |
2036 | 2057 | ||
@@ -2160,7 +2181,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | |||
2160 | ct_iocb->handle = sp->handle; | 2181 | ct_iocb->handle = sp->handle; |
2161 | 2182 | ||
2162 | ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); | 2183 | ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); |
2163 | ct_iocb->vp_index = sp->fcport->vp_idx; | 2184 | ct_iocb->vp_index = sp->fcport->vha->vp_idx; |
2164 | ct_iocb->comp_status = __constant_cpu_to_le16(0); | 2185 | ct_iocb->comp_status = __constant_cpu_to_le16(0); |
2165 | 2186 | ||
2166 | ct_iocb->cmd_dsd_count = | 2187 | ct_iocb->cmd_dsd_count = |
@@ -2343,11 +2364,10 @@ sufficient_dsds: | |||
2343 | else | 2364 | else |
2344 | req->cnt = req->length - | 2365 | req->cnt = req->length - |
2345 | (req->ring_index - cnt); | 2366 | (req->ring_index - cnt); |
2367 | if (req->cnt < (req_cnt + 2)) | ||
2368 | goto queuing_error; | ||
2346 | } | 2369 | } |
2347 | 2370 | ||
2348 | if (req->cnt < (req_cnt + 2)) | ||
2349 | goto queuing_error; | ||
2350 | |||
2351 | ctx = sp->u.scmd.ctx = | 2371 | ctx = sp->u.scmd.ctx = |
2352 | mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); | 2372 | mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); |
2353 | if (!ctx) { | 2373 | if (!ctx) { |
@@ -2362,7 +2382,7 @@ sufficient_dsds: | |||
2362 | if (!ctx->fcp_cmnd) { | 2382 | if (!ctx->fcp_cmnd) { |
2363 | ql_log(ql_log_fatal, vha, 0x3011, | 2383 | ql_log(ql_log_fatal, vha, 0x3011, |
2364 | "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd); | 2384 | "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd); |
2365 | goto queuing_error_fcp_cmnd; | 2385 | goto queuing_error; |
2366 | } | 2386 | } |
2367 | 2387 | ||
2368 | /* Initialize the DSD list and dma handle */ | 2388 | /* Initialize the DSD list and dma handle */ |
@@ -2400,7 +2420,7 @@ sufficient_dsds: | |||
2400 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | 2420 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; |
2401 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | 2421 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; |
2402 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | 2422 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; |
2403 | cmd_pkt->vp_index = sp->fcport->vp_idx; | 2423 | cmd_pkt->vp_index = sp->fcport->vha->vp_idx; |
2404 | 2424 | ||
2405 | /* Build IOCB segments */ | 2425 | /* Build IOCB segments */ |
2406 | if (qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds)) | 2426 | if (qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds)) |
@@ -2489,7 +2509,7 @@ sufficient_dsds: | |||
2489 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | 2509 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; |
2490 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | 2510 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; |
2491 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | 2511 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; |
2492 | cmd_pkt->vp_index = sp->fcport->vp_idx; | 2512 | cmd_pkt->vp_index = sp->fcport->vha->vp_idx; |
2493 | 2513 | ||
2494 | int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); | 2514 | int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); |
2495 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, | 2515 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ce42288049b5..6f67a9d4998b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_target.h" | ||
8 | 9 | ||
9 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
@@ -309,6 +310,28 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) | |||
309 | "IDC failed to post ACK.\n"); | 310 | "IDC failed to post ACK.\n"); |
310 | } | 311 | } |
311 | 312 | ||
313 | #define LS_UNKNOWN 2 | ||
314 | char * | ||
315 | qla2x00_get_link_speed_str(struct qla_hw_data *ha) | ||
316 | { | ||
317 | static char *link_speeds[] = {"1", "2", "?", "4", "8", "16", "10"}; | ||
318 | char *link_speed; | ||
319 | int fw_speed = ha->link_data_rate; | ||
320 | |||
321 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | ||
322 | link_speed = link_speeds[0]; | ||
323 | else if (fw_speed == 0x13) | ||
324 | link_speed = link_speeds[6]; | ||
325 | else { | ||
326 | link_speed = link_speeds[LS_UNKNOWN]; | ||
327 | if (fw_speed < 6) | ||
328 | link_speed = | ||
329 | link_speeds[fw_speed]; | ||
330 | } | ||
331 | |||
332 | return link_speed; | ||
333 | } | ||
334 | |||
312 | /** | 335 | /** |
313 | * qla2x00_async_event() - Process aynchronous events. | 336 | * qla2x00_async_event() - Process aynchronous events. |
314 | * @ha: SCSI driver HA context | 337 | * @ha: SCSI driver HA context |
@@ -317,9 +340,6 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) | |||
317 | void | 340 | void |
318 | qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) | 341 | qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) |
319 | { | 342 | { |
320 | #define LS_UNKNOWN 2 | ||
321 | static char *link_speeds[] = { "1", "2", "?", "4", "8", "16", "10" }; | ||
322 | char *link_speed; | ||
323 | uint16_t handle_cnt; | 343 | uint16_t handle_cnt; |
324 | uint16_t cnt, mbx; | 344 | uint16_t cnt, mbx; |
325 | uint32_t handles[5]; | 345 | uint32_t handles[5]; |
@@ -454,8 +474,8 @@ skip_rio: | |||
454 | case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ | 474 | case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ |
455 | ql_dbg(ql_dbg_async, vha, 0x5008, | 475 | ql_dbg(ql_dbg_async, vha, 0x5008, |
456 | "Asynchronous WAKEUP_THRES.\n"); | 476 | "Asynchronous WAKEUP_THRES.\n"); |
457 | break; | ||
458 | 477 | ||
478 | break; | ||
459 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ | 479 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ |
460 | ql_dbg(ql_dbg_async, vha, 0x5009, | 480 | ql_dbg(ql_dbg_async, vha, 0x5009, |
461 | "LIP occurred (%x).\n", mb[1]); | 481 | "LIP occurred (%x).\n", mb[1]); |
@@ -479,20 +499,14 @@ skip_rio: | |||
479 | break; | 499 | break; |
480 | 500 | ||
481 | case MBA_LOOP_UP: /* Loop Up Event */ | 501 | case MBA_LOOP_UP: /* Loop Up Event */ |
482 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 502 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
483 | link_speed = link_speeds[0]; | ||
484 | ha->link_data_rate = PORT_SPEED_1GB; | 503 | ha->link_data_rate = PORT_SPEED_1GB; |
485 | } else { | 504 | else |
486 | link_speed = link_speeds[LS_UNKNOWN]; | ||
487 | if (mb[1] < 6) | ||
488 | link_speed = link_speeds[mb[1]]; | ||
489 | else if (mb[1] == 0x13) | ||
490 | link_speed = link_speeds[6]; | ||
491 | ha->link_data_rate = mb[1]; | 505 | ha->link_data_rate = mb[1]; |
492 | } | ||
493 | 506 | ||
494 | ql_dbg(ql_dbg_async, vha, 0x500a, | 507 | ql_dbg(ql_dbg_async, vha, 0x500a, |
495 | "LOOP UP detected (%s Gbps).\n", link_speed); | 508 | "LOOP UP detected (%s Gbps).\n", |
509 | qla2x00_get_link_speed_str(ha)); | ||
496 | 510 | ||
497 | vha->flags.management_server_logged_in = 0; | 511 | vha->flags.management_server_logged_in = 0; |
498 | qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); | 512 | qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); |
@@ -638,6 +652,8 @@ skip_rio: | |||
638 | ql_dbg(ql_dbg_async, vha, 0x5010, | 652 | ql_dbg(ql_dbg_async, vha, 0x5010, |
639 | "Port unavailable %04x %04x %04x.\n", | 653 | "Port unavailable %04x %04x %04x.\n", |
640 | mb[1], mb[2], mb[3]); | 654 | mb[1], mb[2], mb[3]); |
655 | ql_log(ql_log_warn, vha, 0x505e, | ||
656 | "Link is offline.\n"); | ||
641 | 657 | ||
642 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | 658 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
643 | atomic_set(&vha->loop_state, LOOP_DOWN); | 659 | atomic_set(&vha->loop_state, LOOP_DOWN); |
@@ -670,12 +686,17 @@ skip_rio: | |||
670 | ql_dbg(ql_dbg_async, vha, 0x5011, | 686 | ql_dbg(ql_dbg_async, vha, 0x5011, |
671 | "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", | 687 | "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", |
672 | mb[1], mb[2], mb[3]); | 688 | mb[1], mb[2], mb[3]); |
689 | |||
690 | qlt_async_event(mb[0], vha, mb); | ||
673 | break; | 691 | break; |
674 | } | 692 | } |
675 | 693 | ||
676 | ql_dbg(ql_dbg_async, vha, 0x5012, | 694 | ql_dbg(ql_dbg_async, vha, 0x5012, |
677 | "Port database changed %04x %04x %04x.\n", | 695 | "Port database changed %04x %04x %04x.\n", |
678 | mb[1], mb[2], mb[3]); | 696 | mb[1], mb[2], mb[3]); |
697 | ql_log(ql_log_warn, vha, 0x505f, | ||
698 | "Link is operational (%s Gbps).\n", | ||
699 | qla2x00_get_link_speed_str(ha)); | ||
679 | 700 | ||
680 | /* | 701 | /* |
681 | * Mark all devices as missing so we will login again. | 702 | * Mark all devices as missing so we will login again. |
@@ -684,8 +705,13 @@ skip_rio: | |||
684 | 705 | ||
685 | qla2x00_mark_all_devices_lost(vha, 1); | 706 | qla2x00_mark_all_devices_lost(vha, 1); |
686 | 707 | ||
708 | if (vha->vp_idx == 0 && !qla_ini_mode_enabled(vha)) | ||
709 | set_bit(SCR_PENDING, &vha->dpc_flags); | ||
710 | |||
687 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | 711 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); |
688 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | 712 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); |
713 | |||
714 | qlt_async_event(mb[0], vha, mb); | ||
689 | break; | 715 | break; |
690 | 716 | ||
691 | case MBA_RSCN_UPDATE: /* State Change Registration */ | 717 | case MBA_RSCN_UPDATE: /* State Change Registration */ |
@@ -807,6 +833,8 @@ skip_rio: | |||
807 | mb[0], mb[1], mb[2], mb[3]); | 833 | mb[0], mb[1], mb[2], mb[3]); |
808 | } | 834 | } |
809 | 835 | ||
836 | qlt_async_event(mb[0], vha, mb); | ||
837 | |||
810 | if (!vha->vp_idx && ha->num_vhosts) | 838 | if (!vha->vp_idx && ha->num_vhosts) |
811 | qla2x00_alert_all_vps(rsp, mb); | 839 | qla2x00_alert_all_vps(rsp, mb); |
812 | } | 840 | } |
@@ -1172,6 +1200,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1172 | } else if (iop[0] & BIT_5) | 1200 | } else if (iop[0] & BIT_5) |
1173 | fcport->port_type = FCT_INITIATOR; | 1201 | fcport->port_type = FCT_INITIATOR; |
1174 | 1202 | ||
1203 | if (iop[0] & BIT_7) | ||
1204 | fcport->flags |= FCF_CONF_COMP_SUPPORTED; | ||
1205 | |||
1175 | if (logio->io_parameter[7] || logio->io_parameter[8]) | 1206 | if (logio->io_parameter[7] || logio->io_parameter[8]) |
1176 | fcport->supported_classes |= FC_COS_CLASS2; | 1207 | fcport->supported_classes |= FC_COS_CLASS2; |
1177 | if (logio->io_parameter[9] || logio->io_parameter[10]) | 1208 | if (logio->io_parameter[9] || logio->io_parameter[10]) |
@@ -1986,6 +2017,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1986 | 2017 | ||
1987 | if (pkt->entry_status != 0) { | 2018 | if (pkt->entry_status != 0) { |
1988 | qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); | 2019 | qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); |
2020 | |||
2021 | (void)qlt_24xx_process_response_error(vha, pkt); | ||
2022 | |||
1989 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; | 2023 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; |
1990 | wmb(); | 2024 | wmb(); |
1991 | continue; | 2025 | continue; |
@@ -2016,6 +2050,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
2016 | case ELS_IOCB_TYPE: | 2050 | case ELS_IOCB_TYPE: |
2017 | qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); | 2051 | qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); |
2018 | break; | 2052 | break; |
2053 | case ABTS_RECV_24XX: | ||
2054 | /* ensure that the ATIO queue is empty */ | ||
2055 | qlt_24xx_process_atio_queue(vha); | ||
2056 | case ABTS_RESP_24XX: | ||
2057 | case CTIO_TYPE7: | ||
2058 | case NOTIFY_ACK_TYPE: | ||
2059 | qlt_response_pkt_all_vps(vha, (response_t *)pkt); | ||
2060 | break; | ||
2019 | case MARKER_TYPE: | 2061 | case MARKER_TYPE: |
2020 | /* Do nothing in this case, this check is to prevent it | 2062 | /* Do nothing in this case, this check is to prevent it |
2021 | * from falling into default case | 2063 | * from falling into default case |
@@ -2168,6 +2210,13 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
2168 | case 0x14: | 2210 | case 0x14: |
2169 | qla24xx_process_response_queue(vha, rsp); | 2211 | qla24xx_process_response_queue(vha, rsp); |
2170 | break; | 2212 | break; |
2213 | case 0x1C: /* ATIO queue updated */ | ||
2214 | qlt_24xx_process_atio_queue(vha); | ||
2215 | break; | ||
2216 | case 0x1D: /* ATIO and response queues updated */ | ||
2217 | qlt_24xx_process_atio_queue(vha); | ||
2218 | qla24xx_process_response_queue(vha, rsp); | ||
2219 | break; | ||
2171 | default: | 2220 | default: |
2172 | ql_dbg(ql_dbg_async, vha, 0x504f, | 2221 | ql_dbg(ql_dbg_async, vha, 0x504f, |
2173 | "Unrecognized interrupt type (%d).\n", stat * 0xff); | 2222 | "Unrecognized interrupt type (%d).\n", stat * 0xff); |
@@ -2312,6 +2361,13 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2312 | case 0x14: | 2361 | case 0x14: |
2313 | qla24xx_process_response_queue(vha, rsp); | 2362 | qla24xx_process_response_queue(vha, rsp); |
2314 | break; | 2363 | break; |
2364 | case 0x1C: /* ATIO queue updated */ | ||
2365 | qlt_24xx_process_atio_queue(vha); | ||
2366 | break; | ||
2367 | case 0x1D: /* ATIO and response queues updated */ | ||
2368 | qlt_24xx_process_atio_queue(vha); | ||
2369 | qla24xx_process_response_queue(vha, rsp); | ||
2370 | break; | ||
2315 | default: | 2371 | default: |
2316 | ql_dbg(ql_dbg_async, vha, 0x5051, | 2372 | ql_dbg(ql_dbg_async, vha, 0x5051, |
2317 | "Unrecognized interrupt type (%d).\n", stat & 0xff); | 2373 | "Unrecognized interrupt type (%d).\n", stat & 0xff); |
@@ -2564,7 +2620,15 @@ void | |||
2564 | qla2x00_free_irqs(scsi_qla_host_t *vha) | 2620 | qla2x00_free_irqs(scsi_qla_host_t *vha) |
2565 | { | 2621 | { |
2566 | struct qla_hw_data *ha = vha->hw; | 2622 | struct qla_hw_data *ha = vha->hw; |
2567 | struct rsp_que *rsp = ha->rsp_q_map[0]; | 2623 | struct rsp_que *rsp; |
2624 | |||
2625 | /* | ||
2626 | * We need to check that ha->rsp_q_map is valid in case we are called | ||
2627 | * from a probe failure context. | ||
2628 | */ | ||
2629 | if (!ha->rsp_q_map || !ha->rsp_q_map[0]) | ||
2630 | return; | ||
2631 | rsp = ha->rsp_q_map[0]; | ||
2568 | 2632 | ||
2569 | if (ha->flags.msix_enabled) | 2633 | if (ha->flags.msix_enabled) |
2570 | qla24xx_disable_msix(ha); | 2634 | qla24xx_disable_msix(ha); |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index b4a23394a7bd..d5ce92c0a8fc 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_target.h" | ||
8 | 9 | ||
9 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
10 | #include <linux/gfp.h> | 11 | #include <linux/gfp.h> |
@@ -270,11 +271,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
270 | ictrl = RD_REG_WORD(®->isp.ictrl); | 271 | ictrl = RD_REG_WORD(®->isp.ictrl); |
271 | } | 272 | } |
272 | ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119, | 273 | ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119, |
273 | "MBX Command timeout for cmd %x.\n", command); | 274 | "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx " |
274 | ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111a, | 275 | "mb[0]=0x%x\n", command, ictrl, jiffies, mb0); |
275 | "iocontrol=%x jiffies=%lx.\n", ictrl, jiffies); | ||
276 | ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111b, | ||
277 | "mb[0] = 0x%x.\n", mb0); | ||
278 | ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019); | 276 | ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019); |
279 | 277 | ||
280 | /* | 278 | /* |
@@ -320,7 +318,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
320 | CRB_NIU_XG_PAUSE_CTL_P1); | 318 | CRB_NIU_XG_PAUSE_CTL_P1); |
321 | } | 319 | } |
322 | ql_log(ql_log_info, base_vha, 0x101c, | 320 | ql_log(ql_log_info, base_vha, 0x101c, |
323 | "Mailbox cmd timeout occured, cmd=0x%x, " | 321 | "Mailbox cmd timeout occurred, cmd=0x%x, " |
324 | "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP " | 322 | "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP " |
325 | "abort.\n", command, mcp->mb[0], | 323 | "abort.\n", command, mcp->mb[0], |
326 | ha->flags.eeh_busy); | 324 | ha->flags.eeh_busy); |
@@ -345,7 +343,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
345 | CRB_NIU_XG_PAUSE_CTL_P1); | 343 | CRB_NIU_XG_PAUSE_CTL_P1); |
346 | } | 344 | } |
347 | ql_log(ql_log_info, base_vha, 0x101e, | 345 | ql_log(ql_log_info, base_vha, 0x101e, |
348 | "Mailbox cmd timeout occured, cmd=0x%x, " | 346 | "Mailbox cmd timeout occurred, cmd=0x%x, " |
349 | "mb[0]=0x%x. Scheduling ISP abort ", | 347 | "mb[0]=0x%x. Scheduling ISP abort ", |
350 | command, mcp->mb[0]); | 348 | command, mcp->mb[0]); |
351 | set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); | 349 | set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); |
@@ -390,7 +388,8 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, | |||
390 | mbx_cmd_t mc; | 388 | mbx_cmd_t mc; |
391 | mbx_cmd_t *mcp = &mc; | 389 | mbx_cmd_t *mcp = &mc; |
392 | 390 | ||
393 | ql_dbg(ql_dbg_mbx, vha, 0x1022, "Entered %s.\n", __func__); | 391 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1022, |
392 | "Entered %s.\n", __func__); | ||
394 | 393 | ||
395 | if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) { | 394 | if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) { |
396 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; | 395 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; |
@@ -424,7 +423,8 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, | |||
424 | ql_dbg(ql_dbg_mbx, vha, 0x1023, | 423 | ql_dbg(ql_dbg_mbx, vha, 0x1023, |
425 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 424 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
426 | } else { | 425 | } else { |
427 | ql_dbg(ql_dbg_mbx, vha, 0x1024, "Done %s.\n", __func__); | 426 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024, |
427 | "Done %s.\n", __func__); | ||
428 | } | 428 | } |
429 | 429 | ||
430 | return rval; | 430 | return rval; |
@@ -454,7 +454,8 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) | |||
454 | mbx_cmd_t mc; | 454 | mbx_cmd_t mc; |
455 | mbx_cmd_t *mcp = &mc; | 455 | mbx_cmd_t *mcp = &mc; |
456 | 456 | ||
457 | ql_dbg(ql_dbg_mbx, vha, 0x1025, "Entered %s.\n", __func__); | 457 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, |
458 | "Entered %s.\n", __func__); | ||
458 | 459 | ||
459 | mcp->mb[0] = MBC_EXECUTE_FIRMWARE; | 460 | mcp->mb[0] = MBC_EXECUTE_FIRMWARE; |
460 | mcp->out_mb = MBX_0; | 461 | mcp->out_mb = MBX_0; |
@@ -489,10 +490,11 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) | |||
489 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 490 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
490 | } else { | 491 | } else { |
491 | if (IS_FWI2_CAPABLE(ha)) { | 492 | if (IS_FWI2_CAPABLE(ha)) { |
492 | ql_dbg(ql_dbg_mbx, vha, 0x1027, | 493 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1027, |
493 | "Done exchanges=%x.\n", mcp->mb[1]); | 494 | "Done exchanges=%x.\n", mcp->mb[1]); |
494 | } else { | 495 | } else { |
495 | ql_dbg(ql_dbg_mbx, vha, 0x1028, "Done %s.\n", __func__); | 496 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, |
497 | "Done %s.\n", __func__); | ||
496 | } | 498 | } |
497 | } | 499 | } |
498 | 500 | ||
@@ -523,7 +525,8 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) | |||
523 | mbx_cmd_t *mcp = &mc; | 525 | mbx_cmd_t *mcp = &mc; |
524 | struct qla_hw_data *ha = vha->hw; | 526 | struct qla_hw_data *ha = vha->hw; |
525 | 527 | ||
526 | ql_dbg(ql_dbg_mbx, vha, 0x1029, "Entered %s.\n", __func__); | 528 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1029, |
529 | "Entered %s.\n", __func__); | ||
527 | 530 | ||
528 | mcp->mb[0] = MBC_GET_FIRMWARE_VERSION; | 531 | mcp->mb[0] = MBC_GET_FIRMWARE_VERSION; |
529 | mcp->out_mb = MBX_0; | 532 | mcp->out_mb = MBX_0; |
@@ -561,11 +564,11 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) | |||
561 | ha->fw_attributes_h = mcp->mb[15]; | 564 | ha->fw_attributes_h = mcp->mb[15]; |
562 | ha->fw_attributes_ext[0] = mcp->mb[16]; | 565 | ha->fw_attributes_ext[0] = mcp->mb[16]; |
563 | ha->fw_attributes_ext[1] = mcp->mb[17]; | 566 | ha->fw_attributes_ext[1] = mcp->mb[17]; |
564 | ql_dbg(ql_dbg_mbx, vha, 0x1139, | 567 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1139, |
565 | "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n", | 568 | "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n", |
566 | __func__, mcp->mb[15], mcp->mb[6]); | 569 | __func__, mcp->mb[15], mcp->mb[6]); |
567 | } else | 570 | } else |
568 | ql_dbg(ql_dbg_mbx, vha, 0x112f, | 571 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x112f, |
569 | "%s: FwAttributes [Upper] invalid, MB6:%04x\n", | 572 | "%s: FwAttributes [Upper] invalid, MB6:%04x\n", |
570 | __func__, mcp->mb[6]); | 573 | __func__, mcp->mb[6]); |
571 | } | 574 | } |
@@ -576,7 +579,8 @@ failed: | |||
576 | ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval); | 579 | ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval); |
577 | } else { | 580 | } else { |
578 | /*EMPTY*/ | 581 | /*EMPTY*/ |
579 | ql_dbg(ql_dbg_mbx, vha, 0x102b, "Done %s.\n", __func__); | 582 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102b, |
583 | "Done %s.\n", __func__); | ||
580 | } | 584 | } |
581 | return rval; | 585 | return rval; |
582 | } | 586 | } |
@@ -602,7 +606,8 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) | |||
602 | mbx_cmd_t mc; | 606 | mbx_cmd_t mc; |
603 | mbx_cmd_t *mcp = &mc; | 607 | mbx_cmd_t *mcp = &mc; |
604 | 608 | ||
605 | ql_dbg(ql_dbg_mbx, vha, 0x102c, "Entered %s.\n", __func__); | 609 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102c, |
610 | "Entered %s.\n", __func__); | ||
606 | 611 | ||
607 | mcp->mb[0] = MBC_GET_FIRMWARE_OPTION; | 612 | mcp->mb[0] = MBC_GET_FIRMWARE_OPTION; |
608 | mcp->out_mb = MBX_0; | 613 | mcp->out_mb = MBX_0; |
@@ -620,7 +625,8 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) | |||
620 | fwopts[2] = mcp->mb[2]; | 625 | fwopts[2] = mcp->mb[2]; |
621 | fwopts[3] = mcp->mb[3]; | 626 | fwopts[3] = mcp->mb[3]; |
622 | 627 | ||
623 | ql_dbg(ql_dbg_mbx, vha, 0x102e, "Done %s.\n", __func__); | 628 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102e, |
629 | "Done %s.\n", __func__); | ||
624 | } | 630 | } |
625 | 631 | ||
626 | return rval; | 632 | return rval; |
@@ -648,7 +654,8 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) | |||
648 | mbx_cmd_t mc; | 654 | mbx_cmd_t mc; |
649 | mbx_cmd_t *mcp = &mc; | 655 | mbx_cmd_t *mcp = &mc; |
650 | 656 | ||
651 | ql_dbg(ql_dbg_mbx, vha, 0x102f, "Entered %s.\n", __func__); | 657 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102f, |
658 | "Entered %s.\n", __func__); | ||
652 | 659 | ||
653 | mcp->mb[0] = MBC_SET_FIRMWARE_OPTION; | 660 | mcp->mb[0] = MBC_SET_FIRMWARE_OPTION; |
654 | mcp->mb[1] = fwopts[1]; | 661 | mcp->mb[1] = fwopts[1]; |
@@ -676,7 +683,8 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) | |||
676 | "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]); | 683 | "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]); |
677 | } else { | 684 | } else { |
678 | /*EMPTY*/ | 685 | /*EMPTY*/ |
679 | ql_dbg(ql_dbg_mbx, vha, 0x1031, "Done %s.\n", __func__); | 686 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1031, |
687 | "Done %s.\n", __func__); | ||
680 | } | 688 | } |
681 | 689 | ||
682 | return rval; | 690 | return rval; |
@@ -704,7 +712,8 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha) | |||
704 | mbx_cmd_t mc; | 712 | mbx_cmd_t mc; |
705 | mbx_cmd_t *mcp = &mc; | 713 | mbx_cmd_t *mcp = &mc; |
706 | 714 | ||
707 | ql_dbg(ql_dbg_mbx, vha, 0x1032, "Entered %s.\n", __func__); | 715 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1032, |
716 | "Entered %s.\n", __func__); | ||
708 | 717 | ||
709 | mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; | 718 | mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; |
710 | mcp->mb[1] = 0xAAAA; | 719 | mcp->mb[1] = 0xAAAA; |
@@ -734,7 +743,8 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha) | |||
734 | ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval); | 743 | ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval); |
735 | } else { | 744 | } else { |
736 | /*EMPTY*/ | 745 | /*EMPTY*/ |
737 | ql_dbg(ql_dbg_mbx, vha, 0x1034, "Done %s.\n", __func__); | 746 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034, |
747 | "Done %s.\n", __func__); | ||
738 | } | 748 | } |
739 | 749 | ||
740 | return rval; | 750 | return rval; |
@@ -762,7 +772,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr) | |||
762 | mbx_cmd_t mc; | 772 | mbx_cmd_t mc; |
763 | mbx_cmd_t *mcp = &mc; | 773 | mbx_cmd_t *mcp = &mc; |
764 | 774 | ||
765 | ql_dbg(ql_dbg_mbx, vha, 0x1035, "Entered %s.\n", __func__); | 775 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1035, |
776 | "Entered %s.\n", __func__); | ||
766 | 777 | ||
767 | mcp->mb[0] = MBC_VERIFY_CHECKSUM; | 778 | mcp->mb[0] = MBC_VERIFY_CHECKSUM; |
768 | mcp->out_mb = MBX_0; | 779 | mcp->out_mb = MBX_0; |
@@ -787,7 +798,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr) | |||
787 | "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ? | 798 | "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ? |
788 | (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]); | 799 | (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]); |
789 | } else { | 800 | } else { |
790 | ql_dbg(ql_dbg_mbx, vha, 0x1037, "Done %s.\n", __func__); | 801 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1037, |
802 | "Done %s.\n", __func__); | ||
791 | } | 803 | } |
792 | 804 | ||
793 | return rval; | 805 | return rval; |
@@ -819,7 +831,8 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, | |||
819 | mbx_cmd_t mc; | 831 | mbx_cmd_t mc; |
820 | mbx_cmd_t *mcp = &mc; | 832 | mbx_cmd_t *mcp = &mc; |
821 | 833 | ||
822 | ql_dbg(ql_dbg_mbx, vha, 0x1038, "Entered %s.\n", __func__); | 834 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, |
835 | "Entered %s.\n", __func__); | ||
823 | 836 | ||
824 | mcp->mb[0] = MBC_IOCB_COMMAND_A64; | 837 | mcp->mb[0] = MBC_IOCB_COMMAND_A64; |
825 | mcp->mb[1] = 0; | 838 | mcp->mb[1] = 0; |
@@ -842,7 +855,8 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, | |||
842 | /* Mask reserved bits. */ | 855 | /* Mask reserved bits. */ |
843 | sts_entry->entry_status &= | 856 | sts_entry->entry_status &= |
844 | IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; | 857 | IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; |
845 | ql_dbg(ql_dbg_mbx, vha, 0x103a, "Done %s.\n", __func__); | 858 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, |
859 | "Done %s.\n", __func__); | ||
846 | } | 860 | } |
847 | 861 | ||
848 | return rval; | 862 | return rval; |
@@ -884,7 +898,8 @@ qla2x00_abort_command(srb_t *sp) | |||
884 | struct req_que *req = vha->req; | 898 | struct req_que *req = vha->req; |
885 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); | 899 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); |
886 | 900 | ||
887 | ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__); | 901 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, |
902 | "Entered %s.\n", __func__); | ||
888 | 903 | ||
889 | spin_lock_irqsave(&ha->hardware_lock, flags); | 904 | spin_lock_irqsave(&ha->hardware_lock, flags); |
890 | for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { | 905 | for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { |
@@ -915,7 +930,8 @@ qla2x00_abort_command(srb_t *sp) | |||
915 | if (rval != QLA_SUCCESS) { | 930 | if (rval != QLA_SUCCESS) { |
916 | ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval); | 931 | ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval); |
917 | } else { | 932 | } else { |
918 | ql_dbg(ql_dbg_mbx, vha, 0x103d, "Done %s.\n", __func__); | 933 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103d, |
934 | "Done %s.\n", __func__); | ||
919 | } | 935 | } |
920 | 936 | ||
921 | return rval; | 937 | return rval; |
@@ -934,7 +950,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) | |||
934 | l = l; | 950 | l = l; |
935 | vha = fcport->vha; | 951 | vha = fcport->vha; |
936 | 952 | ||
937 | ql_dbg(ql_dbg_mbx, vha, 0x103e, "Entered %s.\n", __func__); | 953 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103e, |
954 | "Entered %s.\n", __func__); | ||
938 | 955 | ||
939 | req = vha->hw->req_q_map[0]; | 956 | req = vha->hw->req_q_map[0]; |
940 | rsp = req->rsp; | 957 | rsp = req->rsp; |
@@ -955,7 +972,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) | |||
955 | mcp->flags = 0; | 972 | mcp->flags = 0; |
956 | rval = qla2x00_mailbox_command(vha, mcp); | 973 | rval = qla2x00_mailbox_command(vha, mcp); |
957 | if (rval != QLA_SUCCESS) { | 974 | if (rval != QLA_SUCCESS) { |
958 | ql_dbg(ql_dbg_mbx, vha, 0x103f, "Failed=%x.\n", rval); | 975 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103f, |
976 | "Failed=%x.\n", rval); | ||
959 | } | 977 | } |
960 | 978 | ||
961 | /* Issue marker IOCB. */ | 979 | /* Issue marker IOCB. */ |
@@ -965,7 +983,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) | |||
965 | ql_dbg(ql_dbg_mbx, vha, 0x1040, | 983 | ql_dbg(ql_dbg_mbx, vha, 0x1040, |
966 | "Failed to issue marker IOCB (%x).\n", rval2); | 984 | "Failed to issue marker IOCB (%x).\n", rval2); |
967 | } else { | 985 | } else { |
968 | ql_dbg(ql_dbg_mbx, vha, 0x1041, "Done %s.\n", __func__); | 986 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1041, |
987 | "Done %s.\n", __func__); | ||
969 | } | 988 | } |
970 | 989 | ||
971 | return rval; | 990 | return rval; |
@@ -983,7 +1002,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) | |||
983 | 1002 | ||
984 | vha = fcport->vha; | 1003 | vha = fcport->vha; |
985 | 1004 | ||
986 | ql_dbg(ql_dbg_mbx, vha, 0x1042, "Entered %s.\n", __func__); | 1005 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1042, |
1006 | "Entered %s.\n", __func__); | ||
987 | 1007 | ||
988 | req = vha->hw->req_q_map[0]; | 1008 | req = vha->hw->req_q_map[0]; |
989 | rsp = req->rsp; | 1009 | rsp = req->rsp; |
@@ -1012,7 +1032,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) | |||
1012 | ql_dbg(ql_dbg_mbx, vha, 0x1044, | 1032 | ql_dbg(ql_dbg_mbx, vha, 0x1044, |
1013 | "Failed to issue marker IOCB (%x).\n", rval2); | 1033 | "Failed to issue marker IOCB (%x).\n", rval2); |
1014 | } else { | 1034 | } else { |
1015 | ql_dbg(ql_dbg_mbx, vha, 0x1045, "Done %s.\n", __func__); | 1035 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1045, |
1036 | "Done %s.\n", __func__); | ||
1016 | } | 1037 | } |
1017 | 1038 | ||
1018 | return rval; | 1039 | return rval; |
@@ -1046,7 +1067,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, | |||
1046 | mbx_cmd_t mc; | 1067 | mbx_cmd_t mc; |
1047 | mbx_cmd_t *mcp = &mc; | 1068 | mbx_cmd_t *mcp = &mc; |
1048 | 1069 | ||
1049 | ql_dbg(ql_dbg_mbx, vha, 0x1046, "Entered %s.\n", __func__); | 1070 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1046, |
1071 | "Entered %s.\n", __func__); | ||
1050 | 1072 | ||
1051 | mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; | 1073 | mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; |
1052 | mcp->mb[9] = vha->vp_idx; | 1074 | mcp->mb[9] = vha->vp_idx; |
@@ -1074,7 +1096,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, | |||
1074 | /*EMPTY*/ | 1096 | /*EMPTY*/ |
1075 | ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval); | 1097 | ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval); |
1076 | } else { | 1098 | } else { |
1077 | ql_dbg(ql_dbg_mbx, vha, 0x1048, "Done %s.\n", __func__); | 1099 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1048, |
1100 | "Done %s.\n", __func__); | ||
1078 | 1101 | ||
1079 | if (IS_CNA_CAPABLE(vha->hw)) { | 1102 | if (IS_CNA_CAPABLE(vha->hw)) { |
1080 | vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; | 1103 | vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; |
@@ -1115,7 +1138,8 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov, | |||
1115 | mbx_cmd_t mc; | 1138 | mbx_cmd_t mc; |
1116 | mbx_cmd_t *mcp = &mc; | 1139 | mbx_cmd_t *mcp = &mc; |
1117 | 1140 | ||
1118 | ql_dbg(ql_dbg_mbx, vha, 0x1049, "Entered %s.\n", __func__); | 1141 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1049, |
1142 | "Entered %s.\n", __func__); | ||
1119 | 1143 | ||
1120 | mcp->mb[0] = MBC_GET_RETRY_COUNT; | 1144 | mcp->mb[0] = MBC_GET_RETRY_COUNT; |
1121 | mcp->out_mb = MBX_0; | 1145 | mcp->out_mb = MBX_0; |
@@ -1138,7 +1162,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov, | |||
1138 | *tov = ratov; | 1162 | *tov = ratov; |
1139 | } | 1163 | } |
1140 | 1164 | ||
1141 | ql_dbg(ql_dbg_mbx, vha, 0x104b, | 1165 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104b, |
1142 | "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov); | 1166 | "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov); |
1143 | } | 1167 | } |
1144 | 1168 | ||
@@ -1170,7 +1194,8 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) | |||
1170 | mbx_cmd_t *mcp = &mc; | 1194 | mbx_cmd_t *mcp = &mc; |
1171 | struct qla_hw_data *ha = vha->hw; | 1195 | struct qla_hw_data *ha = vha->hw; |
1172 | 1196 | ||
1173 | ql_dbg(ql_dbg_mbx, vha, 0x104c, "Entered %s.\n", __func__); | 1197 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104c, |
1198 | "Entered %s.\n", __func__); | ||
1174 | 1199 | ||
1175 | if (IS_QLA82XX(ha) && ql2xdbwr) | 1200 | if (IS_QLA82XX(ha) && ql2xdbwr) |
1176 | qla82xx_wr_32(ha, ha->nxdb_wr_ptr, | 1201 | qla82xx_wr_32(ha, ha->nxdb_wr_ptr, |
@@ -1213,9 +1238,100 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) | |||
1213 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); | 1238 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); |
1214 | } else { | 1239 | } else { |
1215 | /*EMPTY*/ | 1240 | /*EMPTY*/ |
1216 | ql_dbg(ql_dbg_mbx, vha, 0x104e, "Done %s.\n", __func__); | 1241 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104e, |
1242 | "Done %s.\n", __func__); | ||
1243 | } | ||
1244 | |||
1245 | return rval; | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | * qla2x00_get_node_name_list | ||
1250 | * Issue get node name list mailbox command, kmalloc() | ||
1251 | * and return the resulting list. Caller must kfree() it! | ||
1252 | * | ||
1253 | * Input: | ||
1254 | * ha = adapter state pointer. | ||
1255 | * out_data = resulting list | ||
1256 | * out_len = length of the resulting list | ||
1257 | * | ||
1258 | * Returns: | ||
1259 | * qla2x00 local function return status code. | ||
1260 | * | ||
1261 | * Context: | ||
1262 | * Kernel context. | ||
1263 | */ | ||
1264 | int | ||
1265 | qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len) | ||
1266 | { | ||
1267 | struct qla_hw_data *ha = vha->hw; | ||
1268 | struct qla_port_24xx_data *list = NULL; | ||
1269 | void *pmap; | ||
1270 | mbx_cmd_t mc; | ||
1271 | dma_addr_t pmap_dma; | ||
1272 | ulong dma_size; | ||
1273 | int rval, left; | ||
1274 | |||
1275 | left = 1; | ||
1276 | while (left > 0) { | ||
1277 | dma_size = left * sizeof(*list); | ||
1278 | pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size, | ||
1279 | &pmap_dma, GFP_KERNEL); | ||
1280 | if (!pmap) { | ||
1281 | ql_log(ql_log_warn, vha, 0x113f, | ||
1282 | "%s(%ld): DMA Alloc failed of %ld\n", | ||
1283 | __func__, vha->host_no, dma_size); | ||
1284 | rval = QLA_MEMORY_ALLOC_FAILED; | ||
1285 | goto out; | ||
1286 | } | ||
1287 | |||
1288 | mc.mb[0] = MBC_PORT_NODE_NAME_LIST; | ||
1289 | mc.mb[1] = BIT_1 | BIT_3; | ||
1290 | mc.mb[2] = MSW(pmap_dma); | ||
1291 | mc.mb[3] = LSW(pmap_dma); | ||
1292 | mc.mb[6] = MSW(MSD(pmap_dma)); | ||
1293 | mc.mb[7] = LSW(MSD(pmap_dma)); | ||
1294 | mc.mb[8] = dma_size; | ||
1295 | mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8; | ||
1296 | mc.in_mb = MBX_0|MBX_1; | ||
1297 | mc.tov = 30; | ||
1298 | mc.flags = MBX_DMA_IN; | ||
1299 | |||
1300 | rval = qla2x00_mailbox_command(vha, &mc); | ||
1301 | if (rval != QLA_SUCCESS) { | ||
1302 | if ((mc.mb[0] == MBS_COMMAND_ERROR) && | ||
1303 | (mc.mb[1] == 0xA)) { | ||
1304 | left += le16_to_cpu(mc.mb[2]) / | ||
1305 | sizeof(struct qla_port_24xx_data); | ||
1306 | goto restart; | ||
1307 | } | ||
1308 | goto out_free; | ||
1309 | } | ||
1310 | |||
1311 | left = 0; | ||
1312 | |||
1313 | list = kzalloc(dma_size, GFP_KERNEL); | ||
1314 | if (!list) { | ||
1315 | ql_log(ql_log_warn, vha, 0x1140, | ||
1316 | "%s(%ld): failed to allocate node names list " | ||
1317 | "structure.\n", __func__, vha->host_no); | ||
1318 | rval = QLA_MEMORY_ALLOC_FAILED; | ||
1319 | goto out_free; | ||
1320 | } | ||
1321 | |||
1322 | memcpy(list, pmap, dma_size); | ||
1323 | restart: | ||
1324 | dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma); | ||
1217 | } | 1325 | } |
1218 | 1326 | ||
1327 | *out_data = list; | ||
1328 | *out_len = dma_size; | ||
1329 | |||
1330 | out: | ||
1331 | return rval; | ||
1332 | |||
1333 | out_free: | ||
1334 | dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma); | ||
1219 | return rval; | 1335 | return rval; |
1220 | } | 1336 | } |
1221 | 1337 | ||
@@ -1246,7 +1362,8 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) | |||
1246 | dma_addr_t pd_dma; | 1362 | dma_addr_t pd_dma; |
1247 | struct qla_hw_data *ha = vha->hw; | 1363 | struct qla_hw_data *ha = vha->hw; |
1248 | 1364 | ||
1249 | ql_dbg(ql_dbg_mbx, vha, 0x104f, "Entered %s.\n", __func__); | 1365 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104f, |
1366 | "Entered %s.\n", __func__); | ||
1250 | 1367 | ||
1251 | pd24 = NULL; | 1368 | pd24 = NULL; |
1252 | pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); | 1369 | pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); |
@@ -1326,6 +1443,13 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) | |||
1326 | fcport->port_type = FCT_INITIATOR; | 1443 | fcport->port_type = FCT_INITIATOR; |
1327 | else | 1444 | else |
1328 | fcport->port_type = FCT_TARGET; | 1445 | fcport->port_type = FCT_TARGET; |
1446 | |||
1447 | /* Passback COS information. */ | ||
1448 | fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ? | ||
1449 | FC_COS_CLASS2 : FC_COS_CLASS3; | ||
1450 | |||
1451 | if (pd24->prli_svc_param_word_3[0] & BIT_7) | ||
1452 | fcport->flags |= FCF_CONF_COMP_SUPPORTED; | ||
1329 | } else { | 1453 | } else { |
1330 | uint64_t zero = 0; | 1454 | uint64_t zero = 0; |
1331 | 1455 | ||
@@ -1378,7 +1502,8 @@ gpd_error_out: | |||
1378 | "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, | 1502 | "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, |
1379 | mcp->mb[0], mcp->mb[1]); | 1503 | mcp->mb[0], mcp->mb[1]); |
1380 | } else { | 1504 | } else { |
1381 | ql_dbg(ql_dbg_mbx, vha, 0x1053, "Done %s.\n", __func__); | 1505 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1053, |
1506 | "Done %s.\n", __func__); | ||
1382 | } | 1507 | } |
1383 | 1508 | ||
1384 | return rval; | 1509 | return rval; |
@@ -1407,7 +1532,8 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) | |||
1407 | mbx_cmd_t mc; | 1532 | mbx_cmd_t mc; |
1408 | mbx_cmd_t *mcp = &mc; | 1533 | mbx_cmd_t *mcp = &mc; |
1409 | 1534 | ||
1410 | ql_dbg(ql_dbg_mbx, vha, 0x1054, "Entered %s.\n", __func__); | 1535 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054, |
1536 | "Entered %s.\n", __func__); | ||
1411 | 1537 | ||
1412 | mcp->mb[0] = MBC_GET_FIRMWARE_STATE; | 1538 | mcp->mb[0] = MBC_GET_FIRMWARE_STATE; |
1413 | mcp->out_mb = MBX_0; | 1539 | mcp->out_mb = MBX_0; |
@@ -1433,7 +1559,8 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) | |||
1433 | ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval); | 1559 | ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval); |
1434 | } else { | 1560 | } else { |
1435 | /*EMPTY*/ | 1561 | /*EMPTY*/ |
1436 | ql_dbg(ql_dbg_mbx, vha, 0x1056, "Done %s.\n", __func__); | 1562 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1056, |
1563 | "Done %s.\n", __func__); | ||
1437 | } | 1564 | } |
1438 | 1565 | ||
1439 | return rval; | 1566 | return rval; |
@@ -1465,7 +1592,8 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name, | |||
1465 | mbx_cmd_t mc; | 1592 | mbx_cmd_t mc; |
1466 | mbx_cmd_t *mcp = &mc; | 1593 | mbx_cmd_t *mcp = &mc; |
1467 | 1594 | ||
1468 | ql_dbg(ql_dbg_mbx, vha, 0x1057, "Entered %s.\n", __func__); | 1595 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1057, |
1596 | "Entered %s.\n", __func__); | ||
1469 | 1597 | ||
1470 | mcp->mb[0] = MBC_GET_PORT_NAME; | 1598 | mcp->mb[0] = MBC_GET_PORT_NAME; |
1471 | mcp->mb[9] = vha->vp_idx; | 1599 | mcp->mb[9] = vha->vp_idx; |
@@ -1499,7 +1627,8 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name, | |||
1499 | name[7] = LSB(mcp->mb[7]); | 1627 | name[7] = LSB(mcp->mb[7]); |
1500 | } | 1628 | } |
1501 | 1629 | ||
1502 | ql_dbg(ql_dbg_mbx, vha, 0x1059, "Done %s.\n", __func__); | 1630 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1059, |
1631 | "Done %s.\n", __func__); | ||
1503 | } | 1632 | } |
1504 | 1633 | ||
1505 | return rval; | 1634 | return rval; |
@@ -1527,7 +1656,8 @@ qla2x00_lip_reset(scsi_qla_host_t *vha) | |||
1527 | mbx_cmd_t mc; | 1656 | mbx_cmd_t mc; |
1528 | mbx_cmd_t *mcp = &mc; | 1657 | mbx_cmd_t *mcp = &mc; |
1529 | 1658 | ||
1530 | ql_dbg(ql_dbg_mbx, vha, 0x105a, "Entered %s.\n", __func__); | 1659 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105a, |
1660 | "Entered %s.\n", __func__); | ||
1531 | 1661 | ||
1532 | if (IS_CNA_CAPABLE(vha->hw)) { | 1662 | if (IS_CNA_CAPABLE(vha->hw)) { |
1533 | /* Logout across all FCFs. */ | 1663 | /* Logout across all FCFs. */ |
@@ -1564,7 +1694,8 @@ qla2x00_lip_reset(scsi_qla_host_t *vha) | |||
1564 | ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval); | 1694 | ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval); |
1565 | } else { | 1695 | } else { |
1566 | /*EMPTY*/ | 1696 | /*EMPTY*/ |
1567 | ql_dbg(ql_dbg_mbx, vha, 0x105c, "Done %s.\n", __func__); | 1697 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105c, |
1698 | "Done %s.\n", __func__); | ||
1568 | } | 1699 | } |
1569 | 1700 | ||
1570 | return rval; | 1701 | return rval; |
@@ -1596,9 +1727,10 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address, | |||
1596 | mbx_cmd_t mc; | 1727 | mbx_cmd_t mc; |
1597 | mbx_cmd_t *mcp = &mc; | 1728 | mbx_cmd_t *mcp = &mc; |
1598 | 1729 | ||
1599 | ql_dbg(ql_dbg_mbx, vha, 0x105d, "Entered %s.\n", __func__); | 1730 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105d, |
1731 | "Entered %s.\n", __func__); | ||
1600 | 1732 | ||
1601 | ql_dbg(ql_dbg_mbx, vha, 0x105e, | 1733 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105e, |
1602 | "Retry cnt=%d ratov=%d total tov=%d.\n", | 1734 | "Retry cnt=%d ratov=%d total tov=%d.\n", |
1603 | vha->hw->retry_count, vha->hw->login_timeout, mcp->tov); | 1735 | vha->hw->retry_count, vha->hw->login_timeout, mcp->tov); |
1604 | 1736 | ||
@@ -1622,7 +1754,8 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address, | |||
1622 | rval, mcp->mb[0], mcp->mb[1]); | 1754 | rval, mcp->mb[0], mcp->mb[1]); |
1623 | } else { | 1755 | } else { |
1624 | /*EMPTY*/ | 1756 | /*EMPTY*/ |
1625 | ql_dbg(ql_dbg_mbx, vha, 0x1060, "Done %s.\n", __func__); | 1757 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1060, |
1758 | "Done %s.\n", __func__); | ||
1626 | } | 1759 | } |
1627 | 1760 | ||
1628 | return rval; | 1761 | return rval; |
@@ -1641,7 +1774,8 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1641 | struct req_que *req; | 1774 | struct req_que *req; |
1642 | struct rsp_que *rsp; | 1775 | struct rsp_que *rsp; |
1643 | 1776 | ||
1644 | ql_dbg(ql_dbg_mbx, vha, 0x1061, "Entered %s.\n", __func__); | 1777 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1061, |
1778 | "Entered %s.\n", __func__); | ||
1645 | 1779 | ||
1646 | if (ha->flags.cpu_affinity_enabled) | 1780 | if (ha->flags.cpu_affinity_enabled) |
1647 | req = ha->req_q_map[0]; | 1781 | req = ha->req_q_map[0]; |
@@ -1715,7 +1849,8 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1715 | break; | 1849 | break; |
1716 | } | 1850 | } |
1717 | } else { | 1851 | } else { |
1718 | ql_dbg(ql_dbg_mbx, vha, 0x1066, "Done %s.\n", __func__); | 1852 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1066, |
1853 | "Done %s.\n", __func__); | ||
1719 | 1854 | ||
1720 | iop[0] = le32_to_cpu(lg->io_parameter[0]); | 1855 | iop[0] = le32_to_cpu(lg->io_parameter[0]); |
1721 | 1856 | ||
@@ -1733,6 +1868,10 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1733 | mb[10] |= BIT_0; /* Class 2. */ | 1868 | mb[10] |= BIT_0; /* Class 2. */ |
1734 | if (lg->io_parameter[9] || lg->io_parameter[10]) | 1869 | if (lg->io_parameter[9] || lg->io_parameter[10]) |
1735 | mb[10] |= BIT_1; /* Class 3. */ | 1870 | mb[10] |= BIT_1; /* Class 3. */ |
1871 | if (lg->io_parameter[0] & __constant_cpu_to_le32(BIT_7)) | ||
1872 | mb[10] |= BIT_7; /* Confirmed Completion | ||
1873 | * Allowed | ||
1874 | */ | ||
1736 | } | 1875 | } |
1737 | 1876 | ||
1738 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); | 1877 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); |
@@ -1770,7 +1909,8 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1770 | mbx_cmd_t *mcp = &mc; | 1909 | mbx_cmd_t *mcp = &mc; |
1771 | struct qla_hw_data *ha = vha->hw; | 1910 | struct qla_hw_data *ha = vha->hw; |
1772 | 1911 | ||
1773 | ql_dbg(ql_dbg_mbx, vha, 0x1067, "Entered %s.\n", __func__); | 1912 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1067, |
1913 | "Entered %s.\n", __func__); | ||
1774 | 1914 | ||
1775 | mcp->mb[0] = MBC_LOGIN_FABRIC_PORT; | 1915 | mcp->mb[0] = MBC_LOGIN_FABRIC_PORT; |
1776 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | 1916 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
@@ -1818,7 +1958,8 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1818 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); | 1958 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); |
1819 | } else { | 1959 | } else { |
1820 | /*EMPTY*/ | 1960 | /*EMPTY*/ |
1821 | ql_dbg(ql_dbg_mbx, vha, 0x1069, "Done %s.\n", __func__); | 1961 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1069, |
1962 | "Done %s.\n", __func__); | ||
1822 | } | 1963 | } |
1823 | 1964 | ||
1824 | return rval; | 1965 | return rval; |
@@ -1849,7 +1990,8 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
1849 | mbx_cmd_t *mcp = &mc; | 1990 | mbx_cmd_t *mcp = &mc; |
1850 | struct qla_hw_data *ha = vha->hw; | 1991 | struct qla_hw_data *ha = vha->hw; |
1851 | 1992 | ||
1852 | ql_dbg(ql_dbg_mbx, vha, 0x106a, "Entered %s.\n", __func__); | 1993 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106a, |
1994 | "Entered %s.\n", __func__); | ||
1853 | 1995 | ||
1854 | if (IS_FWI2_CAPABLE(ha)) | 1996 | if (IS_FWI2_CAPABLE(ha)) |
1855 | return qla24xx_login_fabric(vha, fcport->loop_id, | 1997 | return qla24xx_login_fabric(vha, fcport->loop_id, |
@@ -1891,7 +2033,8 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
1891 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]); | 2033 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]); |
1892 | } else { | 2034 | } else { |
1893 | /*EMPTY*/ | 2035 | /*EMPTY*/ |
1894 | ql_dbg(ql_dbg_mbx, vha, 0x106c, "Done %s.\n", __func__); | 2036 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106c, |
2037 | "Done %s.\n", __func__); | ||
1895 | } | 2038 | } |
1896 | 2039 | ||
1897 | return (rval); | 2040 | return (rval); |
@@ -1908,7 +2051,8 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1908 | struct req_que *req; | 2051 | struct req_que *req; |
1909 | struct rsp_que *rsp; | 2052 | struct rsp_que *rsp; |
1910 | 2053 | ||
1911 | ql_dbg(ql_dbg_mbx, vha, 0x106d, "Entered %s.\n", __func__); | 2054 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d, |
2055 | "Entered %s.\n", __func__); | ||
1912 | 2056 | ||
1913 | lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); | 2057 | lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); |
1914 | if (lg == NULL) { | 2058 | if (lg == NULL) { |
@@ -1952,7 +2096,8 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1952 | le32_to_cpu(lg->io_parameter[1])); | 2096 | le32_to_cpu(lg->io_parameter[1])); |
1953 | } else { | 2097 | } else { |
1954 | /*EMPTY*/ | 2098 | /*EMPTY*/ |
1955 | ql_dbg(ql_dbg_mbx, vha, 0x1072, "Done %s.\n", __func__); | 2099 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1072, |
2100 | "Done %s.\n", __func__); | ||
1956 | } | 2101 | } |
1957 | 2102 | ||
1958 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); | 2103 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); |
@@ -1984,7 +2129,8 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1984 | mbx_cmd_t mc; | 2129 | mbx_cmd_t mc; |
1985 | mbx_cmd_t *mcp = &mc; | 2130 | mbx_cmd_t *mcp = &mc; |
1986 | 2131 | ||
1987 | ql_dbg(ql_dbg_mbx, vha, 0x1073, "Entered %s.\n", __func__); | 2132 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1073, |
2133 | "Entered %s.\n", __func__); | ||
1988 | 2134 | ||
1989 | mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT; | 2135 | mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT; |
1990 | mcp->out_mb = MBX_1|MBX_0; | 2136 | mcp->out_mb = MBX_1|MBX_0; |
@@ -2007,7 +2153,8 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
2007 | "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]); | 2153 | "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]); |
2008 | } else { | 2154 | } else { |
2009 | /*EMPTY*/ | 2155 | /*EMPTY*/ |
2010 | ql_dbg(ql_dbg_mbx, vha, 0x1075, "Done %s.\n", __func__); | 2156 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1075, |
2157 | "Done %s.\n", __func__); | ||
2011 | } | 2158 | } |
2012 | 2159 | ||
2013 | return rval; | 2160 | return rval; |
@@ -2035,7 +2182,8 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha) | |||
2035 | mbx_cmd_t mc; | 2182 | mbx_cmd_t mc; |
2036 | mbx_cmd_t *mcp = &mc; | 2183 | mbx_cmd_t *mcp = &mc; |
2037 | 2184 | ||
2038 | ql_dbg(ql_dbg_mbx, vha, 0x1076, "Entered %s.\n", __func__); | 2185 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1076, |
2186 | "Entered %s.\n", __func__); | ||
2039 | 2187 | ||
2040 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; | 2188 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; |
2041 | mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0; | 2189 | mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0; |
@@ -2052,7 +2200,8 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha) | |||
2052 | ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval); | 2200 | ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval); |
2053 | } else { | 2201 | } else { |
2054 | /*EMPTY*/ | 2202 | /*EMPTY*/ |
2055 | ql_dbg(ql_dbg_mbx, vha, 0x1078, "Done %s.\n", __func__); | 2203 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1078, |
2204 | "Done %s.\n", __func__); | ||
2056 | } | 2205 | } |
2057 | 2206 | ||
2058 | return rval; | 2207 | return rval; |
@@ -2078,7 +2227,8 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma, | |||
2078 | mbx_cmd_t mc; | 2227 | mbx_cmd_t mc; |
2079 | mbx_cmd_t *mcp = &mc; | 2228 | mbx_cmd_t *mcp = &mc; |
2080 | 2229 | ||
2081 | ql_dbg(ql_dbg_mbx, vha, 0x1079, "Entered %s.\n", __func__); | 2230 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1079, |
2231 | "Entered %s.\n", __func__); | ||
2082 | 2232 | ||
2083 | if (id_list == NULL) | 2233 | if (id_list == NULL) |
2084 | return QLA_FUNCTION_FAILED; | 2234 | return QLA_FUNCTION_FAILED; |
@@ -2110,7 +2260,8 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma, | |||
2110 | ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval); | 2260 | ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval); |
2111 | } else { | 2261 | } else { |
2112 | *entries = mcp->mb[1]; | 2262 | *entries = mcp->mb[1]; |
2113 | ql_dbg(ql_dbg_mbx, vha, 0x107b, "Done %s.\n", __func__); | 2263 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107b, |
2264 | "Done %s.\n", __func__); | ||
2114 | } | 2265 | } |
2115 | 2266 | ||
2116 | return rval; | 2267 | return rval; |
@@ -2138,7 +2289,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | |||
2138 | mbx_cmd_t mc; | 2289 | mbx_cmd_t mc; |
2139 | mbx_cmd_t *mcp = &mc; | 2290 | mbx_cmd_t *mcp = &mc; |
2140 | 2291 | ||
2141 | ql_dbg(ql_dbg_mbx, vha, 0x107c, "Entered %s.\n", __func__); | 2292 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107c, |
2293 | "Entered %s.\n", __func__); | ||
2142 | 2294 | ||
2143 | mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; | 2295 | mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; |
2144 | mcp->out_mb = MBX_0; | 2296 | mcp->out_mb = MBX_0; |
@@ -2154,7 +2306,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | |||
2154 | ql_dbg(ql_dbg_mbx, vha, 0x107d, | 2306 | ql_dbg(ql_dbg_mbx, vha, 0x107d, |
2155 | "Failed mb[0]=%x.\n", mcp->mb[0]); | 2307 | "Failed mb[0]=%x.\n", mcp->mb[0]); |
2156 | } else { | 2308 | } else { |
2157 | ql_dbg(ql_dbg_mbx, vha, 0x107e, | 2309 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107e, |
2158 | "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x " | 2310 | "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x " |
2159 | "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2], | 2311 | "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2], |
2160 | mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10], | 2312 | mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10], |
@@ -2201,7 +2353,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) | |||
2201 | dma_addr_t pmap_dma; | 2353 | dma_addr_t pmap_dma; |
2202 | struct qla_hw_data *ha = vha->hw; | 2354 | struct qla_hw_data *ha = vha->hw; |
2203 | 2355 | ||
2204 | ql_dbg(ql_dbg_mbx, vha, 0x107f, "Entered %s.\n", __func__); | 2356 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f, |
2357 | "Entered %s.\n", __func__); | ||
2205 | 2358 | ||
2206 | pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); | 2359 | pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); |
2207 | if (pmap == NULL) { | 2360 | if (pmap == NULL) { |
@@ -2224,7 +2377,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) | |||
2224 | rval = qla2x00_mailbox_command(vha, mcp); | 2377 | rval = qla2x00_mailbox_command(vha, mcp); |
2225 | 2378 | ||
2226 | if (rval == QLA_SUCCESS) { | 2379 | if (rval == QLA_SUCCESS) { |
2227 | ql_dbg(ql_dbg_mbx, vha, 0x1081, | 2380 | ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1081, |
2228 | "mb0/mb1=%x/%X FC/AL position map size (%x).\n", | 2381 | "mb0/mb1=%x/%X FC/AL position map size (%x).\n", |
2229 | mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]); | 2382 | mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]); |
2230 | ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d, | 2383 | ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d, |
@@ -2238,7 +2391,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) | |||
2238 | if (rval != QLA_SUCCESS) { | 2391 | if (rval != QLA_SUCCESS) { |
2239 | ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval); | 2392 | ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval); |
2240 | } else { | 2393 | } else { |
2241 | ql_dbg(ql_dbg_mbx, vha, 0x1083, "Done %s.\n", __func__); | 2394 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1083, |
2395 | "Done %s.\n", __func__); | ||
2242 | } | 2396 | } |
2243 | 2397 | ||
2244 | return rval; | 2398 | return rval; |
@@ -2267,7 +2421,8 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2267 | uint32_t *siter, *diter, dwords; | 2421 | uint32_t *siter, *diter, dwords; |
2268 | struct qla_hw_data *ha = vha->hw; | 2422 | struct qla_hw_data *ha = vha->hw; |
2269 | 2423 | ||
2270 | ql_dbg(ql_dbg_mbx, vha, 0x1084, "Entered %s.\n", __func__); | 2424 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084, |
2425 | "Entered %s.\n", __func__); | ||
2271 | 2426 | ||
2272 | mcp->mb[0] = MBC_GET_LINK_STATUS; | 2427 | mcp->mb[0] = MBC_GET_LINK_STATUS; |
2273 | mcp->mb[2] = MSW(stats_dma); | 2428 | mcp->mb[2] = MSW(stats_dma); |
@@ -2301,7 +2456,8 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2301 | rval = QLA_FUNCTION_FAILED; | 2456 | rval = QLA_FUNCTION_FAILED; |
2302 | } else { | 2457 | } else { |
2303 | /* Copy over data -- firmware data is LE. */ | 2458 | /* Copy over data -- firmware data is LE. */ |
2304 | ql_dbg(ql_dbg_mbx, vha, 0x1086, "Done %s.\n", __func__); | 2459 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086, |
2460 | "Done %s.\n", __func__); | ||
2305 | dwords = offsetof(struct link_statistics, unused1) / 4; | 2461 | dwords = offsetof(struct link_statistics, unused1) / 4; |
2306 | siter = diter = &stats->link_fail_cnt; | 2462 | siter = diter = &stats->link_fail_cnt; |
2307 | while (dwords--) | 2463 | while (dwords--) |
@@ -2324,7 +2480,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, | |||
2324 | mbx_cmd_t *mcp = &mc; | 2480 | mbx_cmd_t *mcp = &mc; |
2325 | uint32_t *siter, *diter, dwords; | 2481 | uint32_t *siter, *diter, dwords; |
2326 | 2482 | ||
2327 | ql_dbg(ql_dbg_mbx, vha, 0x1088, "Entered %s.\n", __func__); | 2483 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, |
2484 | "Entered %s.\n", __func__); | ||
2328 | 2485 | ||
2329 | mcp->mb[0] = MBC_GET_LINK_PRIV_STATS; | 2486 | mcp->mb[0] = MBC_GET_LINK_PRIV_STATS; |
2330 | mcp->mb[2] = MSW(stats_dma); | 2487 | mcp->mb[2] = MSW(stats_dma); |
@@ -2346,7 +2503,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, | |||
2346 | "Failed mb[0]=%x.\n", mcp->mb[0]); | 2503 | "Failed mb[0]=%x.\n", mcp->mb[0]); |
2347 | rval = QLA_FUNCTION_FAILED; | 2504 | rval = QLA_FUNCTION_FAILED; |
2348 | } else { | 2505 | } else { |
2349 | ql_dbg(ql_dbg_mbx, vha, 0x108a, "Done %s.\n", __func__); | 2506 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, |
2507 | "Done %s.\n", __func__); | ||
2350 | /* Copy over data -- firmware data is LE. */ | 2508 | /* Copy over data -- firmware data is LE. */ |
2351 | dwords = sizeof(struct link_statistics) / 4; | 2509 | dwords = sizeof(struct link_statistics) / 4; |
2352 | siter = diter = &stats->link_fail_cnt; | 2510 | siter = diter = &stats->link_fail_cnt; |
@@ -2375,7 +2533,8 @@ qla24xx_abort_command(srb_t *sp) | |||
2375 | struct qla_hw_data *ha = vha->hw; | 2533 | struct qla_hw_data *ha = vha->hw; |
2376 | struct req_que *req = vha->req; | 2534 | struct req_que *req = vha->req; |
2377 | 2535 | ||
2378 | ql_dbg(ql_dbg_mbx, vha, 0x108c, "Entered %s.\n", __func__); | 2536 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c, |
2537 | "Entered %s.\n", __func__); | ||
2379 | 2538 | ||
2380 | spin_lock_irqsave(&ha->hardware_lock, flags); | 2539 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2381 | for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { | 2540 | for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { |
@@ -2404,7 +2563,7 @@ qla24xx_abort_command(srb_t *sp) | |||
2404 | abt->port_id[0] = fcport->d_id.b.al_pa; | 2563 | abt->port_id[0] = fcport->d_id.b.al_pa; |
2405 | abt->port_id[1] = fcport->d_id.b.area; | 2564 | abt->port_id[1] = fcport->d_id.b.area; |
2406 | abt->port_id[2] = fcport->d_id.b.domain; | 2565 | abt->port_id[2] = fcport->d_id.b.domain; |
2407 | abt->vp_index = fcport->vp_idx; | 2566 | abt->vp_index = fcport->vha->vp_idx; |
2408 | 2567 | ||
2409 | abt->req_que_no = cpu_to_le16(req->id); | 2568 | abt->req_que_no = cpu_to_le16(req->id); |
2410 | 2569 | ||
@@ -2423,7 +2582,8 @@ qla24xx_abort_command(srb_t *sp) | |||
2423 | le16_to_cpu(abt->nport_handle)); | 2582 | le16_to_cpu(abt->nport_handle)); |
2424 | rval = QLA_FUNCTION_FAILED; | 2583 | rval = QLA_FUNCTION_FAILED; |
2425 | } else { | 2584 | } else { |
2426 | ql_dbg(ql_dbg_mbx, vha, 0x1091, "Done %s.\n", __func__); | 2585 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091, |
2586 | "Done %s.\n", __func__); | ||
2427 | } | 2587 | } |
2428 | 2588 | ||
2429 | dma_pool_free(ha->s_dma_pool, abt, abt_dma); | 2589 | dma_pool_free(ha->s_dma_pool, abt, abt_dma); |
@@ -2455,7 +2615,8 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2455 | ha = vha->hw; | 2615 | ha = vha->hw; |
2456 | req = vha->req; | 2616 | req = vha->req; |
2457 | 2617 | ||
2458 | ql_dbg(ql_dbg_mbx, vha, 0x1092, "Entered %s.\n", __func__); | 2618 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1092, |
2619 | "Entered %s.\n", __func__); | ||
2459 | 2620 | ||
2460 | if (ha->flags.cpu_affinity_enabled) | 2621 | if (ha->flags.cpu_affinity_enabled) |
2461 | rsp = ha->rsp_q_map[tag + 1]; | 2622 | rsp = ha->rsp_q_map[tag + 1]; |
@@ -2478,7 +2639,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2478 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; | 2639 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; |
2479 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; | 2640 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; |
2480 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; | 2641 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; |
2481 | tsk->p.tsk.vp_index = fcport->vp_idx; | 2642 | tsk->p.tsk.vp_index = fcport->vha->vp_idx; |
2482 | if (type == TCF_LUN_RESET) { | 2643 | if (type == TCF_LUN_RESET) { |
2483 | int_to_scsilun(l, &tsk->p.tsk.lun); | 2644 | int_to_scsilun(l, &tsk->p.tsk.lun); |
2484 | host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun, | 2645 | host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun, |
@@ -2504,7 +2665,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2504 | } else if (le16_to_cpu(sts->scsi_status) & | 2665 | } else if (le16_to_cpu(sts->scsi_status) & |
2505 | SS_RESPONSE_INFO_LEN_VALID) { | 2666 | SS_RESPONSE_INFO_LEN_VALID) { |
2506 | if (le32_to_cpu(sts->rsp_data_len) < 4) { | 2667 | if (le32_to_cpu(sts->rsp_data_len) < 4) { |
2507 | ql_dbg(ql_dbg_mbx, vha, 0x1097, | 2668 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1097, |
2508 | "Ignoring inconsistent data length -- not enough " | 2669 | "Ignoring inconsistent data length -- not enough " |
2509 | "response info (%d).\n", | 2670 | "response info (%d).\n", |
2510 | le32_to_cpu(sts->rsp_data_len)); | 2671 | le32_to_cpu(sts->rsp_data_len)); |
@@ -2523,7 +2684,8 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2523 | ql_dbg(ql_dbg_mbx, vha, 0x1099, | 2684 | ql_dbg(ql_dbg_mbx, vha, 0x1099, |
2524 | "Failed to issue marker IOCB (%x).\n", rval2); | 2685 | "Failed to issue marker IOCB (%x).\n", rval2); |
2525 | } else { | 2686 | } else { |
2526 | ql_dbg(ql_dbg_mbx, vha, 0x109a, "Done %s.\n", __func__); | 2687 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109a, |
2688 | "Done %s.\n", __func__); | ||
2527 | } | 2689 | } |
2528 | 2690 | ||
2529 | dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); | 2691 | dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); |
@@ -2564,7 +2726,8 @@ qla2x00_system_error(scsi_qla_host_t *vha) | |||
2564 | if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha)) | 2726 | if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha)) |
2565 | return QLA_FUNCTION_FAILED; | 2727 | return QLA_FUNCTION_FAILED; |
2566 | 2728 | ||
2567 | ql_dbg(ql_dbg_mbx, vha, 0x109b, "Entered %s.\n", __func__); | 2729 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109b, |
2730 | "Entered %s.\n", __func__); | ||
2568 | 2731 | ||
2569 | mcp->mb[0] = MBC_GEN_SYSTEM_ERROR; | 2732 | mcp->mb[0] = MBC_GEN_SYSTEM_ERROR; |
2570 | mcp->out_mb = MBX_0; | 2733 | mcp->out_mb = MBX_0; |
@@ -2576,7 +2739,8 @@ qla2x00_system_error(scsi_qla_host_t *vha) | |||
2576 | if (rval != QLA_SUCCESS) { | 2739 | if (rval != QLA_SUCCESS) { |
2577 | ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval); | 2740 | ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval); |
2578 | } else { | 2741 | } else { |
2579 | ql_dbg(ql_dbg_mbx, vha, 0x109d, "Done %s.\n", __func__); | 2742 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109d, |
2743 | "Done %s.\n", __func__); | ||
2580 | } | 2744 | } |
2581 | 2745 | ||
2582 | return rval; | 2746 | return rval; |
@@ -2596,7 +2760,8 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g, | |||
2596 | mbx_cmd_t mc; | 2760 | mbx_cmd_t mc; |
2597 | mbx_cmd_t *mcp = &mc; | 2761 | mbx_cmd_t *mcp = &mc; |
2598 | 2762 | ||
2599 | ql_dbg(ql_dbg_mbx, vha, 0x109e, "Entered %s.\n", __func__); | 2763 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109e, |
2764 | "Entered %s.\n", __func__); | ||
2600 | 2765 | ||
2601 | mcp->mb[0] = MBC_SERDES_PARAMS; | 2766 | mcp->mb[0] = MBC_SERDES_PARAMS; |
2602 | mcp->mb[1] = BIT_0; | 2767 | mcp->mb[1] = BIT_0; |
@@ -2615,7 +2780,8 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g, | |||
2615 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 2780 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
2616 | } else { | 2781 | } else { |
2617 | /*EMPTY*/ | 2782 | /*EMPTY*/ |
2618 | ql_dbg(ql_dbg_mbx, vha, 0x10a0, "Done %s.\n", __func__); | 2783 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a0, |
2784 | "Done %s.\n", __func__); | ||
2619 | } | 2785 | } |
2620 | 2786 | ||
2621 | return rval; | 2787 | return rval; |
@@ -2631,7 +2797,8 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha) | |||
2631 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2797 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2632 | return QLA_FUNCTION_FAILED; | 2798 | return QLA_FUNCTION_FAILED; |
2633 | 2799 | ||
2634 | ql_dbg(ql_dbg_mbx, vha, 0x10a1, "Entered %s.\n", __func__); | 2800 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a1, |
2801 | "Entered %s.\n", __func__); | ||
2635 | 2802 | ||
2636 | mcp->mb[0] = MBC_STOP_FIRMWARE; | 2803 | mcp->mb[0] = MBC_STOP_FIRMWARE; |
2637 | mcp->mb[1] = 0; | 2804 | mcp->mb[1] = 0; |
@@ -2646,7 +2813,8 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha) | |||
2646 | if (mcp->mb[0] == MBS_INVALID_COMMAND) | 2813 | if (mcp->mb[0] == MBS_INVALID_COMMAND) |
2647 | rval = QLA_INVALID_COMMAND; | 2814 | rval = QLA_INVALID_COMMAND; |
2648 | } else { | 2815 | } else { |
2649 | ql_dbg(ql_dbg_mbx, vha, 0x10a3, "Done %s.\n", __func__); | 2816 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a3, |
2817 | "Done %s.\n", __func__); | ||
2650 | } | 2818 | } |
2651 | 2819 | ||
2652 | return rval; | 2820 | return rval; |
@@ -2660,7 +2828,8 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, | |||
2660 | mbx_cmd_t mc; | 2828 | mbx_cmd_t mc; |
2661 | mbx_cmd_t *mcp = &mc; | 2829 | mbx_cmd_t *mcp = &mc; |
2662 | 2830 | ||
2663 | ql_dbg(ql_dbg_mbx, vha, 0x10a4, "Entered %s.\n", __func__); | 2831 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a4, |
2832 | "Entered %s.\n", __func__); | ||
2664 | 2833 | ||
2665 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2834 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2666 | return QLA_FUNCTION_FAILED; | 2835 | return QLA_FUNCTION_FAILED; |
@@ -2686,7 +2855,8 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, | |||
2686 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 2855 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
2687 | rval, mcp->mb[0], mcp->mb[1]); | 2856 | rval, mcp->mb[0], mcp->mb[1]); |
2688 | } else { | 2857 | } else { |
2689 | ql_dbg(ql_dbg_mbx, vha, 0x10a6, "Done %s.\n", __func__); | 2858 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a6, |
2859 | "Done %s.\n", __func__); | ||
2690 | } | 2860 | } |
2691 | 2861 | ||
2692 | return rval; | 2862 | return rval; |
@@ -2699,7 +2869,8 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha) | |||
2699 | mbx_cmd_t mc; | 2869 | mbx_cmd_t mc; |
2700 | mbx_cmd_t *mcp = &mc; | 2870 | mbx_cmd_t *mcp = &mc; |
2701 | 2871 | ||
2702 | ql_dbg(ql_dbg_mbx, vha, 0x10a7, "Entered %s.\n", __func__); | 2872 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a7, |
2873 | "Entered %s.\n", __func__); | ||
2703 | 2874 | ||
2704 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2875 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2705 | return QLA_FUNCTION_FAILED; | 2876 | return QLA_FUNCTION_FAILED; |
@@ -2719,7 +2890,8 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha) | |||
2719 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 2890 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
2720 | rval, mcp->mb[0], mcp->mb[1]); | 2891 | rval, mcp->mb[0], mcp->mb[1]); |
2721 | } else { | 2892 | } else { |
2722 | ql_dbg(ql_dbg_mbx, vha, 0x10a9, "Done %s.\n", __func__); | 2893 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a9, |
2894 | "Done %s.\n", __func__); | ||
2723 | } | 2895 | } |
2724 | 2896 | ||
2725 | return rval; | 2897 | return rval; |
@@ -2733,7 +2905,8 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, | |||
2733 | mbx_cmd_t mc; | 2905 | mbx_cmd_t mc; |
2734 | mbx_cmd_t *mcp = &mc; | 2906 | mbx_cmd_t *mcp = &mc; |
2735 | 2907 | ||
2736 | ql_dbg(ql_dbg_mbx, vha, 0x10aa, "Entered %s.\n", __func__); | 2908 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10aa, |
2909 | "Entered %s.\n", __func__); | ||
2737 | 2910 | ||
2738 | if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && | 2911 | if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && |
2739 | !IS_QLA83XX(vha->hw)) | 2912 | !IS_QLA83XX(vha->hw)) |
@@ -2764,7 +2937,8 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, | |||
2764 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 2937 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
2765 | rval, mcp->mb[0], mcp->mb[1]); | 2938 | rval, mcp->mb[0], mcp->mb[1]); |
2766 | } else { | 2939 | } else { |
2767 | ql_dbg(ql_dbg_mbx, vha, 0x10ac, "Done %s.\n", __func__); | 2940 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ac, |
2941 | "Done %s.\n", __func__); | ||
2768 | 2942 | ||
2769 | if (mb) | 2943 | if (mb) |
2770 | memcpy(mb, mcp->mb, 8 * sizeof(*mb)); | 2944 | memcpy(mb, mcp->mb, 8 * sizeof(*mb)); |
@@ -2782,7 +2956,8 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) | |||
2782 | mbx_cmd_t mc; | 2956 | mbx_cmd_t mc; |
2783 | mbx_cmd_t *mcp = &mc; | 2957 | mbx_cmd_t *mcp = &mc; |
2784 | 2958 | ||
2785 | ql_dbg(ql_dbg_mbx, vha, 0x10ad, "Entered %s.\n", __func__); | 2959 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ad, |
2960 | "Entered %s.\n", __func__); | ||
2786 | 2961 | ||
2787 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2962 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2788 | return QLA_FUNCTION_FAILED; | 2963 | return QLA_FUNCTION_FAILED; |
@@ -2804,7 +2979,8 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) | |||
2804 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 2979 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
2805 | rval, mcp->mb[0], mcp->mb[1]); | 2980 | rval, mcp->mb[0], mcp->mb[1]); |
2806 | } else { | 2981 | } else { |
2807 | ql_dbg(ql_dbg_mbx, vha, 0x10af, "Done %s.\n", __func__); | 2982 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10af, |
2983 | "Done %s.\n", __func__); | ||
2808 | 2984 | ||
2809 | if (wr) | 2985 | if (wr) |
2810 | *wr = (uint64_t) mcp->mb[5] << 48 | | 2986 | *wr = (uint64_t) mcp->mb[5] << 48 | |
@@ -2829,7 +3005,8 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2829 | mbx_cmd_t mc; | 3005 | mbx_cmd_t mc; |
2830 | mbx_cmd_t *mcp = &mc; | 3006 | mbx_cmd_t *mcp = &mc; |
2831 | 3007 | ||
2832 | ql_dbg(ql_dbg_mbx, vha, 0x10b0, "Entered %s.\n", __func__); | 3008 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b0, |
3009 | "Entered %s.\n", __func__); | ||
2833 | 3010 | ||
2834 | if (!IS_IIDMA_CAPABLE(vha->hw)) | 3011 | if (!IS_IIDMA_CAPABLE(vha->hw)) |
2835 | return QLA_FUNCTION_FAILED; | 3012 | return QLA_FUNCTION_FAILED; |
@@ -2854,7 +3031,8 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2854 | if (rval != QLA_SUCCESS) { | 3031 | if (rval != QLA_SUCCESS) { |
2855 | ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval); | 3032 | ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval); |
2856 | } else { | 3033 | } else { |
2857 | ql_dbg(ql_dbg_mbx, vha, 0x10b2, "Done %s.\n", __func__); | 3034 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b2, |
3035 | "Done %s.\n", __func__); | ||
2858 | if (port_speed) | 3036 | if (port_speed) |
2859 | *port_speed = mcp->mb[3]; | 3037 | *port_speed = mcp->mb[3]; |
2860 | } | 3038 | } |
@@ -2870,7 +3048,8 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2870 | mbx_cmd_t mc; | 3048 | mbx_cmd_t mc; |
2871 | mbx_cmd_t *mcp = &mc; | 3049 | mbx_cmd_t *mcp = &mc; |
2872 | 3050 | ||
2873 | ql_dbg(ql_dbg_mbx, vha, 0x10b3, "Entered %s.\n", __func__); | 3051 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b3, |
3052 | "Entered %s.\n", __func__); | ||
2874 | 3053 | ||
2875 | if (!IS_IIDMA_CAPABLE(vha->hw)) | 3054 | if (!IS_IIDMA_CAPABLE(vha->hw)) |
2876 | return QLA_FUNCTION_FAILED; | 3055 | return QLA_FUNCTION_FAILED; |
@@ -2897,9 +3076,11 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2897 | } | 3076 | } |
2898 | 3077 | ||
2899 | if (rval != QLA_SUCCESS) { | 3078 | if (rval != QLA_SUCCESS) { |
2900 | ql_dbg(ql_dbg_mbx, vha, 0x10b4, "Failed=%x.\n", rval); | 3079 | ql_dbg(ql_dbg_mbx, vha, 0x10b4, |
3080 | "Failed=%x.\n", rval); | ||
2901 | } else { | 3081 | } else { |
2902 | ql_dbg(ql_dbg_mbx, vha, 0x10b5, "Done %s.\n", __func__); | 3082 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b5, |
3083 | "Done %s.\n", __func__); | ||
2903 | } | 3084 | } |
2904 | 3085 | ||
2905 | return rval; | 3086 | return rval; |
@@ -2915,24 +3096,25 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
2915 | scsi_qla_host_t *vp; | 3096 | scsi_qla_host_t *vp; |
2916 | unsigned long flags; | 3097 | unsigned long flags; |
2917 | 3098 | ||
2918 | ql_dbg(ql_dbg_mbx, vha, 0x10b6, "Entered %s.\n", __func__); | 3099 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6, |
3100 | "Entered %s.\n", __func__); | ||
2919 | 3101 | ||
2920 | if (rptid_entry->entry_status != 0) | 3102 | if (rptid_entry->entry_status != 0) |
2921 | return; | 3103 | return; |
2922 | 3104 | ||
2923 | if (rptid_entry->format == 0) { | 3105 | if (rptid_entry->format == 0) { |
2924 | ql_dbg(ql_dbg_mbx, vha, 0x10b7, | 3106 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7, |
2925 | "Format 0 : Number of VPs setup %d, number of " | 3107 | "Format 0 : Number of VPs setup %d, number of " |
2926 | "VPs acquired %d.\n", | 3108 | "VPs acquired %d.\n", |
2927 | MSB(le16_to_cpu(rptid_entry->vp_count)), | 3109 | MSB(le16_to_cpu(rptid_entry->vp_count)), |
2928 | LSB(le16_to_cpu(rptid_entry->vp_count))); | 3110 | LSB(le16_to_cpu(rptid_entry->vp_count))); |
2929 | ql_dbg(ql_dbg_mbx, vha, 0x10b8, | 3111 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8, |
2930 | "Primary port id %02x%02x%02x.\n", | 3112 | "Primary port id %02x%02x%02x.\n", |
2931 | rptid_entry->port_id[2], rptid_entry->port_id[1], | 3113 | rptid_entry->port_id[2], rptid_entry->port_id[1], |
2932 | rptid_entry->port_id[0]); | 3114 | rptid_entry->port_id[0]); |
2933 | } else if (rptid_entry->format == 1) { | 3115 | } else if (rptid_entry->format == 1) { |
2934 | vp_idx = LSB(stat); | 3116 | vp_idx = LSB(stat); |
2935 | ql_dbg(ql_dbg_mbx, vha, 0x10b9, | 3117 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9, |
2936 | "Format 1: VP[%d] enabled - status %d - with " | 3118 | "Format 1: VP[%d] enabled - status %d - with " |
2937 | "port id %02x%02x%02x.\n", vp_idx, MSB(stat), | 3119 | "port id %02x%02x%02x.\n", vp_idx, MSB(stat), |
2938 | rptid_entry->port_id[2], rptid_entry->port_id[1], | 3120 | rptid_entry->port_id[2], rptid_entry->port_id[1], |
@@ -2999,7 +3181,8 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) | |||
2999 | 3181 | ||
3000 | /* This can be called by the parent */ | 3182 | /* This can be called by the parent */ |
3001 | 3183 | ||
3002 | ql_dbg(ql_dbg_mbx, vha, 0x10bb, "Entered %s.\n", __func__); | 3184 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb, |
3185 | "Entered %s.\n", __func__); | ||
3003 | 3186 | ||
3004 | vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma); | 3187 | vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma); |
3005 | if (!vpmod) { | 3188 | if (!vpmod) { |
@@ -3015,6 +3198,9 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) | |||
3015 | vpmod->vp_count = 1; | 3198 | vpmod->vp_count = 1; |
3016 | vpmod->vp_index1 = vha->vp_idx; | 3199 | vpmod->vp_index1 = vha->vp_idx; |
3017 | vpmod->options_idx1 = BIT_3|BIT_4|BIT_5; | 3200 | vpmod->options_idx1 = BIT_3|BIT_4|BIT_5; |
3201 | |||
3202 | qlt_modify_vp_config(vha, vpmod); | ||
3203 | |||
3018 | memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE); | 3204 | memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE); |
3019 | memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE); | 3205 | memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE); |
3020 | vpmod->entry_count = 1; | 3206 | vpmod->entry_count = 1; |
@@ -3035,7 +3221,8 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) | |||
3035 | rval = QLA_FUNCTION_FAILED; | 3221 | rval = QLA_FUNCTION_FAILED; |
3036 | } else { | 3222 | } else { |
3037 | /* EMPTY */ | 3223 | /* EMPTY */ |
3038 | ql_dbg(ql_dbg_mbx, vha, 0x10c0, "Done %s.\n", __func__); | 3224 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c0, |
3225 | "Done %s.\n", __func__); | ||
3039 | fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING); | 3226 | fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING); |
3040 | } | 3227 | } |
3041 | dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma); | 3228 | dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma); |
@@ -3069,7 +3256,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) | |||
3069 | int vp_index = vha->vp_idx; | 3256 | int vp_index = vha->vp_idx; |
3070 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 3257 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
3071 | 3258 | ||
3072 | ql_dbg(ql_dbg_mbx, vha, 0x10c1, | 3259 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c1, |
3073 | "Entered %s enabling index %d.\n", __func__, vp_index); | 3260 | "Entered %s enabling index %d.\n", __func__, vp_index); |
3074 | 3261 | ||
3075 | if (vp_index == 0 || vp_index >= ha->max_npiv_vports) | 3262 | if (vp_index == 0 || vp_index >= ha->max_npiv_vports) |
@@ -3112,7 +3299,8 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) | |||
3112 | le16_to_cpu(vce->comp_status)); | 3299 | le16_to_cpu(vce->comp_status)); |
3113 | rval = QLA_FUNCTION_FAILED; | 3300 | rval = QLA_FUNCTION_FAILED; |
3114 | } else { | 3301 | } else { |
3115 | ql_dbg(ql_dbg_mbx, vha, 0x10c6, "Done %s.\n", __func__); | 3302 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c6, |
3303 | "Done %s.\n", __func__); | ||
3116 | } | 3304 | } |
3117 | 3305 | ||
3118 | dma_pool_free(ha->s_dma_pool, vce, vce_dma); | 3306 | dma_pool_free(ha->s_dma_pool, vce, vce_dma); |
@@ -3149,14 +3337,8 @@ qla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format, | |||
3149 | mbx_cmd_t mc; | 3337 | mbx_cmd_t mc; |
3150 | mbx_cmd_t *mcp = &mc; | 3338 | mbx_cmd_t *mcp = &mc; |
3151 | 3339 | ||
3152 | ql_dbg(ql_dbg_mbx, vha, 0x10c7, "Entered %s.\n", __func__); | 3340 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7, |
3153 | 3341 | "Entered %s.\n", __func__); | |
3154 | /* | ||
3155 | * This command is implicitly executed by firmware during login for the | ||
3156 | * physical hosts | ||
3157 | */ | ||
3158 | if (vp_idx == 0) | ||
3159 | return QLA_FUNCTION_FAILED; | ||
3160 | 3342 | ||
3161 | mcp->mb[0] = MBC_SEND_CHANGE_REQUEST; | 3343 | mcp->mb[0] = MBC_SEND_CHANGE_REQUEST; |
3162 | mcp->mb[1] = format; | 3344 | mcp->mb[1] = format; |
@@ -3185,7 +3367,8 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, | |||
3185 | mbx_cmd_t mc; | 3367 | mbx_cmd_t mc; |
3186 | mbx_cmd_t *mcp = &mc; | 3368 | mbx_cmd_t *mcp = &mc; |
3187 | 3369 | ||
3188 | ql_dbg(ql_dbg_mbx, vha, 0x1009, "Entered %s.\n", __func__); | 3370 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1009, |
3371 | "Entered %s.\n", __func__); | ||
3189 | 3372 | ||
3190 | if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) { | 3373 | if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) { |
3191 | mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; | 3374 | mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; |
@@ -3219,7 +3402,8 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, | |||
3219 | ql_dbg(ql_dbg_mbx, vha, 0x1008, | 3402 | ql_dbg(ql_dbg_mbx, vha, 0x1008, |
3220 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 3403 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3221 | } else { | 3404 | } else { |
3222 | ql_dbg(ql_dbg_mbx, vha, 0x1007, "Done %s.\n", __func__); | 3405 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1007, |
3406 | "Done %s.\n", __func__); | ||
3223 | } | 3407 | } |
3224 | 3408 | ||
3225 | return rval; | 3409 | return rval; |
@@ -3244,7 +3428,8 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) | |||
3244 | unsigned long flags; | 3428 | unsigned long flags; |
3245 | struct qla_hw_data *ha = vha->hw; | 3429 | struct qla_hw_data *ha = vha->hw; |
3246 | 3430 | ||
3247 | ql_dbg(ql_dbg_mbx, vha, 0x10c8, "Entered %s.\n", __func__); | 3431 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c8, |
3432 | "Entered %s.\n", __func__); | ||
3248 | 3433 | ||
3249 | mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); | 3434 | mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); |
3250 | if (mn == NULL) { | 3435 | if (mn == NULL) { |
@@ -3285,7 +3470,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) | |||
3285 | status[0] = le16_to_cpu(mn->p.rsp.comp_status); | 3470 | status[0] = le16_to_cpu(mn->p.rsp.comp_status); |
3286 | status[1] = status[0] == CS_VCS_CHIP_FAILURE ? | 3471 | status[1] = status[0] == CS_VCS_CHIP_FAILURE ? |
3287 | le16_to_cpu(mn->p.rsp.failure_code) : 0; | 3472 | le16_to_cpu(mn->p.rsp.failure_code) : 0; |
3288 | ql_dbg(ql_dbg_mbx, vha, 0x10ce, | 3473 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ce, |
3289 | "cs=%x fc=%x.\n", status[0], status[1]); | 3474 | "cs=%x fc=%x.\n", status[0], status[1]); |
3290 | 3475 | ||
3291 | if (status[0] != CS_COMPLETE) { | 3476 | if (status[0] != CS_COMPLETE) { |
@@ -3299,7 +3484,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) | |||
3299 | retry = 1; | 3484 | retry = 1; |
3300 | } | 3485 | } |
3301 | } else { | 3486 | } else { |
3302 | ql_dbg(ql_dbg_mbx, vha, 0x10d0, | 3487 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d0, |
3303 | "Firmware updated to %x.\n", | 3488 | "Firmware updated to %x.\n", |
3304 | le32_to_cpu(mn->p.rsp.fw_ver)); | 3489 | le32_to_cpu(mn->p.rsp.fw_ver)); |
3305 | 3490 | ||
@@ -3316,9 +3501,11 @@ verify_done: | |||
3316 | dma_pool_free(ha->s_dma_pool, mn, mn_dma); | 3501 | dma_pool_free(ha->s_dma_pool, mn, mn_dma); |
3317 | 3502 | ||
3318 | if (rval != QLA_SUCCESS) { | 3503 | if (rval != QLA_SUCCESS) { |
3319 | ql_dbg(ql_dbg_mbx, vha, 0x10d1, "Failed=%x.\n", rval); | 3504 | ql_dbg(ql_dbg_mbx, vha, 0x10d1, |
3505 | "Failed=%x.\n", rval); | ||
3320 | } else { | 3506 | } else { |
3321 | ql_dbg(ql_dbg_mbx, vha, 0x10d2, "Done %s.\n", __func__); | 3507 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d2, |
3508 | "Done %s.\n", __func__); | ||
3322 | } | 3509 | } |
3323 | 3510 | ||
3324 | return rval; | 3511 | return rval; |
@@ -3334,7 +3521,8 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) | |||
3334 | struct device_reg_25xxmq __iomem *reg; | 3521 | struct device_reg_25xxmq __iomem *reg; |
3335 | struct qla_hw_data *ha = vha->hw; | 3522 | struct qla_hw_data *ha = vha->hw; |
3336 | 3523 | ||
3337 | ql_dbg(ql_dbg_mbx, vha, 0x10d3, "Entered %s.\n", __func__); | 3524 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d3, |
3525 | "Entered %s.\n", __func__); | ||
3338 | 3526 | ||
3339 | mcp->mb[0] = MBC_INITIALIZE_MULTIQ; | 3527 | mcp->mb[0] = MBC_INITIALIZE_MULTIQ; |
3340 | mcp->mb[1] = req->options; | 3528 | mcp->mb[1] = req->options; |
@@ -3388,7 +3576,8 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) | |||
3388 | ql_dbg(ql_dbg_mbx, vha, 0x10d4, | 3576 | ql_dbg(ql_dbg_mbx, vha, 0x10d4, |
3389 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 3577 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3390 | } else { | 3578 | } else { |
3391 | ql_dbg(ql_dbg_mbx, vha, 0x10d5, "Done %s.\n", __func__); | 3579 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d5, |
3580 | "Done %s.\n", __func__); | ||
3392 | } | 3581 | } |
3393 | 3582 | ||
3394 | return rval; | 3583 | return rval; |
@@ -3404,7 +3593,8 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) | |||
3404 | struct device_reg_25xxmq __iomem *reg; | 3593 | struct device_reg_25xxmq __iomem *reg; |
3405 | struct qla_hw_data *ha = vha->hw; | 3594 | struct qla_hw_data *ha = vha->hw; |
3406 | 3595 | ||
3407 | ql_dbg(ql_dbg_mbx, vha, 0x10d6, "Entered %s.\n", __func__); | 3596 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d6, |
3597 | "Entered %s.\n", __func__); | ||
3408 | 3598 | ||
3409 | mcp->mb[0] = MBC_INITIALIZE_MULTIQ; | 3599 | mcp->mb[0] = MBC_INITIALIZE_MULTIQ; |
3410 | mcp->mb[1] = rsp->options; | 3600 | mcp->mb[1] = rsp->options; |
@@ -3456,7 +3646,8 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) | |||
3456 | ql_dbg(ql_dbg_mbx, vha, 0x10d7, | 3646 | ql_dbg(ql_dbg_mbx, vha, 0x10d7, |
3457 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 3647 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3458 | } else { | 3648 | } else { |
3459 | ql_dbg(ql_dbg_mbx, vha, 0x10d8, "Done %s.\n", __func__); | 3649 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d8, |
3650 | "Done %s.\n", __func__); | ||
3460 | } | 3651 | } |
3461 | 3652 | ||
3462 | return rval; | 3653 | return rval; |
@@ -3469,7 +3660,8 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb) | |||
3469 | mbx_cmd_t mc; | 3660 | mbx_cmd_t mc; |
3470 | mbx_cmd_t *mcp = &mc; | 3661 | mbx_cmd_t *mcp = &mc; |
3471 | 3662 | ||
3472 | ql_dbg(ql_dbg_mbx, vha, 0x10d9, "Entered %s.\n", __func__); | 3663 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d9, |
3664 | "Entered %s.\n", __func__); | ||
3473 | 3665 | ||
3474 | mcp->mb[0] = MBC_IDC_ACK; | 3666 | mcp->mb[0] = MBC_IDC_ACK; |
3475 | memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t)); | 3667 | memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t)); |
@@ -3483,7 +3675,8 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb) | |||
3483 | ql_dbg(ql_dbg_mbx, vha, 0x10da, | 3675 | ql_dbg(ql_dbg_mbx, vha, 0x10da, |
3484 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 3676 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3485 | } else { | 3677 | } else { |
3486 | ql_dbg(ql_dbg_mbx, vha, 0x10db, "Done %s.\n", __func__); | 3678 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10db, |
3679 | "Done %s.\n", __func__); | ||
3487 | } | 3680 | } |
3488 | 3681 | ||
3489 | return rval; | 3682 | return rval; |
@@ -3496,7 +3689,8 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) | |||
3496 | mbx_cmd_t mc; | 3689 | mbx_cmd_t mc; |
3497 | mbx_cmd_t *mcp = &mc; | 3690 | mbx_cmd_t *mcp = &mc; |
3498 | 3691 | ||
3499 | ql_dbg(ql_dbg_mbx, vha, 0x10dc, "Entered %s.\n", __func__); | 3692 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10dc, |
3693 | "Entered %s.\n", __func__); | ||
3500 | 3694 | ||
3501 | if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) | 3695 | if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) |
3502 | return QLA_FUNCTION_FAILED; | 3696 | return QLA_FUNCTION_FAILED; |
@@ -3514,7 +3708,8 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) | |||
3514 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 3708 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
3515 | rval, mcp->mb[0], mcp->mb[1]); | 3709 | rval, mcp->mb[0], mcp->mb[1]); |
3516 | } else { | 3710 | } else { |
3517 | ql_dbg(ql_dbg_mbx, vha, 0x10de, "Done %s.\n", __func__); | 3711 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10de, |
3712 | "Done %s.\n", __func__); | ||
3518 | *sector_size = mcp->mb[1]; | 3713 | *sector_size = mcp->mb[1]; |
3519 | } | 3714 | } |
3520 | 3715 | ||
@@ -3531,7 +3726,8 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) | |||
3531 | if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) | 3726 | if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) |
3532 | return QLA_FUNCTION_FAILED; | 3727 | return QLA_FUNCTION_FAILED; |
3533 | 3728 | ||
3534 | ql_dbg(ql_dbg_mbx, vha, 0x10df, "Entered %s.\n", __func__); | 3729 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df, |
3730 | "Entered %s.\n", __func__); | ||
3535 | 3731 | ||
3536 | mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; | 3732 | mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; |
3537 | mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE : | 3733 | mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE : |
@@ -3547,7 +3743,8 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) | |||
3547 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 3743 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
3548 | rval, mcp->mb[0], mcp->mb[1]); | 3744 | rval, mcp->mb[0], mcp->mb[1]); |
3549 | } else { | 3745 | } else { |
3550 | ql_dbg(ql_dbg_mbx, vha, 0x10e1, "Done %s.\n", __func__); | 3746 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e1, |
3747 | "Done %s.\n", __func__); | ||
3551 | } | 3748 | } |
3552 | 3749 | ||
3553 | return rval; | 3750 | return rval; |
@@ -3563,7 +3760,8 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) | |||
3563 | if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) | 3760 | if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) |
3564 | return QLA_FUNCTION_FAILED; | 3761 | return QLA_FUNCTION_FAILED; |
3565 | 3762 | ||
3566 | ql_dbg(ql_dbg_mbx, vha, 0x10e2, "Entered %s.\n", __func__); | 3763 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, |
3764 | "Entered %s.\n", __func__); | ||
3567 | 3765 | ||
3568 | mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; | 3766 | mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; |
3569 | mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR; | 3767 | mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR; |
@@ -3582,7 +3780,8 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) | |||
3582 | "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", | 3780 | "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", |
3583 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); | 3781 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); |
3584 | } else { | 3782 | } else { |
3585 | ql_dbg(ql_dbg_mbx, vha, 0x10e4, "Done %s.\n", __func__); | 3783 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4, |
3784 | "Done %s.\n", __func__); | ||
3586 | } | 3785 | } |
3587 | 3786 | ||
3588 | return rval; | 3787 | return rval; |
@@ -3595,7 +3794,8 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) | |||
3595 | mbx_cmd_t mc; | 3794 | mbx_cmd_t mc; |
3596 | mbx_cmd_t *mcp = &mc; | 3795 | mbx_cmd_t *mcp = &mc; |
3597 | 3796 | ||
3598 | ql_dbg(ql_dbg_mbx, vha, 0x10e5, "Entered %s.\n", __func__); | 3797 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e5, |
3798 | "Entered %s.\n", __func__); | ||
3599 | 3799 | ||
3600 | mcp->mb[0] = MBC_RESTART_MPI_FW; | 3800 | mcp->mb[0] = MBC_RESTART_MPI_FW; |
3601 | mcp->out_mb = MBX_0; | 3801 | mcp->out_mb = MBX_0; |
@@ -3609,7 +3809,8 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) | |||
3609 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 3809 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
3610 | rval, mcp->mb[0], mcp->mb[1]); | 3810 | rval, mcp->mb[0], mcp->mb[1]); |
3611 | } else { | 3811 | } else { |
3612 | ql_dbg(ql_dbg_mbx, vha, 0x10e7, "Done %s.\n", __func__); | 3812 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e7, |
3813 | "Done %s.\n", __func__); | ||
3613 | } | 3814 | } |
3614 | 3815 | ||
3615 | return rval; | 3816 | return rval; |
@@ -3624,7 +3825,8 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, | |||
3624 | mbx_cmd_t *mcp = &mc; | 3825 | mbx_cmd_t *mcp = &mc; |
3625 | struct qla_hw_data *ha = vha->hw; | 3826 | struct qla_hw_data *ha = vha->hw; |
3626 | 3827 | ||
3627 | ql_dbg(ql_dbg_mbx, vha, 0x10e8, "Entered %s.\n", __func__); | 3828 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, |
3829 | "Entered %s.\n", __func__); | ||
3628 | 3830 | ||
3629 | if (!IS_FWI2_CAPABLE(ha)) | 3831 | if (!IS_FWI2_CAPABLE(ha)) |
3630 | return QLA_FUNCTION_FAILED; | 3832 | return QLA_FUNCTION_FAILED; |
@@ -3654,7 +3856,8 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, | |||
3654 | ql_dbg(ql_dbg_mbx, vha, 0x10e9, | 3856 | ql_dbg(ql_dbg_mbx, vha, 0x10e9, |
3655 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 3857 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3656 | } else { | 3858 | } else { |
3657 | ql_dbg(ql_dbg_mbx, vha, 0x10ea, "Done %s.\n", __func__); | 3859 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, |
3860 | "Done %s.\n", __func__); | ||
3658 | } | 3861 | } |
3659 | 3862 | ||
3660 | return rval; | 3863 | return rval; |
@@ -3669,7 +3872,8 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, | |||
3669 | mbx_cmd_t *mcp = &mc; | 3872 | mbx_cmd_t *mcp = &mc; |
3670 | struct qla_hw_data *ha = vha->hw; | 3873 | struct qla_hw_data *ha = vha->hw; |
3671 | 3874 | ||
3672 | ql_dbg(ql_dbg_mbx, vha, 0x10eb, "Entered %s.\n", __func__); | 3875 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10eb, |
3876 | "Entered %s.\n", __func__); | ||
3673 | 3877 | ||
3674 | if (!IS_FWI2_CAPABLE(ha)) | 3878 | if (!IS_FWI2_CAPABLE(ha)) |
3675 | return QLA_FUNCTION_FAILED; | 3879 | return QLA_FUNCTION_FAILED; |
@@ -3699,7 +3903,8 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, | |||
3699 | ql_dbg(ql_dbg_mbx, vha, 0x10ec, | 3903 | ql_dbg(ql_dbg_mbx, vha, 0x10ec, |
3700 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 3904 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3701 | } else { | 3905 | } else { |
3702 | ql_dbg(ql_dbg_mbx, vha, 0x10ed, "Done %s.\n", __func__); | 3906 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ed, |
3907 | "Done %s.\n", __func__); | ||
3703 | } | 3908 | } |
3704 | 3909 | ||
3705 | return rval; | 3910 | return rval; |
@@ -3713,7 +3918,8 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, | |||
3713 | mbx_cmd_t mc; | 3918 | mbx_cmd_t mc; |
3714 | mbx_cmd_t *mcp = &mc; | 3919 | mbx_cmd_t *mcp = &mc; |
3715 | 3920 | ||
3716 | ql_dbg(ql_dbg_mbx, vha, 0x10ee, "Entered %s.\n", __func__); | 3921 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ee, |
3922 | "Entered %s.\n", __func__); | ||
3717 | 3923 | ||
3718 | if (!IS_CNA_CAPABLE(vha->hw)) | 3924 | if (!IS_CNA_CAPABLE(vha->hw)) |
3719 | return QLA_FUNCTION_FAILED; | 3925 | return QLA_FUNCTION_FAILED; |
@@ -3735,7 +3941,8 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, | |||
3735 | "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", | 3941 | "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", |
3736 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); | 3942 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); |
3737 | } else { | 3943 | } else { |
3738 | ql_dbg(ql_dbg_mbx, vha, 0x10f0, "Done %s.\n", __func__); | 3944 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f0, |
3945 | "Done %s.\n", __func__); | ||
3739 | 3946 | ||
3740 | 3947 | ||
3741 | *actual_size = mcp->mb[2] << 2; | 3948 | *actual_size = mcp->mb[2] << 2; |
@@ -3752,7 +3959,8 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, | |||
3752 | mbx_cmd_t mc; | 3959 | mbx_cmd_t mc; |
3753 | mbx_cmd_t *mcp = &mc; | 3960 | mbx_cmd_t *mcp = &mc; |
3754 | 3961 | ||
3755 | ql_dbg(ql_dbg_mbx, vha, 0x10f1, "Entered %s.\n", __func__); | 3962 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f1, |
3963 | "Entered %s.\n", __func__); | ||
3756 | 3964 | ||
3757 | if (!IS_CNA_CAPABLE(vha->hw)) | 3965 | if (!IS_CNA_CAPABLE(vha->hw)) |
3758 | return QLA_FUNCTION_FAILED; | 3966 | return QLA_FUNCTION_FAILED; |
@@ -3775,7 +3983,8 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, | |||
3775 | "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", | 3983 | "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", |
3776 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); | 3984 | rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); |
3777 | } else { | 3985 | } else { |
3778 | ql_dbg(ql_dbg_mbx, vha, 0x10f3, "Done %s.\n", __func__); | 3986 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f3, |
3987 | "Done %s.\n", __func__); | ||
3779 | } | 3988 | } |
3780 | 3989 | ||
3781 | return rval; | 3990 | return rval; |
@@ -3788,7 +3997,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) | |||
3788 | mbx_cmd_t mc; | 3997 | mbx_cmd_t mc; |
3789 | mbx_cmd_t *mcp = &mc; | 3998 | mbx_cmd_t *mcp = &mc; |
3790 | 3999 | ||
3791 | ql_dbg(ql_dbg_mbx, vha, 0x10f4, "Entered %s.\n", __func__); | 4000 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f4, |
4001 | "Entered %s.\n", __func__); | ||
3792 | 4002 | ||
3793 | if (!IS_FWI2_CAPABLE(vha->hw)) | 4003 | if (!IS_FWI2_CAPABLE(vha->hw)) |
3794 | return QLA_FUNCTION_FAILED; | 4004 | return QLA_FUNCTION_FAILED; |
@@ -3805,7 +4015,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) | |||
3805 | ql_dbg(ql_dbg_mbx, vha, 0x10f5, | 4015 | ql_dbg(ql_dbg_mbx, vha, 0x10f5, |
3806 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4016 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3807 | } else { | 4017 | } else { |
3808 | ql_dbg(ql_dbg_mbx, vha, 0x10f6, "Done %s.\n", __func__); | 4018 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f6, |
4019 | "Done %s.\n", __func__); | ||
3809 | *data = mcp->mb[3] << 16 | mcp->mb[2]; | 4020 | *data = mcp->mb[3] << 16 | mcp->mb[2]; |
3810 | } | 4021 | } |
3811 | 4022 | ||
@@ -3821,7 +4032,8 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, | |||
3821 | mbx_cmd_t *mcp = &mc; | 4032 | mbx_cmd_t *mcp = &mc; |
3822 | uint32_t iter_cnt = 0x1; | 4033 | uint32_t iter_cnt = 0x1; |
3823 | 4034 | ||
3824 | ql_dbg(ql_dbg_mbx, vha, 0x10f7, "Entered %s.\n", __func__); | 4035 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f7, |
4036 | "Entered %s.\n", __func__); | ||
3825 | 4037 | ||
3826 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | 4038 | memset(mcp->mb, 0 , sizeof(mcp->mb)); |
3827 | mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; | 4039 | mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; |
@@ -3865,7 +4077,8 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, | |||
3865 | "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], | 4077 | "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], |
3866 | mcp->mb[3], mcp->mb[18], mcp->mb[19]); | 4078 | mcp->mb[3], mcp->mb[18], mcp->mb[19]); |
3867 | } else { | 4079 | } else { |
3868 | ql_dbg(ql_dbg_mbx, vha, 0x10f9, "Done %s.\n", __func__); | 4080 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f9, |
4081 | "Done %s.\n", __func__); | ||
3869 | } | 4082 | } |
3870 | 4083 | ||
3871 | /* Copy mailbox information */ | 4084 | /* Copy mailbox information */ |
@@ -3882,7 +4095,8 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, | |||
3882 | mbx_cmd_t *mcp = &mc; | 4095 | mbx_cmd_t *mcp = &mc; |
3883 | struct qla_hw_data *ha = vha->hw; | 4096 | struct qla_hw_data *ha = vha->hw; |
3884 | 4097 | ||
3885 | ql_dbg(ql_dbg_mbx, vha, 0x10fa, "Entered %s.\n", __func__); | 4098 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fa, |
4099 | "Entered %s.\n", __func__); | ||
3886 | 4100 | ||
3887 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | 4101 | memset(mcp->mb, 0 , sizeof(mcp->mb)); |
3888 | mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; | 4102 | mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; |
@@ -3926,7 +4140,8 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, | |||
3926 | "Failed=%x mb[0]=%x mb[1]=%x.\n", | 4140 | "Failed=%x mb[0]=%x mb[1]=%x.\n", |
3927 | rval, mcp->mb[0], mcp->mb[1]); | 4141 | rval, mcp->mb[0], mcp->mb[1]); |
3928 | } else { | 4142 | } else { |
3929 | ql_dbg(ql_dbg_mbx, vha, 0x10fc, "Done %s.\n", __func__); | 4143 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fc, |
4144 | "Done %s.\n", __func__); | ||
3930 | } | 4145 | } |
3931 | 4146 | ||
3932 | /* Copy mailbox information */ | 4147 | /* Copy mailbox information */ |
@@ -3941,7 +4156,7 @@ qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic) | |||
3941 | mbx_cmd_t mc; | 4156 | mbx_cmd_t mc; |
3942 | mbx_cmd_t *mcp = &mc; | 4157 | mbx_cmd_t *mcp = &mc; |
3943 | 4158 | ||
3944 | ql_dbg(ql_dbg_mbx, vha, 0x10fd, | 4159 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fd, |
3945 | "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic); | 4160 | "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic); |
3946 | 4161 | ||
3947 | mcp->mb[0] = MBC_ISP84XX_RESET; | 4162 | mcp->mb[0] = MBC_ISP84XX_RESET; |
@@ -3955,7 +4170,8 @@ qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic) | |||
3955 | if (rval != QLA_SUCCESS) | 4170 | if (rval != QLA_SUCCESS) |
3956 | ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval); | 4171 | ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval); |
3957 | else | 4172 | else |
3958 | ql_dbg(ql_dbg_mbx, vha, 0x10ff, "Done %s.\n", __func__); | 4173 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ff, |
4174 | "Done %s.\n", __func__); | ||
3959 | 4175 | ||
3960 | return rval; | 4176 | return rval; |
3961 | } | 4177 | } |
@@ -3967,7 +4183,8 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | |||
3967 | mbx_cmd_t mc; | 4183 | mbx_cmd_t mc; |
3968 | mbx_cmd_t *mcp = &mc; | 4184 | mbx_cmd_t *mcp = &mc; |
3969 | 4185 | ||
3970 | ql_dbg(ql_dbg_mbx, vha, 0x1100, "Entered %s.\n", __func__); | 4186 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1100, |
4187 | "Entered %s.\n", __func__); | ||
3971 | 4188 | ||
3972 | if (!IS_FWI2_CAPABLE(vha->hw)) | 4189 | if (!IS_FWI2_CAPABLE(vha->hw)) |
3973 | return QLA_FUNCTION_FAILED; | 4190 | return QLA_FUNCTION_FAILED; |
@@ -3986,7 +4203,8 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | |||
3986 | ql_dbg(ql_dbg_mbx, vha, 0x1101, | 4203 | ql_dbg(ql_dbg_mbx, vha, 0x1101, |
3987 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4204 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
3988 | } else { | 4205 | } else { |
3989 | ql_dbg(ql_dbg_mbx, vha, 0x1102, "Done %s.\n", __func__); | 4206 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102, |
4207 | "Done %s.\n", __func__); | ||
3990 | } | 4208 | } |
3991 | 4209 | ||
3992 | return rval; | 4210 | return rval; |
@@ -4003,7 +4221,8 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) | |||
4003 | 4221 | ||
4004 | rval = QLA_SUCCESS; | 4222 | rval = QLA_SUCCESS; |
4005 | 4223 | ||
4006 | ql_dbg(ql_dbg_mbx, vha, 0x1103, "Entered %s.\n", __func__); | 4224 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1103, |
4225 | "Entered %s.\n", __func__); | ||
4007 | 4226 | ||
4008 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 4227 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
4009 | 4228 | ||
@@ -4046,7 +4265,8 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) | |||
4046 | ql_dbg(ql_dbg_mbx, vha, 0x1104, | 4265 | ql_dbg(ql_dbg_mbx, vha, 0x1104, |
4047 | "Failed=%x mb[0]=%x.\n", rval, mb[0]); | 4266 | "Failed=%x mb[0]=%x.\n", rval, mb[0]); |
4048 | } else { | 4267 | } else { |
4049 | ql_dbg(ql_dbg_mbx, vha, 0x1105, "Done %s.\n", __func__); | 4268 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1105, |
4269 | "Done %s.\n", __func__); | ||
4050 | } | 4270 | } |
4051 | 4271 | ||
4052 | return rval; | 4272 | return rval; |
@@ -4060,7 +4280,8 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) | |||
4060 | mbx_cmd_t *mcp = &mc; | 4280 | mbx_cmd_t *mcp = &mc; |
4061 | struct qla_hw_data *ha = vha->hw; | 4281 | struct qla_hw_data *ha = vha->hw; |
4062 | 4282 | ||
4063 | ql_dbg(ql_dbg_mbx, vha, 0x1106, "Entered %s.\n", __func__); | 4283 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106, |
4284 | "Entered %s.\n", __func__); | ||
4064 | 4285 | ||
4065 | if (!IS_FWI2_CAPABLE(ha)) | 4286 | if (!IS_FWI2_CAPABLE(ha)) |
4066 | return QLA_FUNCTION_FAILED; | 4287 | return QLA_FUNCTION_FAILED; |
@@ -4078,7 +4299,8 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) | |||
4078 | ql_dbg(ql_dbg_mbx, vha, 0x1107, | 4299 | ql_dbg(ql_dbg_mbx, vha, 0x1107, |
4079 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4300 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4080 | } else { | 4301 | } else { |
4081 | ql_dbg(ql_dbg_mbx, vha, 0x1108, "Done %s.\n", __func__); | 4302 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, |
4303 | "Done %s.\n", __func__); | ||
4082 | if (mcp->mb[1] != 0x7) | 4304 | if (mcp->mb[1] != 0x7) |
4083 | ha->link_data_rate = mcp->mb[1]; | 4305 | ha->link_data_rate = mcp->mb[1]; |
4084 | } | 4306 | } |
@@ -4094,7 +4316,8 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) | |||
4094 | mbx_cmd_t *mcp = &mc; | 4316 | mbx_cmd_t *mcp = &mc; |
4095 | struct qla_hw_data *ha = vha->hw; | 4317 | struct qla_hw_data *ha = vha->hw; |
4096 | 4318 | ||
4097 | ql_dbg(ql_dbg_mbx, vha, 0x1109, "Entered %s.\n", __func__); | 4319 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1109, |
4320 | "Entered %s.\n", __func__); | ||
4098 | 4321 | ||
4099 | if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) | 4322 | if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) |
4100 | return QLA_FUNCTION_FAILED; | 4323 | return QLA_FUNCTION_FAILED; |
@@ -4113,7 +4336,8 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) | |||
4113 | /* Copy all bits to preserve original value */ | 4336 | /* Copy all bits to preserve original value */ |
4114 | memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4); | 4337 | memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4); |
4115 | 4338 | ||
4116 | ql_dbg(ql_dbg_mbx, vha, 0x110b, "Done %s.\n", __func__); | 4339 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110b, |
4340 | "Done %s.\n", __func__); | ||
4117 | } | 4341 | } |
4118 | return rval; | 4342 | return rval; |
4119 | } | 4343 | } |
@@ -4125,7 +4349,8 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb) | |||
4125 | mbx_cmd_t mc; | 4349 | mbx_cmd_t mc; |
4126 | mbx_cmd_t *mcp = &mc; | 4350 | mbx_cmd_t *mcp = &mc; |
4127 | 4351 | ||
4128 | ql_dbg(ql_dbg_mbx, vha, 0x110c, "Entered %s.\n", __func__); | 4352 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110c, |
4353 | "Entered %s.\n", __func__); | ||
4129 | 4354 | ||
4130 | mcp->mb[0] = MBC_SET_PORT_CONFIG; | 4355 | mcp->mb[0] = MBC_SET_PORT_CONFIG; |
4131 | /* Copy all bits to preserve original setting */ | 4356 | /* Copy all bits to preserve original setting */ |
@@ -4140,7 +4365,8 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb) | |||
4140 | ql_dbg(ql_dbg_mbx, vha, 0x110d, | 4365 | ql_dbg(ql_dbg_mbx, vha, 0x110d, |
4141 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4366 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4142 | } else | 4367 | } else |
4143 | ql_dbg(ql_dbg_mbx, vha, 0x110e, "Done %s.\n", __func__); | 4368 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110e, |
4369 | "Done %s.\n", __func__); | ||
4144 | 4370 | ||
4145 | return rval; | 4371 | return rval; |
4146 | } | 4372 | } |
@@ -4155,7 +4381,8 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, | |||
4155 | mbx_cmd_t *mcp = &mc; | 4381 | mbx_cmd_t *mcp = &mc; |
4156 | struct qla_hw_data *ha = vha->hw; | 4382 | struct qla_hw_data *ha = vha->hw; |
4157 | 4383 | ||
4158 | ql_dbg(ql_dbg_mbx, vha, 0x110f, "Entered %s.\n", __func__); | 4384 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110f, |
4385 | "Entered %s.\n", __func__); | ||
4159 | 4386 | ||
4160 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | 4387 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) |
4161 | return QLA_FUNCTION_FAILED; | 4388 | return QLA_FUNCTION_FAILED; |
@@ -4183,7 +4410,8 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, | |||
4183 | if (rval != QLA_SUCCESS) { | 4410 | if (rval != QLA_SUCCESS) { |
4184 | ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval); | 4411 | ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval); |
4185 | } else { | 4412 | } else { |
4186 | ql_dbg(ql_dbg_mbx, vha, 0x10cc, "Done %s.\n", __func__); | 4413 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10cc, |
4414 | "Done %s.\n", __func__); | ||
4187 | } | 4415 | } |
4188 | 4416 | ||
4189 | return rval; | 4417 | return rval; |
@@ -4196,7 +4424,8 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac) | |||
4196 | uint8_t byte; | 4424 | uint8_t byte; |
4197 | struct qla_hw_data *ha = vha->hw; | 4425 | struct qla_hw_data *ha = vha->hw; |
4198 | 4426 | ||
4199 | ql_dbg(ql_dbg_mbx, vha, 0x10ca, "Entered %s.\n", __func__); | 4427 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ca, |
4428 | "Entered %s.\n", __func__); | ||
4200 | 4429 | ||
4201 | /* Integer part */ | 4430 | /* Integer part */ |
4202 | rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1, BIT_13|BIT_0); | 4431 | rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1, BIT_13|BIT_0); |
@@ -4216,7 +4445,8 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac) | |||
4216 | } | 4445 | } |
4217 | *frac = (byte >> 6) * 25; | 4446 | *frac = (byte >> 6) * 25; |
4218 | 4447 | ||
4219 | ql_dbg(ql_dbg_mbx, vha, 0x1018, "Done %s.\n", __func__); | 4448 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1018, |
4449 | "Done %s.\n", __func__); | ||
4220 | fail: | 4450 | fail: |
4221 | return rval; | 4451 | return rval; |
4222 | } | 4452 | } |
@@ -4229,7 +4459,8 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) | |||
4229 | mbx_cmd_t mc; | 4459 | mbx_cmd_t mc; |
4230 | mbx_cmd_t *mcp = &mc; | 4460 | mbx_cmd_t *mcp = &mc; |
4231 | 4461 | ||
4232 | ql_dbg(ql_dbg_mbx, vha, 0x1017, "Entered %s.\n", __func__); | 4462 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1017, |
4463 | "Entered %s.\n", __func__); | ||
4233 | 4464 | ||
4234 | if (!IS_FWI2_CAPABLE(ha)) | 4465 | if (!IS_FWI2_CAPABLE(ha)) |
4235 | return QLA_FUNCTION_FAILED; | 4466 | return QLA_FUNCTION_FAILED; |
@@ -4248,7 +4479,8 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) | |||
4248 | ql_dbg(ql_dbg_mbx, vha, 0x1016, | 4479 | ql_dbg(ql_dbg_mbx, vha, 0x1016, |
4249 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4480 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4250 | } else { | 4481 | } else { |
4251 | ql_dbg(ql_dbg_mbx, vha, 0x100e, "Done %s.\n", __func__); | 4482 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100e, |
4483 | "Done %s.\n", __func__); | ||
4252 | } | 4484 | } |
4253 | 4485 | ||
4254 | return rval; | 4486 | return rval; |
@@ -4262,7 +4494,8 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha) | |||
4262 | mbx_cmd_t mc; | 4494 | mbx_cmd_t mc; |
4263 | mbx_cmd_t *mcp = &mc; | 4495 | mbx_cmd_t *mcp = &mc; |
4264 | 4496 | ||
4265 | ql_dbg(ql_dbg_mbx, vha, 0x100d, "Entered %s.\n", __func__); | 4497 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100d, |
4498 | "Entered %s.\n", __func__); | ||
4266 | 4499 | ||
4267 | if (!IS_QLA82XX(ha)) | 4500 | if (!IS_QLA82XX(ha)) |
4268 | return QLA_FUNCTION_FAILED; | 4501 | return QLA_FUNCTION_FAILED; |
@@ -4281,7 +4514,8 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha) | |||
4281 | ql_dbg(ql_dbg_mbx, vha, 0x100c, | 4514 | ql_dbg(ql_dbg_mbx, vha, 0x100c, |
4282 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4515 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4283 | } else { | 4516 | } else { |
4284 | ql_dbg(ql_dbg_mbx, vha, 0x100b, "Done %s.\n", __func__); | 4517 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100b, |
4518 | "Done %s.\n", __func__); | ||
4285 | } | 4519 | } |
4286 | 4520 | ||
4287 | return rval; | 4521 | return rval; |
@@ -4295,7 +4529,8 @@ qla82xx_md_get_template_size(scsi_qla_host_t *vha) | |||
4295 | mbx_cmd_t *mcp = &mc; | 4529 | mbx_cmd_t *mcp = &mc; |
4296 | int rval = QLA_FUNCTION_FAILED; | 4530 | int rval = QLA_FUNCTION_FAILED; |
4297 | 4531 | ||
4298 | ql_dbg(ql_dbg_mbx, vha, 0x111f, "Entered %s.\n", __func__); | 4532 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111f, |
4533 | "Entered %s.\n", __func__); | ||
4299 | 4534 | ||
4300 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | 4535 | memset(mcp->mb, 0 , sizeof(mcp->mb)); |
4301 | mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); | 4536 | mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); |
@@ -4318,7 +4553,8 @@ qla82xx_md_get_template_size(scsi_qla_host_t *vha) | |||
4318 | (mcp->mb[1] << 16) | mcp->mb[0], | 4553 | (mcp->mb[1] << 16) | mcp->mb[0], |
4319 | (mcp->mb[3] << 16) | mcp->mb[2]); | 4554 | (mcp->mb[3] << 16) | mcp->mb[2]); |
4320 | } else { | 4555 | } else { |
4321 | ql_dbg(ql_dbg_mbx, vha, 0x1121, "Done %s.\n", __func__); | 4556 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1121, |
4557 | "Done %s.\n", __func__); | ||
4322 | ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]); | 4558 | ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]); |
4323 | if (!ha->md_template_size) { | 4559 | if (!ha->md_template_size) { |
4324 | ql_dbg(ql_dbg_mbx, vha, 0x1122, | 4560 | ql_dbg(ql_dbg_mbx, vha, 0x1122, |
@@ -4337,7 +4573,8 @@ qla82xx_md_get_template(scsi_qla_host_t *vha) | |||
4337 | mbx_cmd_t *mcp = &mc; | 4573 | mbx_cmd_t *mcp = &mc; |
4338 | int rval = QLA_FUNCTION_FAILED; | 4574 | int rval = QLA_FUNCTION_FAILED; |
4339 | 4575 | ||
4340 | ql_dbg(ql_dbg_mbx, vha, 0x1123, "Entered %s.\n", __func__); | 4576 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1123, |
4577 | "Entered %s.\n", __func__); | ||
4341 | 4578 | ||
4342 | ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev, | 4579 | ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev, |
4343 | ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL); | 4580 | ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL); |
@@ -4372,7 +4609,8 @@ qla82xx_md_get_template(scsi_qla_host_t *vha) | |||
4372 | ((mcp->mb[1] << 16) | mcp->mb[0]), | 4609 | ((mcp->mb[1] << 16) | mcp->mb[0]), |
4373 | ((mcp->mb[3] << 16) | mcp->mb[2])); | 4610 | ((mcp->mb[3] << 16) | mcp->mb[2])); |
4374 | } else | 4611 | } else |
4375 | ql_dbg(ql_dbg_mbx, vha, 0x1126, "Done %s.\n", __func__); | 4612 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1126, |
4613 | "Done %s.\n", __func__); | ||
4376 | return rval; | 4614 | return rval; |
4377 | } | 4615 | } |
4378 | 4616 | ||
@@ -4387,7 +4625,8 @@ qla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) | |||
4387 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) | 4625 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) |
4388 | return QLA_FUNCTION_FAILED; | 4626 | return QLA_FUNCTION_FAILED; |
4389 | 4627 | ||
4390 | ql_dbg(ql_dbg_mbx, vha, 0x1133, "Entered %s.\n", __func__); | 4628 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1133, |
4629 | "Entered %s.\n", __func__); | ||
4391 | 4630 | ||
4392 | memset(mcp, 0, sizeof(mbx_cmd_t)); | 4631 | memset(mcp, 0, sizeof(mbx_cmd_t)); |
4393 | mcp->mb[0] = MBC_SET_LED_CONFIG; | 4632 | mcp->mb[0] = MBC_SET_LED_CONFIG; |
@@ -4412,7 +4651,8 @@ qla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) | |||
4412 | ql_dbg(ql_dbg_mbx, vha, 0x1134, | 4651 | ql_dbg(ql_dbg_mbx, vha, 0x1134, |
4413 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4652 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4414 | } else { | 4653 | } else { |
4415 | ql_dbg(ql_dbg_mbx, vha, 0x1135, "Done %s.\n", __func__); | 4654 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1135, |
4655 | "Done %s.\n", __func__); | ||
4416 | } | 4656 | } |
4417 | 4657 | ||
4418 | return rval; | 4658 | return rval; |
@@ -4429,7 +4669,8 @@ qla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) | |||
4429 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) | 4669 | if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) |
4430 | return QLA_FUNCTION_FAILED; | 4670 | return QLA_FUNCTION_FAILED; |
4431 | 4671 | ||
4432 | ql_dbg(ql_dbg_mbx, vha, 0x1136, "Entered %s.\n", __func__); | 4672 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1136, |
4673 | "Entered %s.\n", __func__); | ||
4433 | 4674 | ||
4434 | memset(mcp, 0, sizeof(mbx_cmd_t)); | 4675 | memset(mcp, 0, sizeof(mbx_cmd_t)); |
4435 | mcp->mb[0] = MBC_GET_LED_CONFIG; | 4676 | mcp->mb[0] = MBC_GET_LED_CONFIG; |
@@ -4454,7 +4695,8 @@ qla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) | |||
4454 | led_cfg[4] = mcp->mb[5]; | 4695 | led_cfg[4] = mcp->mb[5]; |
4455 | led_cfg[5] = mcp->mb[6]; | 4696 | led_cfg[5] = mcp->mb[6]; |
4456 | } | 4697 | } |
4457 | ql_dbg(ql_dbg_mbx, vha, 0x1138, "Done %s.\n", __func__); | 4698 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1138, |
4699 | "Done %s.\n", __func__); | ||
4458 | } | 4700 | } |
4459 | 4701 | ||
4460 | return rval; | 4702 | return rval; |
@@ -4471,7 +4713,7 @@ qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) | |||
4471 | if (!IS_QLA82XX(ha)) | 4713 | if (!IS_QLA82XX(ha)) |
4472 | return QLA_FUNCTION_FAILED; | 4714 | return QLA_FUNCTION_FAILED; |
4473 | 4715 | ||
4474 | ql_dbg(ql_dbg_mbx, vha, 0x1127, | 4716 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1127, |
4475 | "Entered %s.\n", __func__); | 4717 | "Entered %s.\n", __func__); |
4476 | 4718 | ||
4477 | memset(mcp, 0, sizeof(mbx_cmd_t)); | 4719 | memset(mcp, 0, sizeof(mbx_cmd_t)); |
@@ -4491,7 +4733,7 @@ qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) | |||
4491 | ql_dbg(ql_dbg_mbx, vha, 0x1128, | 4733 | ql_dbg(ql_dbg_mbx, vha, 0x1128, |
4492 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4734 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4493 | } else { | 4735 | } else { |
4494 | ql_dbg(ql_dbg_mbx, vha, 0x1129, | 4736 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1129, |
4495 | "Done %s.\n", __func__); | 4737 | "Done %s.\n", __func__); |
4496 | } | 4738 | } |
4497 | 4739 | ||
@@ -4509,7 +4751,8 @@ qla83xx_write_remote_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) | |||
4509 | if (!IS_QLA83XX(ha)) | 4751 | if (!IS_QLA83XX(ha)) |
4510 | return QLA_FUNCTION_FAILED; | 4752 | return QLA_FUNCTION_FAILED; |
4511 | 4753 | ||
4512 | ql_dbg(ql_dbg_mbx, vha, 0x1130, "Entered %s.\n", __func__); | 4754 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130, |
4755 | "Entered %s.\n", __func__); | ||
4513 | 4756 | ||
4514 | mcp->mb[0] = MBC_WRITE_REMOTE_REG; | 4757 | mcp->mb[0] = MBC_WRITE_REMOTE_REG; |
4515 | mcp->mb[1] = LSW(reg); | 4758 | mcp->mb[1] = LSW(reg); |
@@ -4527,7 +4770,7 @@ qla83xx_write_remote_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) | |||
4527 | ql_dbg(ql_dbg_mbx, vha, 0x1131, | 4770 | ql_dbg(ql_dbg_mbx, vha, 0x1131, |
4528 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4771 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4529 | } else { | 4772 | } else { |
4530 | ql_dbg(ql_dbg_mbx, vha, 0x1132, | 4773 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1132, |
4531 | "Done %s.\n", __func__); | 4774 | "Done %s.\n", __func__); |
4532 | } | 4775 | } |
4533 | 4776 | ||
@@ -4543,13 +4786,14 @@ qla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport) | |||
4543 | mbx_cmd_t *mcp = &mc; | 4786 | mbx_cmd_t *mcp = &mc; |
4544 | 4787 | ||
4545 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 4788 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
4546 | ql_dbg(ql_dbg_mbx, vha, 0x113b, | 4789 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113b, |
4547 | "Implicit LOGO Unsupported.\n"); | 4790 | "Implicit LOGO Unsupported.\n"); |
4548 | return QLA_FUNCTION_FAILED; | 4791 | return QLA_FUNCTION_FAILED; |
4549 | } | 4792 | } |
4550 | 4793 | ||
4551 | 4794 | ||
4552 | ql_dbg(ql_dbg_mbx, vha, 0x113c, "Done %s.\n", __func__); | 4795 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113c, |
4796 | "Entering %s.\n", __func__); | ||
4553 | 4797 | ||
4554 | /* Perform Implicit LOGO. */ | 4798 | /* Perform Implicit LOGO. */ |
4555 | mcp->mb[0] = MBC_PORT_LOGOUT; | 4799 | mcp->mb[0] = MBC_PORT_LOGOUT; |
@@ -4564,7 +4808,8 @@ qla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport) | |||
4564 | ql_dbg(ql_dbg_mbx, vha, 0x113d, | 4808 | ql_dbg(ql_dbg_mbx, vha, 0x113d, |
4565 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | 4809 | "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); |
4566 | else | 4810 | else |
4567 | ql_dbg(ql_dbg_mbx, vha, 0x113e, "Done %s.\n", __func__); | 4811 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113e, |
4812 | "Done %s.\n", __func__); | ||
4568 | 4813 | ||
4569 | return rval; | 4814 | return rval; |
4570 | } | 4815 | } |
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index aa062a1b0ca4..3e8b32419e68 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_gbl.h" | 8 | #include "qla_gbl.h" |
9 | #include "qla_target.h" | ||
9 | 10 | ||
10 | #include <linux/moduleparam.h> | 11 | #include <linux/moduleparam.h> |
11 | #include <linux/vmalloc.h> | 12 | #include <linux/vmalloc.h> |
@@ -49,6 +50,9 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | |||
49 | 50 | ||
50 | spin_lock_irqsave(&ha->vport_slock, flags); | 51 | spin_lock_irqsave(&ha->vport_slock, flags); |
51 | list_add_tail(&vha->list, &ha->vp_list); | 52 | list_add_tail(&vha->list, &ha->vp_list); |
53 | |||
54 | qlt_update_vp_map(vha, SET_VP_IDX); | ||
55 | |||
52 | spin_unlock_irqrestore(&ha->vport_slock, flags); | 56 | spin_unlock_irqrestore(&ha->vport_slock, flags); |
53 | 57 | ||
54 | mutex_unlock(&ha->vport_lock); | 58 | mutex_unlock(&ha->vport_lock); |
@@ -79,6 +83,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) | |||
79 | spin_lock_irqsave(&ha->vport_slock, flags); | 83 | spin_lock_irqsave(&ha->vport_slock, flags); |
80 | } | 84 | } |
81 | list_del(&vha->list); | 85 | list_del(&vha->list); |
86 | qlt_update_vp_map(vha, RESET_VP_IDX); | ||
82 | spin_unlock_irqrestore(&ha->vport_slock, flags); | 87 | spin_unlock_irqrestore(&ha->vport_slock, flags); |
83 | 88 | ||
84 | vp_id = vha->vp_idx; | 89 | vp_id = vha->vp_idx; |
@@ -134,7 +139,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) | |||
134 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 139 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
135 | ql_dbg(ql_dbg_vport, vha, 0xa001, | 140 | ql_dbg(ql_dbg_vport, vha, 0xa001, |
136 | "Marking port dead, loop_id=0x%04x : %x.\n", | 141 | "Marking port dead, loop_id=0x%04x : %x.\n", |
137 | fcport->loop_id, fcport->vp_idx); | 142 | fcport->loop_id, fcport->vha->vp_idx); |
138 | 143 | ||
139 | qla2x00_mark_device_lost(vha, fcport, 0, 0); | 144 | qla2x00_mark_device_lost(vha, fcport, 0, 0); |
140 | qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); | 145 | qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); |
@@ -150,6 +155,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) | |||
150 | atomic_set(&vha->loop_state, LOOP_DOWN); | 155 | atomic_set(&vha->loop_state, LOOP_DOWN); |
151 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | 156 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); |
152 | 157 | ||
158 | /* Remove port id from vp target map */ | ||
159 | qlt_update_vp_map(vha, RESET_AL_PA); | ||
160 | |||
153 | qla2x00_mark_vp_devices_dead(vha); | 161 | qla2x00_mark_vp_devices_dead(vha); |
154 | atomic_set(&vha->vp_state, VP_FAILED); | 162 | atomic_set(&vha->vp_state, VP_FAILED); |
155 | vha->flags.management_server_logged_in = 0; | 163 | vha->flags.management_server_logged_in = 0; |
@@ -295,10 +303,8 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha) | |||
295 | static int | 303 | static int |
296 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) | 304 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) |
297 | { | 305 | { |
298 | ql_dbg(ql_dbg_dpc, vha, 0x4012, | 306 | ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012, |
299 | "Entering %s.\n", __func__); | 307 | "Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags); |
300 | ql_dbg(ql_dbg_dpc, vha, 0x4013, | ||
301 | "vp_flags: 0x%lx.\n", vha->vp_flags); | ||
302 | 308 | ||
303 | qla2x00_do_work(vha); | 309 | qla2x00_do_work(vha); |
304 | 310 | ||
@@ -348,7 +354,7 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) | |||
348 | } | 354 | } |
349 | } | 355 | } |
350 | 356 | ||
351 | ql_dbg(ql_dbg_dpc, vha, 0x401c, | 357 | ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x401c, |
352 | "Exiting %s.\n", __func__); | 358 | "Exiting %s.\n", __func__); |
353 | return 0; | 359 | return 0; |
354 | } | 360 | } |
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index de722a933438..caf627ba7fa8 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -1190,12 +1190,12 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) | |||
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | /* Offset in flash = lower 16 bits | 1192 | /* Offset in flash = lower 16 bits |
1193 | * Number of enteries = upper 16 bits | 1193 | * Number of entries = upper 16 bits |
1194 | */ | 1194 | */ |
1195 | offset = n & 0xffffU; | 1195 | offset = n & 0xffffU; |
1196 | n = (n >> 16) & 0xffffU; | 1196 | n = (n >> 16) & 0xffffU; |
1197 | 1197 | ||
1198 | /* number of addr/value pair should not exceed 1024 enteries */ | 1198 | /* number of addr/value pair should not exceed 1024 entries */ |
1199 | if (n >= 1024) { | 1199 | if (n >= 1024) { |
1200 | ql_log(ql_log_fatal, vha, 0x0071, | 1200 | ql_log(ql_log_fatal, vha, 0x0071, |
1201 | "Card flash not initialized:n=0x%x.\n", n); | 1201 | "Card flash not initialized:n=0x%x.\n", n); |
@@ -2050,7 +2050,7 @@ qla82xx_intr_handler(int irq, void *dev_id) | |||
2050 | 2050 | ||
2051 | rsp = (struct rsp_que *) dev_id; | 2051 | rsp = (struct rsp_que *) dev_id; |
2052 | if (!rsp) { | 2052 | if (!rsp) { |
2053 | ql_log(ql_log_info, NULL, 0xb054, | 2053 | ql_log(ql_log_info, NULL, 0xb053, |
2054 | "%s: NULL response queue pointer.\n", __func__); | 2054 | "%s: NULL response queue pointer.\n", __func__); |
2055 | return IRQ_NONE; | 2055 | return IRQ_NONE; |
2056 | } | 2056 | } |
@@ -2446,7 +2446,7 @@ qla82xx_load_fw(scsi_qla_host_t *vha) | |||
2446 | 2446 | ||
2447 | if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) { | 2447 | if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) { |
2448 | ql_log(ql_log_info, vha, 0x00a1, | 2448 | ql_log(ql_log_info, vha, 0x00a1, |
2449 | "Firmware loaded successully from flash.\n"); | 2449 | "Firmware loaded successfully from flash.\n"); |
2450 | return QLA_SUCCESS; | 2450 | return QLA_SUCCESS; |
2451 | } else { | 2451 | } else { |
2452 | ql_log(ql_log_warn, vha, 0x0108, | 2452 | ql_log(ql_log_warn, vha, 0x0108, |
@@ -2461,7 +2461,7 @@ try_blob_fw: | |||
2461 | blob = ha->hablob = qla2x00_request_firmware(vha); | 2461 | blob = ha->hablob = qla2x00_request_firmware(vha); |
2462 | if (!blob) { | 2462 | if (!blob) { |
2463 | ql_log(ql_log_fatal, vha, 0x00a3, | 2463 | ql_log(ql_log_fatal, vha, 0x00a3, |
2464 | "Firmware image not preset.\n"); | 2464 | "Firmware image not present.\n"); |
2465 | goto fw_load_failed; | 2465 | goto fw_load_failed; |
2466 | } | 2466 | } |
2467 | 2467 | ||
@@ -2689,7 +2689,7 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr, | |||
2689 | if (!optrom) { | 2689 | if (!optrom) { |
2690 | ql_log(ql_log_warn, vha, 0xb01b, | 2690 | ql_log(ql_log_warn, vha, 0xb01b, |
2691 | "Unable to allocate memory " | 2691 | "Unable to allocate memory " |
2692 | "for optron burst write (%x KB).\n", | 2692 | "for optrom burst write (%x KB).\n", |
2693 | OPTROM_BURST_SIZE / 1024); | 2693 | OPTROM_BURST_SIZE / 1024); |
2694 | } | 2694 | } |
2695 | } | 2695 | } |
@@ -2960,9 +2960,8 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha) | |||
2960 | * changing the state to DEV_READY | 2960 | * changing the state to DEV_READY |
2961 | */ | 2961 | */ |
2962 | ql_log(ql_log_info, vha, 0xb023, | 2962 | ql_log(ql_log_info, vha, 0xb023, |
2963 | "%s : QUIESCENT TIMEOUT.\n", QLA2XXX_DRIVER_NAME); | 2963 | "%s : QUIESCENT TIMEOUT DRV_ACTIVE:%d " |
2964 | ql_log(ql_log_info, vha, 0xb024, | 2964 | "DRV_STATE:%d.\n", QLA2XXX_DRIVER_NAME, |
2965 | "DRV_ACTIVE:%d DRV_STATE:%d.\n", | ||
2966 | drv_active, drv_state); | 2965 | drv_active, drv_state); |
2967 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 2966 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
2968 | QLA82XX_DEV_READY); | 2967 | QLA82XX_DEV_READY); |
@@ -3129,7 +3128,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) | |||
3129 | if (ql2xmdenable) { | 3128 | if (ql2xmdenable) { |
3130 | if (qla82xx_md_collect(vha)) | 3129 | if (qla82xx_md_collect(vha)) |
3131 | ql_log(ql_log_warn, vha, 0xb02c, | 3130 | ql_log(ql_log_warn, vha, 0xb02c, |
3132 | "Not able to collect minidump.\n"); | 3131 | "Minidump not collected.\n"); |
3133 | } else | 3132 | } else |
3134 | ql_log(ql_log_warn, vha, 0xb04f, | 3133 | ql_log(ql_log_warn, vha, 0xb04f, |
3135 | "Minidump disabled.\n"); | 3134 | "Minidump disabled.\n"); |
@@ -3160,11 +3159,11 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha) | |||
3160 | "Firmware version differs " | 3159 | "Firmware version differs " |
3161 | "Previous version: %d:%d:%d - " | 3160 | "Previous version: %d:%d:%d - " |
3162 | "New version: %d:%d:%d\n", | 3161 | "New version: %d:%d:%d\n", |
3162 | fw_major_version, fw_minor_version, | ||
3163 | fw_subminor_version, | ||
3163 | ha->fw_major_version, | 3164 | ha->fw_major_version, |
3164 | ha->fw_minor_version, | 3165 | ha->fw_minor_version, |
3165 | ha->fw_subminor_version, | 3166 | ha->fw_subminor_version); |
3166 | fw_major_version, fw_minor_version, | ||
3167 | fw_subminor_version); | ||
3168 | /* Release MiniDump resources */ | 3167 | /* Release MiniDump resources */ |
3169 | qla82xx_md_free(vha); | 3168 | qla82xx_md_free(vha); |
3170 | /* ALlocate MiniDump resources */ | 3169 | /* ALlocate MiniDump resources */ |
@@ -3325,6 +3324,30 @@ exit: | |||
3325 | return rval; | 3324 | return rval; |
3326 | } | 3325 | } |
3327 | 3326 | ||
3327 | static int qla82xx_check_temp(scsi_qla_host_t *vha) | ||
3328 | { | ||
3329 | uint32_t temp, temp_state, temp_val; | ||
3330 | struct qla_hw_data *ha = vha->hw; | ||
3331 | |||
3332 | temp = qla82xx_rd_32(ha, CRB_TEMP_STATE); | ||
3333 | temp_state = qla82xx_get_temp_state(temp); | ||
3334 | temp_val = qla82xx_get_temp_val(temp); | ||
3335 | |||
3336 | if (temp_state == QLA82XX_TEMP_PANIC) { | ||
3337 | ql_log(ql_log_warn, vha, 0x600e, | ||
3338 | "Device temperature %d degrees C exceeds " | ||
3339 | " maximum allowed. Hardware has been shut down.\n", | ||
3340 | temp_val); | ||
3341 | return 1; | ||
3342 | } else if (temp_state == QLA82XX_TEMP_WARN) { | ||
3343 | ql_log(ql_log_warn, vha, 0x600f, | ||
3344 | "Device temperature %d degrees C exceeds " | ||
3345 | "operating range. Immediate action needed.\n", | ||
3346 | temp_val); | ||
3347 | } | ||
3348 | return 0; | ||
3349 | } | ||
3350 | |||
3328 | void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) | 3351 | void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) |
3329 | { | 3352 | { |
3330 | struct qla_hw_data *ha = vha->hw; | 3353 | struct qla_hw_data *ha = vha->hw; |
@@ -3347,18 +3370,20 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3347 | /* don't poll if reset is going on */ | 3370 | /* don't poll if reset is going on */ |
3348 | if (!ha->flags.isp82xx_reset_hdlr_active) { | 3371 | if (!ha->flags.isp82xx_reset_hdlr_active) { |
3349 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 3372 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
3350 | if (dev_state == QLA82XX_DEV_NEED_RESET && | 3373 | if (qla82xx_check_temp(vha)) { |
3374 | set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); | ||
3375 | ha->flags.isp82xx_fw_hung = 1; | ||
3376 | qla82xx_clear_pending_mbx(vha); | ||
3377 | } else if (dev_state == QLA82XX_DEV_NEED_RESET && | ||
3351 | !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { | 3378 | !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { |
3352 | ql_log(ql_log_warn, vha, 0x6001, | 3379 | ql_log(ql_log_warn, vha, 0x6001, |
3353 | "Adapter reset needed.\n"); | 3380 | "Adapter reset needed.\n"); |
3354 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3381 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
3355 | qla2xxx_wake_dpc(vha); | ||
3356 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | 3382 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && |
3357 | !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { | 3383 | !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { |
3358 | ql_log(ql_log_warn, vha, 0x6002, | 3384 | ql_log(ql_log_warn, vha, 0x6002, |
3359 | "Quiescent needed.\n"); | 3385 | "Quiescent needed.\n"); |
3360 | set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); | 3386 | set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); |
3361 | qla2xxx_wake_dpc(vha); | ||
3362 | } else { | 3387 | } else { |
3363 | if (qla82xx_check_fw_alive(vha)) { | 3388 | if (qla82xx_check_fw_alive(vha)) { |
3364 | ql_dbg(ql_dbg_timer, vha, 0x6011, | 3389 | ql_dbg(ql_dbg_timer, vha, 0x6011, |
@@ -3398,7 +3423,6 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3398 | set_bit(ISP_ABORT_NEEDED, | 3423 | set_bit(ISP_ABORT_NEEDED, |
3399 | &vha->dpc_flags); | 3424 | &vha->dpc_flags); |
3400 | } | 3425 | } |
3401 | qla2xxx_wake_dpc(vha); | ||
3402 | ha->flags.isp82xx_fw_hung = 1; | 3426 | ha->flags.isp82xx_fw_hung = 1; |
3403 | ql_log(ql_log_warn, vha, 0x6007, "Firmware hung.\n"); | 3427 | ql_log(ql_log_warn, vha, 0x6007, "Firmware hung.\n"); |
3404 | qla82xx_clear_pending_mbx(vha); | 3428 | qla82xx_clear_pending_mbx(vha); |
@@ -4113,6 +4137,14 @@ qla82xx_md_collect(scsi_qla_host_t *vha) | |||
4113 | goto md_failed; | 4137 | goto md_failed; |
4114 | } | 4138 | } |
4115 | 4139 | ||
4140 | if (ha->flags.isp82xx_no_md_cap) { | ||
4141 | ql_log(ql_log_warn, vha, 0xb054, | ||
4142 | "Forced reset from application, " | ||
4143 | "ignore minidump capture\n"); | ||
4144 | ha->flags.isp82xx_no_md_cap = 0; | ||
4145 | goto md_failed; | ||
4146 | } | ||
4147 | |||
4116 | if (qla82xx_validate_template_chksum(vha)) { | 4148 | if (qla82xx_validate_template_chksum(vha)) { |
4117 | ql_log(ql_log_info, vha, 0xb039, | 4149 | ql_log(ql_log_info, vha, 0xb039, |
4118 | "Template checksum validation error\n"); | 4150 | "Template checksum validation error\n"); |
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 4ac50e274661..6eb210e3cc63 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) | 26 | #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) |
27 | #define BOOT_LOADER_DIMM_STATUS QLA82XX_REG(0x54) | 27 | #define BOOT_LOADER_DIMM_STATUS QLA82XX_REG(0x54) |
28 | #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) | 28 | #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) |
29 | #define CRB_TEMP_STATE QLA82XX_REG(0x1b4) | ||
29 | #define QLA82XX_DMA_SHIFT_VALUE 0x55555555 | 30 | #define QLA82XX_DMA_SHIFT_VALUE 0x55555555 |
30 | 31 | ||
31 | #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 | 32 | #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 |
@@ -561,7 +562,6 @@ | |||
561 | #define QLA82XX_FW_VERSION_SUB (QLA82XX_CAM_RAM(0x158)) | 562 | #define QLA82XX_FW_VERSION_SUB (QLA82XX_CAM_RAM(0x158)) |
562 | #define QLA82XX_PCIE_REG(reg) (QLA82XX_CRB_PCIE + (reg)) | 563 | #define QLA82XX_PCIE_REG(reg) (QLA82XX_CRB_PCIE + (reg)) |
563 | 564 | ||
564 | #define PCIE_CHICKEN3 (0x120c8) | ||
565 | #define PCIE_SETUP_FUNCTION (0x12040) | 565 | #define PCIE_SETUP_FUNCTION (0x12040) |
566 | #define PCIE_SETUP_FUNCTION2 (0x12048) | 566 | #define PCIE_SETUP_FUNCTION2 (0x12048) |
567 | 567 | ||
@@ -1178,4 +1178,16 @@ static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC, | |||
1178 | #define CRB_NIU_XG_PAUSE_CTL_P0 0x1 | 1178 | #define CRB_NIU_XG_PAUSE_CTL_P0 0x1 |
1179 | #define CRB_NIU_XG_PAUSE_CTL_P1 0x8 | 1179 | #define CRB_NIU_XG_PAUSE_CTL_P1 0x8 |
1180 | 1180 | ||
1181 | #define qla82xx_get_temp_val(x) ((x) >> 16) | ||
1182 | #define qla82xx_get_temp_state(x) ((x) & 0xffff) | ||
1183 | #define qla82xx_encode_temp(val, state) (((val) << 16) | (state)) | ||
1184 | |||
1185 | /* | ||
1186 | * Temperature control. | ||
1187 | */ | ||
1188 | enum { | ||
1189 | QLA82XX_TEMP_NORMAL = 0x1, /* Normal operating range */ | ||
1190 | QLA82XX_TEMP_WARN, /* Sound alert, temperature getting high */ | ||
1191 | QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */ | ||
1192 | }; | ||
1181 | #endif | 1193 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c9c56a8427f3..6d1d873a20e2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -13,12 +13,13 @@ | |||
13 | #include <linux/mutex.h> | 13 | #include <linux/mutex.h> |
14 | #include <linux/kobject.h> | 14 | #include <linux/kobject.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | |||
17 | #include <scsi/scsi_tcq.h> | 16 | #include <scsi/scsi_tcq.h> |
18 | #include <scsi/scsicam.h> | 17 | #include <scsi/scsicam.h> |
19 | #include <scsi/scsi_transport.h> | 18 | #include <scsi/scsi_transport.h> |
20 | #include <scsi/scsi_transport_fc.h> | 19 | #include <scsi/scsi_transport_fc.h> |
21 | 20 | ||
21 | #include "qla_target.h" | ||
22 | |||
22 | /* | 23 | /* |
23 | * Driver version | 24 | * Driver version |
24 | */ | 25 | */ |
@@ -40,6 +41,12 @@ static struct kmem_cache *ctx_cachep; | |||
40 | */ | 41 | */ |
41 | int ql_errlev = ql_log_all; | 42 | int ql_errlev = ql_log_all; |
42 | 43 | ||
44 | int ql2xenableclass2; | ||
45 | module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR); | ||
46 | MODULE_PARM_DESC(ql2xenableclass2, | ||
47 | "Specify if Class 2 operations are supported from the very " | ||
48 | "beginning. Default is 0 - class 2 not supported."); | ||
49 | |||
43 | int ql2xlogintimeout = 20; | 50 | int ql2xlogintimeout = 20; |
44 | module_param(ql2xlogintimeout, int, S_IRUGO); | 51 | module_param(ql2xlogintimeout, int, S_IRUGO); |
45 | MODULE_PARM_DESC(ql2xlogintimeout, | 52 | MODULE_PARM_DESC(ql2xlogintimeout, |
@@ -255,6 +262,8 @@ struct scsi_host_template qla2xxx_driver_template = { | |||
255 | 262 | ||
256 | .max_sectors = 0xFFFF, | 263 | .max_sectors = 0xFFFF, |
257 | .shost_attrs = qla2x00_host_attrs, | 264 | .shost_attrs = qla2x00_host_attrs, |
265 | |||
266 | .supported_mode = MODE_INITIATOR, | ||
258 | }; | 267 | }; |
259 | 268 | ||
260 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; | 269 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; |
@@ -306,7 +315,8 @@ static void qla2x00_free_fw_dump(struct qla_hw_data *); | |||
306 | static void qla2x00_mem_free(struct qla_hw_data *); | 315 | static void qla2x00_mem_free(struct qla_hw_data *); |
307 | 316 | ||
308 | /* -------------------------------------------------------------------------- */ | 317 | /* -------------------------------------------------------------------------- */ |
309 | static int qla2x00_alloc_queues(struct qla_hw_data *ha) | 318 | static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, |
319 | struct rsp_que *rsp) | ||
310 | { | 320 | { |
311 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | 321 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); |
312 | ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues, | 322 | ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues, |
@@ -324,6 +334,12 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha) | |||
324 | "Unable to allocate memory for response queue ptrs.\n"); | 334 | "Unable to allocate memory for response queue ptrs.\n"); |
325 | goto fail_rsp_map; | 335 | goto fail_rsp_map; |
326 | } | 336 | } |
337 | /* | ||
338 | * Make sure we record at least the request and response queue zero in | ||
339 | * case we need to free them if part of the probe fails. | ||
340 | */ | ||
341 | ha->rsp_q_map[0] = rsp; | ||
342 | ha->req_q_map[0] = req; | ||
327 | set_bit(0, ha->rsp_qid_map); | 343 | set_bit(0, ha->rsp_qid_map); |
328 | set_bit(0, ha->req_qid_map); | 344 | set_bit(0, ha->req_qid_map); |
329 | return 1; | 345 | return 1; |
@@ -642,12 +658,12 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
642 | 658 | ||
643 | if (ha->flags.eeh_busy) { | 659 | if (ha->flags.eeh_busy) { |
644 | if (ha->flags.pci_channel_io_perm_failure) { | 660 | if (ha->flags.pci_channel_io_perm_failure) { |
645 | ql_dbg(ql_dbg_io, vha, 0x3001, | 661 | ql_dbg(ql_dbg_aer, vha, 0x9010, |
646 | "PCI Channel IO permanent failure, exiting " | 662 | "PCI Channel IO permanent failure, exiting " |
647 | "cmd=%p.\n", cmd); | 663 | "cmd=%p.\n", cmd); |
648 | cmd->result = DID_NO_CONNECT << 16; | 664 | cmd->result = DID_NO_CONNECT << 16; |
649 | } else { | 665 | } else { |
650 | ql_dbg(ql_dbg_io, vha, 0x3002, | 666 | ql_dbg(ql_dbg_aer, vha, 0x9011, |
651 | "EEH_Busy, Requeuing the cmd=%p.\n", cmd); | 667 | "EEH_Busy, Requeuing the cmd=%p.\n", cmd); |
652 | cmd->result = DID_REQUEUE << 16; | 668 | cmd->result = DID_REQUEUE << 16; |
653 | } | 669 | } |
@@ -657,7 +673,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
657 | rval = fc_remote_port_chkready(rport); | 673 | rval = fc_remote_port_chkready(rport); |
658 | if (rval) { | 674 | if (rval) { |
659 | cmd->result = rval; | 675 | cmd->result = rval; |
660 | ql_dbg(ql_dbg_io, vha, 0x3003, | 676 | ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3003, |
661 | "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n", | 677 | "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n", |
662 | cmd, rval); | 678 | cmd, rval); |
663 | goto qc24_fail_command; | 679 | goto qc24_fail_command; |
@@ -1136,7 +1152,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
1136 | ret = FAILED; | 1152 | ret = FAILED; |
1137 | 1153 | ||
1138 | ql_log(ql_log_info, vha, 0x8012, | 1154 | ql_log(ql_log_info, vha, 0x8012, |
1139 | "BUS RESET ISSUED nexus=%ld:%d%d.\n", vha->host_no, id, lun); | 1155 | "BUS RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); |
1140 | 1156 | ||
1141 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | 1157 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { |
1142 | ql_log(ql_log_fatal, vha, 0x8013, | 1158 | ql_log(ql_log_fatal, vha, 0x8013, |
@@ -2180,6 +2196,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2180 | ql_dbg_pci(ql_dbg_init, pdev, 0x000a, | 2196 | ql_dbg_pci(ql_dbg_init, pdev, 0x000a, |
2181 | "Memory allocated for ha=%p.\n", ha); | 2197 | "Memory allocated for ha=%p.\n", ha); |
2182 | ha->pdev = pdev; | 2198 | ha->pdev = pdev; |
2199 | ha->tgt.enable_class_2 = ql2xenableclass2; | ||
2183 | 2200 | ||
2184 | /* Clear our data area */ | 2201 | /* Clear our data area */ |
2185 | ha->bars = bars; | 2202 | ha->bars = bars; |
@@ -2243,6 +2260,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2243 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | 2260 | ha->mbx_count = MAILBOX_REGISTER_COUNT; |
2244 | req_length = REQUEST_ENTRY_CNT_24XX; | 2261 | req_length = REQUEST_ENTRY_CNT_24XX; |
2245 | rsp_length = RESPONSE_ENTRY_CNT_2300; | 2262 | rsp_length = RESPONSE_ENTRY_CNT_2300; |
2263 | ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; | ||
2246 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; | 2264 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; |
2247 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); | 2265 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); |
2248 | ha->gid_list_info_size = 8; | 2266 | ha->gid_list_info_size = 8; |
@@ -2258,6 +2276,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2258 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | 2276 | ha->mbx_count = MAILBOX_REGISTER_COUNT; |
2259 | req_length = REQUEST_ENTRY_CNT_24XX; | 2277 | req_length = REQUEST_ENTRY_CNT_24XX; |
2260 | rsp_length = RESPONSE_ENTRY_CNT_2300; | 2278 | rsp_length = RESPONSE_ENTRY_CNT_2300; |
2279 | ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; | ||
2261 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; | 2280 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; |
2262 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); | 2281 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); |
2263 | ha->gid_list_info_size = 8; | 2282 | ha->gid_list_info_size = 8; |
@@ -2417,6 +2436,17 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2417 | host->max_cmd_len, host->max_channel, host->max_lun, | 2436 | host->max_cmd_len, host->max_channel, host->max_lun, |
2418 | host->transportt, sht->vendor_id); | 2437 | host->transportt, sht->vendor_id); |
2419 | 2438 | ||
2439 | que_init: | ||
2440 | /* Alloc arrays of request and response ring ptrs */ | ||
2441 | if (!qla2x00_alloc_queues(ha, req, rsp)) { | ||
2442 | ql_log(ql_log_fatal, base_vha, 0x003d, | ||
2443 | "Failed to allocate memory for queue pointers..." | ||
2444 | "aborting.\n"); | ||
2445 | goto probe_init_failed; | ||
2446 | } | ||
2447 | |||
2448 | qlt_probe_one_stage1(base_vha, ha); | ||
2449 | |||
2420 | /* Set up the irqs */ | 2450 | /* Set up the irqs */ |
2421 | ret = qla2x00_request_irqs(ha, rsp); | 2451 | ret = qla2x00_request_irqs(ha, rsp); |
2422 | if (ret) | 2452 | if (ret) |
@@ -2424,20 +2454,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2424 | 2454 | ||
2425 | pci_save_state(pdev); | 2455 | pci_save_state(pdev); |
2426 | 2456 | ||
2427 | /* Alloc arrays of request and response ring ptrs */ | 2457 | /* Assign back pointers */ |
2428 | que_init: | ||
2429 | if (!qla2x00_alloc_queues(ha)) { | ||
2430 | ql_log(ql_log_fatal, base_vha, 0x003d, | ||
2431 | "Failed to allocate memory for queue pointers.. aborting.\n"); | ||
2432 | goto probe_init_failed; | ||
2433 | } | ||
2434 | |||
2435 | ha->rsp_q_map[0] = rsp; | ||
2436 | ha->req_q_map[0] = req; | ||
2437 | rsp->req = req; | 2458 | rsp->req = req; |
2438 | req->rsp = rsp; | 2459 | req->rsp = rsp; |
2439 | set_bit(0, ha->req_qid_map); | 2460 | |
2440 | set_bit(0, ha->rsp_qid_map); | ||
2441 | /* FWI2-capable only. */ | 2461 | /* FWI2-capable only. */ |
2442 | req->req_q_in = &ha->iobase->isp24.req_q_in; | 2462 | req->req_q_in = &ha->iobase->isp24.req_q_in; |
2443 | req->req_q_out = &ha->iobase->isp24.req_q_out; | 2463 | req->req_q_out = &ha->iobase->isp24.req_q_out; |
@@ -2514,6 +2534,14 @@ que_init: | |||
2514 | ql_dbg(ql_dbg_init, base_vha, 0x00ee, | 2534 | ql_dbg(ql_dbg_init, base_vha, 0x00ee, |
2515 | "DPC thread started successfully.\n"); | 2535 | "DPC thread started successfully.\n"); |
2516 | 2536 | ||
2537 | /* | ||
2538 | * If we're not coming up in initiator mode, we might sit for | ||
2539 | * a while without waking up the dpc thread, which leads to a | ||
2540 | * stuck process warning. So just kick the dpc once here and | ||
2541 | * let the kthread start (and go back to sleep in qla2x00_do_dpc). | ||
2542 | */ | ||
2543 | qla2xxx_wake_dpc(base_vha); | ||
2544 | |||
2517 | skip_dpc: | 2545 | skip_dpc: |
2518 | list_add_tail(&base_vha->list, &ha->vp_list); | 2546 | list_add_tail(&base_vha->list, &ha->vp_list); |
2519 | base_vha->host->irq = ha->pdev->irq; | 2547 | base_vha->host->irq = ha->pdev->irq; |
@@ -2559,7 +2587,11 @@ skip_dpc: | |||
2559 | ql_dbg(ql_dbg_init, base_vha, 0x00f2, | 2587 | ql_dbg(ql_dbg_init, base_vha, 0x00f2, |
2560 | "Init done and hba is online.\n"); | 2588 | "Init done and hba is online.\n"); |
2561 | 2589 | ||
2562 | scsi_scan_host(host); | 2590 | if (qla_ini_mode_enabled(base_vha)) |
2591 | scsi_scan_host(host); | ||
2592 | else | ||
2593 | ql_dbg(ql_dbg_init, base_vha, 0x0122, | ||
2594 | "skipping scsi_scan_host() for non-initiator port\n"); | ||
2563 | 2595 | ||
2564 | qla2x00_alloc_sysfs_attr(base_vha); | 2596 | qla2x00_alloc_sysfs_attr(base_vha); |
2565 | 2597 | ||
@@ -2577,11 +2609,17 @@ skip_dpc: | |||
2577 | base_vha->host_no, | 2609 | base_vha->host_no, |
2578 | ha->isp_ops->fw_version_str(base_vha, fw_str)); | 2610 | ha->isp_ops->fw_version_str(base_vha, fw_str)); |
2579 | 2611 | ||
2612 | qlt_add_target(ha, base_vha); | ||
2613 | |||
2580 | return 0; | 2614 | return 0; |
2581 | 2615 | ||
2582 | probe_init_failed: | 2616 | probe_init_failed: |
2583 | qla2x00_free_req_que(ha, req); | 2617 | qla2x00_free_req_que(ha, req); |
2618 | ha->req_q_map[0] = NULL; | ||
2619 | clear_bit(0, ha->req_qid_map); | ||
2584 | qla2x00_free_rsp_que(ha, rsp); | 2620 | qla2x00_free_rsp_que(ha, rsp); |
2621 | ha->rsp_q_map[0] = NULL; | ||
2622 | clear_bit(0, ha->rsp_qid_map); | ||
2585 | ha->max_req_queues = ha->max_rsp_queues = 0; | 2623 | ha->max_req_queues = ha->max_rsp_queues = 0; |
2586 | 2624 | ||
2587 | probe_failed: | 2625 | probe_failed: |
@@ -2621,6 +2659,22 @@ probe_out: | |||
2621 | } | 2659 | } |
2622 | 2660 | ||
2623 | static void | 2661 | static void |
2662 | qla2x00_stop_dpc_thread(scsi_qla_host_t *vha) | ||
2663 | { | ||
2664 | struct qla_hw_data *ha = vha->hw; | ||
2665 | struct task_struct *t = ha->dpc_thread; | ||
2666 | |||
2667 | if (ha->dpc_thread == NULL) | ||
2668 | return; | ||
2669 | /* | ||
2670 | * qla2xxx_wake_dpc checks for ->dpc_thread | ||
2671 | * so we need to zero it out. | ||
2672 | */ | ||
2673 | ha->dpc_thread = NULL; | ||
2674 | kthread_stop(t); | ||
2675 | } | ||
2676 | |||
2677 | static void | ||
2624 | qla2x00_shutdown(struct pci_dev *pdev) | 2678 | qla2x00_shutdown(struct pci_dev *pdev) |
2625 | { | 2679 | { |
2626 | scsi_qla_host_t *vha; | 2680 | scsi_qla_host_t *vha; |
@@ -2663,9 +2717,18 @@ qla2x00_remove_one(struct pci_dev *pdev) | |||
2663 | struct qla_hw_data *ha; | 2717 | struct qla_hw_data *ha; |
2664 | unsigned long flags; | 2718 | unsigned long flags; |
2665 | 2719 | ||
2720 | /* | ||
2721 | * If the PCI device is disabled that means that probe failed and any | ||
2722 | * resources should be have cleaned up on probe exit. | ||
2723 | */ | ||
2724 | if (!atomic_read(&pdev->enable_cnt)) | ||
2725 | return; | ||
2726 | |||
2666 | base_vha = pci_get_drvdata(pdev); | 2727 | base_vha = pci_get_drvdata(pdev); |
2667 | ha = base_vha->hw; | 2728 | ha = base_vha->hw; |
2668 | 2729 | ||
2730 | ha->flags.host_shutting_down = 1; | ||
2731 | |||
2669 | mutex_lock(&ha->vport_lock); | 2732 | mutex_lock(&ha->vport_lock); |
2670 | while (ha->cur_vport_count) { | 2733 | while (ha->cur_vport_count) { |
2671 | struct Scsi_Host *scsi_host; | 2734 | struct Scsi_Host *scsi_host; |
@@ -2719,6 +2782,7 @@ qla2x00_remove_one(struct pci_dev *pdev) | |||
2719 | ha->dpc_thread = NULL; | 2782 | ha->dpc_thread = NULL; |
2720 | kthread_stop(t); | 2783 | kthread_stop(t); |
2721 | } | 2784 | } |
2785 | qlt_remove_target(ha, base_vha); | ||
2722 | 2786 | ||
2723 | qla2x00_free_sysfs_attr(base_vha); | 2787 | qla2x00_free_sysfs_attr(base_vha); |
2724 | 2788 | ||
@@ -2770,17 +2834,7 @@ qla2x00_free_device(scsi_qla_host_t *vha) | |||
2770 | if (vha->timer_active) | 2834 | if (vha->timer_active) |
2771 | qla2x00_stop_timer(vha); | 2835 | qla2x00_stop_timer(vha); |
2772 | 2836 | ||
2773 | /* Kill the kernel thread for this host */ | 2837 | qla2x00_stop_dpc_thread(vha); |
2774 | if (ha->dpc_thread) { | ||
2775 | struct task_struct *t = ha->dpc_thread; | ||
2776 | |||
2777 | /* | ||
2778 | * qla2xxx_wake_dpc checks for ->dpc_thread | ||
2779 | * so we need to zero it out. | ||
2780 | */ | ||
2781 | ha->dpc_thread = NULL; | ||
2782 | kthread_stop(t); | ||
2783 | } | ||
2784 | 2838 | ||
2785 | qla25xx_delete_queues(vha); | 2839 | qla25xx_delete_queues(vha); |
2786 | 2840 | ||
@@ -2842,8 +2896,10 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
2842 | spin_unlock_irqrestore(vha->host->host_lock, flags); | 2896 | spin_unlock_irqrestore(vha->host->host_lock, flags); |
2843 | set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); | 2897 | set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); |
2844 | qla2xxx_wake_dpc(base_vha); | 2898 | qla2xxx_wake_dpc(base_vha); |
2845 | } else | 2899 | } else { |
2846 | fc_remote_port_delete(rport); | 2900 | fc_remote_port_delete(rport); |
2901 | qlt_fc_port_deleted(vha, fcport); | ||
2902 | } | ||
2847 | } | 2903 | } |
2848 | 2904 | ||
2849 | /* | 2905 | /* |
@@ -2859,7 +2915,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
2859 | int do_login, int defer) | 2915 | int do_login, int defer) |
2860 | { | 2916 | { |
2861 | if (atomic_read(&fcport->state) == FCS_ONLINE && | 2917 | if (atomic_read(&fcport->state) == FCS_ONLINE && |
2862 | vha->vp_idx == fcport->vp_idx) { | 2918 | vha->vp_idx == fcport->vha->vp_idx) { |
2863 | qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); | 2919 | qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); |
2864 | qla2x00_schedule_rport_del(vha, fcport, defer); | 2920 | qla2x00_schedule_rport_del(vha, fcport, defer); |
2865 | } | 2921 | } |
@@ -2908,7 +2964,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) | |||
2908 | fc_port_t *fcport; | 2964 | fc_port_t *fcport; |
2909 | 2965 | ||
2910 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 2966 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
2911 | if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx) | 2967 | if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx) |
2912 | continue; | 2968 | continue; |
2913 | 2969 | ||
2914 | /* | 2970 | /* |
@@ -2921,7 +2977,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) | |||
2921 | qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); | 2977 | qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); |
2922 | if (defer) | 2978 | if (defer) |
2923 | qla2x00_schedule_rport_del(vha, fcport, defer); | 2979 | qla2x00_schedule_rport_del(vha, fcport, defer); |
2924 | else if (vha->vp_idx == fcport->vp_idx) | 2980 | else if (vha->vp_idx == fcport->vha->vp_idx) |
2925 | qla2x00_schedule_rport_del(vha, fcport, defer); | 2981 | qla2x00_schedule_rport_del(vha, fcport, defer); |
2926 | } | 2982 | } |
2927 | } | 2983 | } |
@@ -2946,10 +3002,13 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, | |||
2946 | if (!ha->init_cb) | 3002 | if (!ha->init_cb) |
2947 | goto fail; | 3003 | goto fail; |
2948 | 3004 | ||
3005 | if (qlt_mem_alloc(ha) < 0) | ||
3006 | goto fail_free_init_cb; | ||
3007 | |||
2949 | ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, | 3008 | ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, |
2950 | qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL); | 3009 | qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL); |
2951 | if (!ha->gid_list) | 3010 | if (!ha->gid_list) |
2952 | goto fail_free_init_cb; | 3011 | goto fail_free_tgt_mem; |
2953 | 3012 | ||
2954 | ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); | 3013 | ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); |
2955 | if (!ha->srb_mempool) | 3014 | if (!ha->srb_mempool) |
@@ -3167,6 +3226,8 @@ fail_free_gid_list: | |||
3167 | ha->gid_list_dma); | 3226 | ha->gid_list_dma); |
3168 | ha->gid_list = NULL; | 3227 | ha->gid_list = NULL; |
3169 | ha->gid_list_dma = 0; | 3228 | ha->gid_list_dma = 0; |
3229 | fail_free_tgt_mem: | ||
3230 | qlt_mem_free(ha); | ||
3170 | fail_free_init_cb: | 3231 | fail_free_init_cb: |
3171 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, | 3232 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, |
3172 | ha->init_cb_dma); | 3233 | ha->init_cb_dma); |
@@ -3282,6 +3343,8 @@ qla2x00_mem_free(struct qla_hw_data *ha) | |||
3282 | if (ha->ctx_mempool) | 3343 | if (ha->ctx_mempool) |
3283 | mempool_destroy(ha->ctx_mempool); | 3344 | mempool_destroy(ha->ctx_mempool); |
3284 | 3345 | ||
3346 | qlt_mem_free(ha); | ||
3347 | |||
3285 | if (ha->init_cb) | 3348 | if (ha->init_cb) |
3286 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, | 3349 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, |
3287 | ha->init_cb, ha->init_cb_dma); | 3350 | ha->init_cb, ha->init_cb_dma); |
@@ -3311,6 +3374,10 @@ qla2x00_mem_free(struct qla_hw_data *ha) | |||
3311 | 3374 | ||
3312 | ha->gid_list = NULL; | 3375 | ha->gid_list = NULL; |
3313 | ha->gid_list_dma = 0; | 3376 | ha->gid_list_dma = 0; |
3377 | |||
3378 | ha->tgt.atio_ring = NULL; | ||
3379 | ha->tgt.atio_dma = 0; | ||
3380 | ha->tgt.tgt_vp_map = NULL; | ||
3314 | } | 3381 | } |
3315 | 3382 | ||
3316 | struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, | 3383 | struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, |
@@ -3671,10 +3738,9 @@ qla2x00_do_dpc(void *data) | |||
3671 | 3738 | ||
3672 | ha->dpc_active = 1; | 3739 | ha->dpc_active = 1; |
3673 | 3740 | ||
3674 | ql_dbg(ql_dbg_dpc, base_vha, 0x4001, | 3741 | ql_dbg(ql_dbg_dpc + ql_dbg_verbose, base_vha, 0x4001, |
3675 | "DPC handler waking up.\n"); | 3742 | "DPC handler waking up, dpc_flags=0x%lx.\n", |
3676 | ql_dbg(ql_dbg_dpc, base_vha, 0x4002, | 3743 | base_vha->dpc_flags); |
3677 | "dpc_flags=0x%lx.\n", base_vha->dpc_flags); | ||
3678 | 3744 | ||
3679 | qla2x00_do_work(base_vha); | 3745 | qla2x00_do_work(base_vha); |
3680 | 3746 | ||
@@ -3740,6 +3806,16 @@ qla2x00_do_dpc(void *data) | |||
3740 | clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); | 3806 | clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); |
3741 | } | 3807 | } |
3742 | 3808 | ||
3809 | if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) { | ||
3810 | int ret; | ||
3811 | ret = qla2x00_send_change_request(base_vha, 0x3, 0); | ||
3812 | if (ret != QLA_SUCCESS) | ||
3813 | ql_log(ql_log_warn, base_vha, 0x121, | ||
3814 | "Failed to enable receiving of RSCN " | ||
3815 | "requests: 0x%x.\n", ret); | ||
3816 | clear_bit(SCR_PENDING, &base_vha->dpc_flags); | ||
3817 | } | ||
3818 | |||
3743 | if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { | 3819 | if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { |
3744 | ql_dbg(ql_dbg_dpc, base_vha, 0x4009, | 3820 | ql_dbg(ql_dbg_dpc, base_vha, 0x4009, |
3745 | "Quiescence mode scheduled.\n"); | 3821 | "Quiescence mode scheduled.\n"); |
@@ -4457,6 +4533,21 @@ qla2x00_module_init(void) | |||
4457 | return -ENOMEM; | 4533 | return -ENOMEM; |
4458 | } | 4534 | } |
4459 | 4535 | ||
4536 | /* Initialize target kmem_cache and mem_pools */ | ||
4537 | ret = qlt_init(); | ||
4538 | if (ret < 0) { | ||
4539 | kmem_cache_destroy(srb_cachep); | ||
4540 | return ret; | ||
4541 | } else if (ret > 0) { | ||
4542 | /* | ||
4543 | * If initiator mode is explictly disabled by qlt_init(), | ||
4544 | * prevent scsi_transport_fc.c:fc_scsi_scan_rport() from | ||
4545 | * performing scsi_scan_target() during LOOP UP event. | ||
4546 | */ | ||
4547 | qla2xxx_transport_functions.disable_target_scan = 1; | ||
4548 | qla2xxx_transport_vport_functions.disable_target_scan = 1; | ||
4549 | } | ||
4550 | |||
4460 | /* Derive version string. */ | 4551 | /* Derive version string. */ |
4461 | strcpy(qla2x00_version_str, QLA2XXX_VERSION); | 4552 | strcpy(qla2x00_version_str, QLA2XXX_VERSION); |
4462 | if (ql2xextended_error_logging) | 4553 | if (ql2xextended_error_logging) |
@@ -4468,6 +4559,7 @@ qla2x00_module_init(void) | |||
4468 | kmem_cache_destroy(srb_cachep); | 4559 | kmem_cache_destroy(srb_cachep); |
4469 | ql_log(ql_log_fatal, NULL, 0x0002, | 4560 | ql_log(ql_log_fatal, NULL, 0x0002, |
4470 | "fc_attach_transport failed...Failing load!.\n"); | 4561 | "fc_attach_transport failed...Failing load!.\n"); |
4562 | qlt_exit(); | ||
4471 | return -ENODEV; | 4563 | return -ENODEV; |
4472 | } | 4564 | } |
4473 | 4565 | ||
@@ -4481,6 +4573,7 @@ qla2x00_module_init(void) | |||
4481 | fc_attach_transport(&qla2xxx_transport_vport_functions); | 4573 | fc_attach_transport(&qla2xxx_transport_vport_functions); |
4482 | if (!qla2xxx_transport_vport_template) { | 4574 | if (!qla2xxx_transport_vport_template) { |
4483 | kmem_cache_destroy(srb_cachep); | 4575 | kmem_cache_destroy(srb_cachep); |
4576 | qlt_exit(); | ||
4484 | fc_release_transport(qla2xxx_transport_template); | 4577 | fc_release_transport(qla2xxx_transport_template); |
4485 | ql_log(ql_log_fatal, NULL, 0x0004, | 4578 | ql_log(ql_log_fatal, NULL, 0x0004, |
4486 | "fc_attach_transport vport failed...Failing load!.\n"); | 4579 | "fc_attach_transport vport failed...Failing load!.\n"); |
@@ -4492,6 +4585,7 @@ qla2x00_module_init(void) | |||
4492 | ret = pci_register_driver(&qla2xxx_pci_driver); | 4585 | ret = pci_register_driver(&qla2xxx_pci_driver); |
4493 | if (ret) { | 4586 | if (ret) { |
4494 | kmem_cache_destroy(srb_cachep); | 4587 | kmem_cache_destroy(srb_cachep); |
4588 | qlt_exit(); | ||
4495 | fc_release_transport(qla2xxx_transport_template); | 4589 | fc_release_transport(qla2xxx_transport_template); |
4496 | fc_release_transport(qla2xxx_transport_vport_template); | 4590 | fc_release_transport(qla2xxx_transport_vport_template); |
4497 | ql_log(ql_log_fatal, NULL, 0x0006, | 4591 | ql_log(ql_log_fatal, NULL, 0x0006, |
@@ -4511,6 +4605,7 @@ qla2x00_module_exit(void) | |||
4511 | pci_unregister_driver(&qla2xxx_pci_driver); | 4605 | pci_unregister_driver(&qla2xxx_pci_driver); |
4512 | qla2x00_release_firmware(); | 4606 | qla2x00_release_firmware(); |
4513 | kmem_cache_destroy(srb_cachep); | 4607 | kmem_cache_destroy(srb_cachep); |
4608 | qlt_exit(); | ||
4514 | if (ctx_cachep) | 4609 | if (ctx_cachep) |
4515 | kmem_cache_destroy(ctx_cachep); | 4610 | kmem_cache_destroy(ctx_cachep); |
4516 | fc_release_transport(qla2xxx_transport_template); | 4611 | fc_release_transport(qla2xxx_transport_template); |
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c new file mode 100644 index 000000000000..04f80ebf09eb --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
@@ -0,0 +1,4973 @@ | |||
1 | /* | ||
2 | * qla_target.c SCSI LLD infrastructure for QLogic 22xx/23xx/24xx/25xx | ||
3 | * | ||
4 | * based on qla2x00t.c code: | ||
5 | * | ||
6 | * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net> | ||
7 | * Copyright (C) 2004 - 2005 Leonid Stoljar | ||
8 | * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us> | ||
9 | * Copyright (C) 2006 - 2010 ID7 Ltd. | ||
10 | * | ||
11 | * Forward port and refactoring to modern qla2xxx and target/configfs | ||
12 | * | ||
13 | * Copyright (C) 2010-2011 Nicholas A. Bellinger <nab@kernel.org> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation, version 2 | ||
18 | * of the License. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <linux/version.h> | ||
30 | #include <linux/blkdev.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/list.h> | ||
35 | #include <linux/workqueue.h> | ||
36 | #include <asm/unaligned.h> | ||
37 | #include <scsi/scsi.h> | ||
38 | #include <scsi/scsi_host.h> | ||
39 | #include <scsi/scsi_tcq.h> | ||
40 | #include <target/target_core_base.h> | ||
41 | #include <target/target_core_fabric.h> | ||
42 | |||
43 | #include "qla_def.h" | ||
44 | #include "qla_target.h" | ||
45 | |||
46 | static char *qlini_mode = QLA2XXX_INI_MODE_STR_ENABLED; | ||
47 | module_param(qlini_mode, charp, S_IRUGO); | ||
48 | MODULE_PARM_DESC(qlini_mode, | ||
49 | "Determines when initiator mode will be enabled. Possible values: " | ||
50 | "\"exclusive\" - initiator mode will be enabled on load, " | ||
51 | "disabled on enabling target mode and then on disabling target mode " | ||
52 | "enabled back; " | ||
53 | "\"disabled\" - initiator mode will never be enabled; " | ||
54 | "\"enabled\" (default) - initiator mode will always stay enabled."); | ||
55 | |||
56 | static int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE; | ||
57 | |||
58 | /* | ||
59 | * From scsi/fc/fc_fcp.h | ||
60 | */ | ||
61 | enum fcp_resp_rsp_codes { | ||
62 | FCP_TMF_CMPL = 0, | ||
63 | FCP_DATA_LEN_INVALID = 1, | ||
64 | FCP_CMND_FIELDS_INVALID = 2, | ||
65 | FCP_DATA_PARAM_MISMATCH = 3, | ||
66 | FCP_TMF_REJECTED = 4, | ||
67 | FCP_TMF_FAILED = 5, | ||
68 | FCP_TMF_INVALID_LUN = 9, | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * fc_pri_ta from scsi/fc/fc_fcp.h | ||
73 | */ | ||
74 | #define FCP_PTA_SIMPLE 0 /* simple task attribute */ | ||
75 | #define FCP_PTA_HEADQ 1 /* head of queue task attribute */ | ||
76 | #define FCP_PTA_ORDERED 2 /* ordered task attribute */ | ||
77 | #define FCP_PTA_ACA 4 /* auto. contigent allegiance */ | ||
78 | #define FCP_PTA_MASK 7 /* mask for task attribute field */ | ||
79 | #define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */ | ||
80 | #define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */ | ||
81 | |||
82 | /* | ||
83 | * This driver calls qla2x00_alloc_iocbs() and qla2x00_issue_marker(), which | ||
84 | * must be called under HW lock and could unlock/lock it inside. | ||
85 | * It isn't an issue, since in the current implementation on the time when | ||
86 | * those functions are called: | ||
87 | * | ||
88 | * - Either context is IRQ and only IRQ handler can modify HW data, | ||
89 | * including rings related fields, | ||
90 | * | ||
91 | * - Or access to target mode variables from struct qla_tgt doesn't | ||
92 | * cross those functions boundaries, except tgt_stop, which | ||
93 | * additionally protected by irq_cmd_count. | ||
94 | */ | ||
95 | /* Predefs for callbacks handed to qla2xxx LLD */ | ||
96 | static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha, | ||
97 | struct atio_from_isp *pkt); | ||
98 | static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); | ||
99 | static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, | ||
100 | int fn, void *iocb, int flags); | ||
101 | static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd | ||
102 | *cmd, struct atio_from_isp *atio, int ha_locked); | ||
103 | static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha, | ||
104 | struct qla_tgt_srr_imm *imm, int ha_lock); | ||
105 | /* | ||
106 | * Global Variables | ||
107 | */ | ||
108 | static struct kmem_cache *qla_tgt_cmd_cachep; | ||
109 | static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; | ||
110 | static mempool_t *qla_tgt_mgmt_cmd_mempool; | ||
111 | static struct workqueue_struct *qla_tgt_wq; | ||
112 | static DEFINE_MUTEX(qla_tgt_mutex); | ||
113 | static LIST_HEAD(qla_tgt_glist); | ||
114 | |||
115 | /* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */ | ||
116 | static struct qla_tgt_sess *qlt_find_sess_by_port_name( | ||
117 | struct qla_tgt *tgt, | ||
118 | const uint8_t *port_name) | ||
119 | { | ||
120 | struct qla_tgt_sess *sess; | ||
121 | |||
122 | list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { | ||
123 | if (!memcmp(sess->port_name, port_name, WWN_SIZE)) | ||
124 | return sess; | ||
125 | } | ||
126 | |||
127 | return NULL; | ||
128 | } | ||
129 | |||
130 | /* Might release hw lock, then reaquire!! */ | ||
131 | static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked) | ||
132 | { | ||
133 | /* Send marker if required */ | ||
134 | if (unlikely(vha->marker_needed != 0)) { | ||
135 | int rc = qla2x00_issue_marker(vha, vha_locked); | ||
136 | if (rc != QLA_SUCCESS) { | ||
137 | ql_dbg(ql_dbg_tgt, vha, 0xe03d, | ||
138 | "qla_target(%d): issue_marker() failed\n", | ||
139 | vha->vp_idx); | ||
140 | } | ||
141 | return rc; | ||
142 | } | ||
143 | return QLA_SUCCESS; | ||
144 | } | ||
145 | |||
146 | static inline | ||
147 | struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha, | ||
148 | uint8_t *d_id) | ||
149 | { | ||
150 | struct qla_hw_data *ha = vha->hw; | ||
151 | uint8_t vp_idx; | ||
152 | |||
153 | if ((vha->d_id.b.area != d_id[1]) || (vha->d_id.b.domain != d_id[0])) | ||
154 | return NULL; | ||
155 | |||
156 | if (vha->d_id.b.al_pa == d_id[2]) | ||
157 | return vha; | ||
158 | |||
159 | BUG_ON(ha->tgt.tgt_vp_map == NULL); | ||
160 | vp_idx = ha->tgt.tgt_vp_map[d_id[2]].idx; | ||
161 | if (likely(test_bit(vp_idx, ha->vp_idx_map))) | ||
162 | return ha->tgt.tgt_vp_map[vp_idx].vha; | ||
163 | |||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | static inline | ||
168 | struct scsi_qla_host *qlt_find_host_by_vp_idx(struct scsi_qla_host *vha, | ||
169 | uint16_t vp_idx) | ||
170 | { | ||
171 | struct qla_hw_data *ha = vha->hw; | ||
172 | |||
173 | if (vha->vp_idx == vp_idx) | ||
174 | return vha; | ||
175 | |||
176 | BUG_ON(ha->tgt.tgt_vp_map == NULL); | ||
177 | if (likely(test_bit(vp_idx, ha->vp_idx_map))) | ||
178 | return ha->tgt.tgt_vp_map[vp_idx].vha; | ||
179 | |||
180 | return NULL; | ||
181 | } | ||
182 | |||
183 | void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, | ||
184 | struct atio_from_isp *atio) | ||
185 | { | ||
186 | switch (atio->u.raw.entry_type) { | ||
187 | case ATIO_TYPE7: | ||
188 | { | ||
189 | struct scsi_qla_host *host = qlt_find_host_by_d_id(vha, | ||
190 | atio->u.isp24.fcp_hdr.d_id); | ||
191 | if (unlikely(NULL == host)) { | ||
192 | ql_dbg(ql_dbg_tgt, vha, 0xe03e, | ||
193 | "qla_target(%d): Received ATIO_TYPE7 " | ||
194 | "with unknown d_id %x:%x:%x\n", vha->vp_idx, | ||
195 | atio->u.isp24.fcp_hdr.d_id[0], | ||
196 | atio->u.isp24.fcp_hdr.d_id[1], | ||
197 | atio->u.isp24.fcp_hdr.d_id[2]); | ||
198 | break; | ||
199 | } | ||
200 | qlt_24xx_atio_pkt(host, atio); | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | case IMMED_NOTIFY_TYPE: | ||
205 | { | ||
206 | struct scsi_qla_host *host = vha; | ||
207 | struct imm_ntfy_from_isp *entry = | ||
208 | (struct imm_ntfy_from_isp *)atio; | ||
209 | |||
210 | if ((entry->u.isp24.vp_index != 0xFF) && | ||
211 | (entry->u.isp24.nport_handle != 0xFFFF)) { | ||
212 | host = qlt_find_host_by_vp_idx(vha, | ||
213 | entry->u.isp24.vp_index); | ||
214 | if (unlikely(!host)) { | ||
215 | ql_dbg(ql_dbg_tgt, vha, 0xe03f, | ||
216 | "qla_target(%d): Received " | ||
217 | "ATIO (IMMED_NOTIFY_TYPE) " | ||
218 | "with unknown vp_index %d\n", | ||
219 | vha->vp_idx, entry->u.isp24.vp_index); | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | qlt_24xx_atio_pkt(host, atio); | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | default: | ||
228 | ql_dbg(ql_dbg_tgt, vha, 0xe040, | ||
229 | "qla_target(%d): Received unknown ATIO atio " | ||
230 | "type %x\n", vha->vp_idx, atio->u.raw.entry_type); | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | return; | ||
235 | } | ||
236 | |||
237 | void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) | ||
238 | { | ||
239 | switch (pkt->entry_type) { | ||
240 | case CTIO_TYPE7: | ||
241 | { | ||
242 | struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; | ||
243 | struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha, | ||
244 | entry->vp_index); | ||
245 | if (unlikely(!host)) { | ||
246 | ql_dbg(ql_dbg_tgt, vha, 0xe041, | ||
247 | "qla_target(%d): Response pkt (CTIO_TYPE7) " | ||
248 | "received, with unknown vp_index %d\n", | ||
249 | vha->vp_idx, entry->vp_index); | ||
250 | break; | ||
251 | } | ||
252 | qlt_response_pkt(host, pkt); | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | case IMMED_NOTIFY_TYPE: | ||
257 | { | ||
258 | struct scsi_qla_host *host = vha; | ||
259 | struct imm_ntfy_from_isp *entry = | ||
260 | (struct imm_ntfy_from_isp *)pkt; | ||
261 | |||
262 | host = qlt_find_host_by_vp_idx(vha, entry->u.isp24.vp_index); | ||
263 | if (unlikely(!host)) { | ||
264 | ql_dbg(ql_dbg_tgt, vha, 0xe042, | ||
265 | "qla_target(%d): Response pkt (IMMED_NOTIFY_TYPE) " | ||
266 | "received, with unknown vp_index %d\n", | ||
267 | vha->vp_idx, entry->u.isp24.vp_index); | ||
268 | break; | ||
269 | } | ||
270 | qlt_response_pkt(host, pkt); | ||
271 | break; | ||
272 | } | ||
273 | |||
274 | case NOTIFY_ACK_TYPE: | ||
275 | { | ||
276 | struct scsi_qla_host *host = vha; | ||
277 | struct nack_to_isp *entry = (struct nack_to_isp *)pkt; | ||
278 | |||
279 | if (0xFF != entry->u.isp24.vp_index) { | ||
280 | host = qlt_find_host_by_vp_idx(vha, | ||
281 | entry->u.isp24.vp_index); | ||
282 | if (unlikely(!host)) { | ||
283 | ql_dbg(ql_dbg_tgt, vha, 0xe043, | ||
284 | "qla_target(%d): Response " | ||
285 | "pkt (NOTIFY_ACK_TYPE) " | ||
286 | "received, with unknown " | ||
287 | "vp_index %d\n", vha->vp_idx, | ||
288 | entry->u.isp24.vp_index); | ||
289 | break; | ||
290 | } | ||
291 | } | ||
292 | qlt_response_pkt(host, pkt); | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | case ABTS_RECV_24XX: | ||
297 | { | ||
298 | struct abts_recv_from_24xx *entry = | ||
299 | (struct abts_recv_from_24xx *)pkt; | ||
300 | struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha, | ||
301 | entry->vp_index); | ||
302 | if (unlikely(!host)) { | ||
303 | ql_dbg(ql_dbg_tgt, vha, 0xe044, | ||
304 | "qla_target(%d): Response pkt " | ||
305 | "(ABTS_RECV_24XX) received, with unknown " | ||
306 | "vp_index %d\n", vha->vp_idx, entry->vp_index); | ||
307 | break; | ||
308 | } | ||
309 | qlt_response_pkt(host, pkt); | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | case ABTS_RESP_24XX: | ||
314 | { | ||
315 | struct abts_resp_to_24xx *entry = | ||
316 | (struct abts_resp_to_24xx *)pkt; | ||
317 | struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha, | ||
318 | entry->vp_index); | ||
319 | if (unlikely(!host)) { | ||
320 | ql_dbg(ql_dbg_tgt, vha, 0xe045, | ||
321 | "qla_target(%d): Response pkt " | ||
322 | "(ABTS_RECV_24XX) received, with unknown " | ||
323 | "vp_index %d\n", vha->vp_idx, entry->vp_index); | ||
324 | break; | ||
325 | } | ||
326 | qlt_response_pkt(host, pkt); | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | default: | ||
331 | qlt_response_pkt(vha, pkt); | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | } | ||
336 | |||
337 | static void qlt_free_session_done(struct work_struct *work) | ||
338 | { | ||
339 | struct qla_tgt_sess *sess = container_of(work, struct qla_tgt_sess, | ||
340 | free_work); | ||
341 | struct qla_tgt *tgt = sess->tgt; | ||
342 | struct scsi_qla_host *vha = sess->vha; | ||
343 | struct qla_hw_data *ha = vha->hw; | ||
344 | |||
345 | BUG_ON(!tgt); | ||
346 | /* | ||
347 | * Release the target session for FC Nexus from fabric module code. | ||
348 | */ | ||
349 | if (sess->se_sess != NULL) | ||
350 | ha->tgt.tgt_ops->free_session(sess); | ||
351 | |||
352 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, | ||
353 | "Unregistration of sess %p finished\n", sess); | ||
354 | |||
355 | kfree(sess); | ||
356 | /* | ||
357 | * We need to protect against race, when tgt is freed before or | ||
358 | * inside wake_up() | ||
359 | */ | ||
360 | tgt->sess_count--; | ||
361 | if (tgt->sess_count == 0) | ||
362 | wake_up_all(&tgt->waitQ); | ||
363 | } | ||
364 | |||
365 | /* ha->hardware_lock supposed to be held on entry */ | ||
366 | void qlt_unreg_sess(struct qla_tgt_sess *sess) | ||
367 | { | ||
368 | struct scsi_qla_host *vha = sess->vha; | ||
369 | |||
370 | vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); | ||
371 | |||
372 | list_del(&sess->sess_list_entry); | ||
373 | if (sess->deleted) | ||
374 | list_del(&sess->del_list_entry); | ||
375 | |||
376 | INIT_WORK(&sess->free_work, qlt_free_session_done); | ||
377 | schedule_work(&sess->free_work); | ||
378 | } | ||
379 | EXPORT_SYMBOL(qlt_unreg_sess); | ||
380 | |||
381 | /* ha->hardware_lock supposed to be held on entry */ | ||
382 | static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) | ||
383 | { | ||
384 | struct qla_hw_data *ha = vha->hw; | ||
385 | struct qla_tgt_sess *sess = NULL; | ||
386 | uint32_t unpacked_lun, lun = 0; | ||
387 | uint16_t loop_id; | ||
388 | int res = 0; | ||
389 | struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb; | ||
390 | struct atio_from_isp *a = (struct atio_from_isp *)iocb; | ||
391 | |||
392 | loop_id = le16_to_cpu(n->u.isp24.nport_handle); | ||
393 | if (loop_id == 0xFFFF) { | ||
394 | #if 0 /* FIXME: Re-enable Global event handling.. */ | ||
395 | /* Global event */ | ||
396 | atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); | ||
397 | qlt_clear_tgt_db(ha->tgt.qla_tgt, 1); | ||
398 | if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { | ||
399 | sess = list_entry(ha->tgt.qla_tgt->sess_list.next, | ||
400 | typeof(*sess), sess_list_entry); | ||
401 | switch (mcmd) { | ||
402 | case QLA_TGT_NEXUS_LOSS_SESS: | ||
403 | mcmd = QLA_TGT_NEXUS_LOSS; | ||
404 | break; | ||
405 | case QLA_TGT_ABORT_ALL_SESS: | ||
406 | mcmd = QLA_TGT_ABORT_ALL; | ||
407 | break; | ||
408 | case QLA_TGT_NEXUS_LOSS: | ||
409 | case QLA_TGT_ABORT_ALL: | ||
410 | break; | ||
411 | default: | ||
412 | ql_dbg(ql_dbg_tgt, vha, 0xe046, | ||
413 | "qla_target(%d): Not allowed " | ||
414 | "command %x in %s", vha->vp_idx, | ||
415 | mcmd, __func__); | ||
416 | sess = NULL; | ||
417 | break; | ||
418 | } | ||
419 | } else | ||
420 | sess = NULL; | ||
421 | #endif | ||
422 | } else { | ||
423 | sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); | ||
424 | } | ||
425 | |||
426 | ql_dbg(ql_dbg_tgt, vha, 0xe000, | ||
427 | "Using sess for qla_tgt_reset: %p\n", sess); | ||
428 | if (!sess) { | ||
429 | res = -ESRCH; | ||
430 | return res; | ||
431 | } | ||
432 | |||
433 | ql_dbg(ql_dbg_tgt, vha, 0xe047, | ||
434 | "scsi(%ld): resetting (session %p from port " | ||
435 | "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, " | ||
436 | "mcmd %x, loop_id %d)\n", vha->host_no, sess, | ||
437 | sess->port_name[0], sess->port_name[1], | ||
438 | sess->port_name[2], sess->port_name[3], | ||
439 | sess->port_name[4], sess->port_name[5], | ||
440 | sess->port_name[6], sess->port_name[7], | ||
441 | mcmd, loop_id); | ||
442 | |||
443 | lun = a->u.isp24.fcp_cmnd.lun; | ||
444 | unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); | ||
445 | |||
446 | return qlt_issue_task_mgmt(sess, unpacked_lun, mcmd, | ||
447 | iocb, QLA24XX_MGMT_SEND_NACK); | ||
448 | } | ||
449 | |||
450 | /* ha->hardware_lock supposed to be held on entry */ | ||
451 | static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, | ||
452 | bool immediate) | ||
453 | { | ||
454 | struct qla_tgt *tgt = sess->tgt; | ||
455 | uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5; | ||
456 | |||
457 | if (sess->deleted) | ||
458 | return; | ||
459 | |||
460 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, | ||
461 | "Scheduling sess %p for deletion\n", sess); | ||
462 | list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); | ||
463 | sess->deleted = 1; | ||
464 | |||
465 | if (immediate) | ||
466 | dev_loss_tmo = 0; | ||
467 | |||
468 | sess->expires = jiffies + dev_loss_tmo * HZ; | ||
469 | |||
470 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe048, | ||
471 | "qla_target(%d): session for port %02x:%02x:%02x:" | ||
472 | "%02x:%02x:%02x:%02x:%02x (loop ID %d) scheduled for " | ||
473 | "deletion in %u secs (expires: %lu) immed: %d\n", | ||
474 | sess->vha->vp_idx, | ||
475 | sess->port_name[0], sess->port_name[1], | ||
476 | sess->port_name[2], sess->port_name[3], | ||
477 | sess->port_name[4], sess->port_name[5], | ||
478 | sess->port_name[6], sess->port_name[7], | ||
479 | sess->loop_id, dev_loss_tmo, sess->expires, immediate); | ||
480 | |||
481 | if (immediate) | ||
482 | schedule_delayed_work(&tgt->sess_del_work, 0); | ||
483 | else | ||
484 | schedule_delayed_work(&tgt->sess_del_work, | ||
485 | jiffies - sess->expires); | ||
486 | } | ||
487 | |||
488 | /* ha->hardware_lock supposed to be held on entry */ | ||
489 | static void qlt_clear_tgt_db(struct qla_tgt *tgt, bool local_only) | ||
490 | { | ||
491 | struct qla_tgt_sess *sess; | ||
492 | |||
493 | list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) | ||
494 | qlt_schedule_sess_for_deletion(sess, true); | ||
495 | |||
496 | /* At this point tgt could be already dead */ | ||
497 | } | ||
498 | |||
499 | static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, | ||
500 | uint16_t *loop_id) | ||
501 | { | ||
502 | struct qla_hw_data *ha = vha->hw; | ||
503 | dma_addr_t gid_list_dma; | ||
504 | struct gid_list_info *gid_list; | ||
505 | char *id_iter; | ||
506 | int res, rc, i; | ||
507 | uint16_t entries; | ||
508 | |||
509 | gid_list = dma_alloc_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), | ||
510 | &gid_list_dma, GFP_KERNEL); | ||
511 | if (!gid_list) { | ||
512 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf044, | ||
513 | "qla_target(%d): DMA Alloc failed of %u\n", | ||
514 | vha->vp_idx, qla2x00_gid_list_size(ha)); | ||
515 | return -ENOMEM; | ||
516 | } | ||
517 | |||
518 | /* Get list of logged in devices */ | ||
519 | rc = qla2x00_get_id_list(vha, gid_list, gid_list_dma, &entries); | ||
520 | if (rc != QLA_SUCCESS) { | ||
521 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf045, | ||
522 | "qla_target(%d): get_id_list() failed: %x\n", | ||
523 | vha->vp_idx, rc); | ||
524 | res = -1; | ||
525 | goto out_free_id_list; | ||
526 | } | ||
527 | |||
528 | id_iter = (char *)gid_list; | ||
529 | res = -1; | ||
530 | for (i = 0; i < entries; i++) { | ||
531 | struct gid_list_info *gid = (struct gid_list_info *)id_iter; | ||
532 | if ((gid->al_pa == s_id[2]) && | ||
533 | (gid->area == s_id[1]) && | ||
534 | (gid->domain == s_id[0])) { | ||
535 | *loop_id = le16_to_cpu(gid->loop_id); | ||
536 | res = 0; | ||
537 | break; | ||
538 | } | ||
539 | id_iter += ha->gid_list_info_size; | ||
540 | } | ||
541 | |||
542 | out_free_id_list: | ||
543 | dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), | ||
544 | gid_list, gid_list_dma); | ||
545 | return res; | ||
546 | } | ||
547 | |||
548 | static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, | ||
549 | struct qla_tgt_sess *sess) | ||
550 | { | ||
551 | struct qla_hw_data *ha = vha->hw; | ||
552 | struct qla_port_24xx_data *pmap24; | ||
553 | bool res, found = false; | ||
554 | int rc, i; | ||
555 | uint16_t loop_id = 0xFFFF; /* to eliminate compiler's warning */ | ||
556 | uint16_t entries; | ||
557 | void *pmap; | ||
558 | int pmap_len; | ||
559 | fc_port_t *fcport; | ||
560 | int global_resets; | ||
561 | |||
562 | retry: | ||
563 | global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); | ||
564 | |||
565 | rc = qla2x00_get_node_name_list(vha, &pmap, &pmap_len); | ||
566 | if (rc != QLA_SUCCESS) { | ||
567 | res = false; | ||
568 | goto out; | ||
569 | } | ||
570 | |||
571 | pmap24 = pmap; | ||
572 | entries = pmap_len/sizeof(*pmap24); | ||
573 | |||
574 | for (i = 0; i < entries; ++i) { | ||
575 | if (!memcmp(sess->port_name, pmap24[i].port_name, WWN_SIZE)) { | ||
576 | loop_id = le16_to_cpu(pmap24[i].loop_id); | ||
577 | found = true; | ||
578 | break; | ||
579 | } | ||
580 | } | ||
581 | |||
582 | kfree(pmap); | ||
583 | |||
584 | if (!found) { | ||
585 | res = false; | ||
586 | goto out; | ||
587 | } | ||
588 | |||
589 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf046, | ||
590 | "qlt_check_fcport_exist(): loop_id %d", loop_id); | ||
591 | |||
592 | fcport = kzalloc(sizeof(*fcport), GFP_KERNEL); | ||
593 | if (fcport == NULL) { | ||
594 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf047, | ||
595 | "qla_target(%d): Allocation of tmp FC port failed", | ||
596 | vha->vp_idx); | ||
597 | res = false; | ||
598 | goto out; | ||
599 | } | ||
600 | |||
601 | fcport->loop_id = loop_id; | ||
602 | |||
603 | rc = qla2x00_get_port_database(vha, fcport, 0); | ||
604 | if (rc != QLA_SUCCESS) { | ||
605 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf048, | ||
606 | "qla_target(%d): Failed to retrieve fcport " | ||
607 | "information -- get_port_database() returned %x " | ||
608 | "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id); | ||
609 | res = false; | ||
610 | goto out_free_fcport; | ||
611 | } | ||
612 | |||
613 | if (global_resets != | ||
614 | atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) { | ||
615 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002, | ||
616 | "qla_target(%d): global reset during session discovery" | ||
617 | " (counter was %d, new %d), retrying", | ||
618 | vha->vp_idx, global_resets, | ||
619 | atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)); | ||
620 | goto retry; | ||
621 | } | ||
622 | |||
623 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003, | ||
624 | "Updating sess %p s_id %x:%x:%x, loop_id %d) to d_id %x:%x:%x, " | ||
625 | "loop_id %d", sess, sess->s_id.b.domain, sess->s_id.b.al_pa, | ||
626 | sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, | ||
627 | fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); | ||
628 | |||
629 | sess->s_id = fcport->d_id; | ||
630 | sess->loop_id = fcport->loop_id; | ||
631 | sess->conf_compl_supported = !!(fcport->flags & | ||
632 | FCF_CONF_COMP_SUPPORTED); | ||
633 | |||
634 | res = true; | ||
635 | |||
636 | out_free_fcport: | ||
637 | kfree(fcport); | ||
638 | |||
639 | out: | ||
640 | return res; | ||
641 | } | ||
642 | |||
643 | /* ha->hardware_lock supposed to be held on entry */ | ||
644 | static void qlt_undelete_sess(struct qla_tgt_sess *sess) | ||
645 | { | ||
646 | BUG_ON(!sess->deleted); | ||
647 | |||
648 | list_del(&sess->del_list_entry); | ||
649 | sess->deleted = 0; | ||
650 | } | ||
651 | |||
652 | static void qlt_del_sess_work_fn(struct delayed_work *work) | ||
653 | { | ||
654 | struct qla_tgt *tgt = container_of(work, struct qla_tgt, | ||
655 | sess_del_work); | ||
656 | struct scsi_qla_host *vha = tgt->vha; | ||
657 | struct qla_hw_data *ha = vha->hw; | ||
658 | struct qla_tgt_sess *sess; | ||
659 | unsigned long flags; | ||
660 | |||
661 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
662 | while (!list_empty(&tgt->del_sess_list)) { | ||
663 | sess = list_entry(tgt->del_sess_list.next, typeof(*sess), | ||
664 | del_list_entry); | ||
665 | if (time_after_eq(jiffies, sess->expires)) { | ||
666 | bool cancel; | ||
667 | |||
668 | qlt_undelete_sess(sess); | ||
669 | |||
670 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
671 | cancel = qlt_check_fcport_exist(vha, sess); | ||
672 | |||
673 | if (cancel) { | ||
674 | if (sess->deleted) { | ||
675 | /* | ||
676 | * sess was again deleted while we were | ||
677 | * discovering it | ||
678 | */ | ||
679 | spin_lock_irqsave(&ha->hardware_lock, | ||
680 | flags); | ||
681 | continue; | ||
682 | } | ||
683 | |||
684 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf049, | ||
685 | "qla_target(%d): cancel deletion of " | ||
686 | "session for port %02x:%02x:%02x:%02x:%02x:" | ||
687 | "%02x:%02x:%02x (loop ID %d), because " | ||
688 | " it isn't deleted by firmware", | ||
689 | vha->vp_idx, sess->port_name[0], | ||
690 | sess->port_name[1], sess->port_name[2], | ||
691 | sess->port_name[3], sess->port_name[4], | ||
692 | sess->port_name[5], sess->port_name[6], | ||
693 | sess->port_name[7], sess->loop_id); | ||
694 | } else { | ||
695 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, | ||
696 | "Timeout: sess %p about to be deleted\n", | ||
697 | sess); | ||
698 | ha->tgt.tgt_ops->shutdown_sess(sess); | ||
699 | ha->tgt.tgt_ops->put_sess(sess); | ||
700 | } | ||
701 | |||
702 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
703 | } else { | ||
704 | schedule_delayed_work(&tgt->sess_del_work, | ||
705 | jiffies - sess->expires); | ||
706 | break; | ||
707 | } | ||
708 | } | ||
709 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * Adds an extra ref to allow to drop hw lock after adding sess to the list. | ||
714 | * Caller must put it. | ||
715 | */ | ||
716 | static struct qla_tgt_sess *qlt_create_sess( | ||
717 | struct scsi_qla_host *vha, | ||
718 | fc_port_t *fcport, | ||
719 | bool local) | ||
720 | { | ||
721 | struct qla_hw_data *ha = vha->hw; | ||
722 | struct qla_tgt_sess *sess; | ||
723 | unsigned long flags; | ||
724 | unsigned char be_sid[3]; | ||
725 | |||
726 | /* Check to avoid double sessions */ | ||
727 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
728 | list_for_each_entry(sess, &ha->tgt.qla_tgt->sess_list, | ||
729 | sess_list_entry) { | ||
730 | if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) { | ||
731 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005, | ||
732 | "Double sess %p found (s_id %x:%x:%x, " | ||
733 | "loop_id %d), updating to d_id %x:%x:%x, " | ||
734 | "loop_id %d", sess, sess->s_id.b.domain, | ||
735 | sess->s_id.b.al_pa, sess->s_id.b.area, | ||
736 | sess->loop_id, fcport->d_id.b.domain, | ||
737 | fcport->d_id.b.al_pa, fcport->d_id.b.area, | ||
738 | fcport->loop_id); | ||
739 | |||
740 | if (sess->deleted) | ||
741 | qlt_undelete_sess(sess); | ||
742 | |||
743 | kref_get(&sess->se_sess->sess_kref); | ||
744 | sess->s_id = fcport->d_id; | ||
745 | sess->loop_id = fcport->loop_id; | ||
746 | sess->conf_compl_supported = !!(fcport->flags & | ||
747 | FCF_CONF_COMP_SUPPORTED); | ||
748 | if (sess->local && !local) | ||
749 | sess->local = 0; | ||
750 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
751 | |||
752 | return sess; | ||
753 | } | ||
754 | } | ||
755 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
756 | |||
757 | sess = kzalloc(sizeof(*sess), GFP_KERNEL); | ||
758 | if (!sess) { | ||
759 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04a, | ||
760 | "qla_target(%u): session allocation failed, " | ||
761 | "all commands from port %02x:%02x:%02x:%02x:" | ||
762 | "%02x:%02x:%02x:%02x will be refused", vha->vp_idx, | ||
763 | fcport->port_name[0], fcport->port_name[1], | ||
764 | fcport->port_name[2], fcport->port_name[3], | ||
765 | fcport->port_name[4], fcport->port_name[5], | ||
766 | fcport->port_name[6], fcport->port_name[7]); | ||
767 | |||
768 | return NULL; | ||
769 | } | ||
770 | sess->tgt = ha->tgt.qla_tgt; | ||
771 | sess->vha = vha; | ||
772 | sess->s_id = fcport->d_id; | ||
773 | sess->loop_id = fcport->loop_id; | ||
774 | sess->local = local; | ||
775 | |||
776 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, | ||
777 | "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", | ||
778 | sess, ha->tgt.qla_tgt); | ||
779 | |||
780 | be_sid[0] = sess->s_id.b.domain; | ||
781 | be_sid[1] = sess->s_id.b.area; | ||
782 | be_sid[2] = sess->s_id.b.al_pa; | ||
783 | /* | ||
784 | * Determine if this fc_port->port_name is allowed to access | ||
785 | * target mode using explict NodeACLs+MappedLUNs, or using | ||
786 | * TPG demo mode. If this is successful a target mode FC nexus | ||
787 | * is created. | ||
788 | */ | ||
789 | if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, | ||
790 | &fcport->port_name[0], sess, &be_sid[0], fcport->loop_id) < 0) { | ||
791 | kfree(sess); | ||
792 | return NULL; | ||
793 | } | ||
794 | /* | ||
795 | * Take an extra reference to ->sess_kref here to handle qla_tgt_sess | ||
796 | * access across ->hardware_lock reaquire. | ||
797 | */ | ||
798 | kref_get(&sess->se_sess->sess_kref); | ||
799 | |||
800 | sess->conf_compl_supported = !!(fcport->flags & | ||
801 | FCF_CONF_COMP_SUPPORTED); | ||
802 | BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); | ||
803 | memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); | ||
804 | |||
805 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
806 | list_add_tail(&sess->sess_list_entry, &ha->tgt.qla_tgt->sess_list); | ||
807 | ha->tgt.qla_tgt->sess_count++; | ||
808 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
809 | |||
810 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, | ||
811 | "qla_target(%d): %ssession for wwn %02x:%02x:%02x:%02x:" | ||
812 | "%02x:%02x:%02x:%02x (loop_id %d, s_id %x:%x:%x, confirmed" | ||
813 | " completion %ssupported) added\n", | ||
814 | vha->vp_idx, local ? "local " : "", fcport->port_name[0], | ||
815 | fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], | ||
816 | fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], | ||
817 | fcport->port_name[7], fcport->loop_id, sess->s_id.b.domain, | ||
818 | sess->s_id.b.area, sess->s_id.b.al_pa, sess->conf_compl_supported ? | ||
819 | "" : "not "); | ||
820 | |||
821 | return sess; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() | ||
826 | */ | ||
827 | void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | ||
828 | { | ||
829 | struct qla_hw_data *ha = vha->hw; | ||
830 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
831 | struct qla_tgt_sess *sess; | ||
832 | unsigned long flags; | ||
833 | |||
834 | if (!vha->hw->tgt.tgt_ops) | ||
835 | return; | ||
836 | |||
837 | if (!tgt || (fcport->port_type != FCT_INITIATOR)) | ||
838 | return; | ||
839 | |||
840 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
841 | if (tgt->tgt_stop) { | ||
842 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
843 | return; | ||
844 | } | ||
845 | sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); | ||
846 | if (!sess) { | ||
847 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
848 | |||
849 | mutex_lock(&ha->tgt.tgt_mutex); | ||
850 | sess = qlt_create_sess(vha, fcport, false); | ||
851 | mutex_unlock(&ha->tgt.tgt_mutex); | ||
852 | |||
853 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
854 | } else { | ||
855 | kref_get(&sess->se_sess->sess_kref); | ||
856 | |||
857 | if (sess->deleted) { | ||
858 | qlt_undelete_sess(sess); | ||
859 | |||
860 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c, | ||
861 | "qla_target(%u): %ssession for port %02x:" | ||
862 | "%02x:%02x:%02x:%02x:%02x:%02x:%02x (loop ID %d) " | ||
863 | "reappeared\n", vha->vp_idx, sess->local ? "local " | ||
864 | : "", sess->port_name[0], sess->port_name[1], | ||
865 | sess->port_name[2], sess->port_name[3], | ||
866 | sess->port_name[4], sess->port_name[5], | ||
867 | sess->port_name[6], sess->port_name[7], | ||
868 | sess->loop_id); | ||
869 | |||
870 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, | ||
871 | "Reappeared sess %p\n", sess); | ||
872 | } | ||
873 | sess->s_id = fcport->d_id; | ||
874 | sess->loop_id = fcport->loop_id; | ||
875 | sess->conf_compl_supported = !!(fcport->flags & | ||
876 | FCF_CONF_COMP_SUPPORTED); | ||
877 | } | ||
878 | |||
879 | if (sess && sess->local) { | ||
880 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d, | ||
881 | "qla_target(%u): local session for " | ||
882 | "port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " | ||
883 | "(loop ID %d) became global\n", vha->vp_idx, | ||
884 | fcport->port_name[0], fcport->port_name[1], | ||
885 | fcport->port_name[2], fcport->port_name[3], | ||
886 | fcport->port_name[4], fcport->port_name[5], | ||
887 | fcport->port_name[6], fcport->port_name[7], | ||
888 | sess->loop_id); | ||
889 | sess->local = 0; | ||
890 | } | ||
891 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
892 | |||
893 | ha->tgt.tgt_ops->put_sess(sess); | ||
894 | } | ||
895 | |||
896 | void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) | ||
897 | { | ||
898 | struct qla_hw_data *ha = vha->hw; | ||
899 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
900 | struct qla_tgt_sess *sess; | ||
901 | unsigned long flags; | ||
902 | |||
903 | if (!vha->hw->tgt.tgt_ops) | ||
904 | return; | ||
905 | |||
906 | if (!tgt || (fcport->port_type != FCT_INITIATOR)) | ||
907 | return; | ||
908 | |||
909 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
910 | if (tgt->tgt_stop) { | ||
911 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
912 | return; | ||
913 | } | ||
914 | sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); | ||
915 | if (!sess) { | ||
916 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
917 | return; | ||
918 | } | ||
919 | |||
920 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess); | ||
921 | |||
922 | sess->local = 1; | ||
923 | qlt_schedule_sess_for_deletion(sess, false); | ||
924 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
925 | } | ||
926 | |||
927 | static inline int test_tgt_sess_count(struct qla_tgt *tgt) | ||
928 | { | ||
929 | struct qla_hw_data *ha = tgt->ha; | ||
930 | unsigned long flags; | ||
931 | int res; | ||
932 | /* | ||
933 | * We need to protect against race, when tgt is freed before or | ||
934 | * inside wake_up() | ||
935 | */ | ||
936 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
937 | ql_dbg(ql_dbg_tgt, tgt->vha, 0xe002, | ||
938 | "tgt %p, empty(sess_list)=%d sess_count=%d\n", | ||
939 | tgt, list_empty(&tgt->sess_list), tgt->sess_count); | ||
940 | res = (tgt->sess_count == 0); | ||
941 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
942 | |||
943 | return res; | ||
944 | } | ||
945 | |||
946 | /* Called by tcm_qla2xxx configfs code */ | ||
947 | void qlt_stop_phase1(struct qla_tgt *tgt) | ||
948 | { | ||
949 | struct scsi_qla_host *vha = tgt->vha; | ||
950 | struct qla_hw_data *ha = tgt->ha; | ||
951 | unsigned long flags; | ||
952 | |||
953 | if (tgt->tgt_stop || tgt->tgt_stopped) { | ||
954 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e, | ||
955 | "Already in tgt->tgt_stop or tgt_stopped state\n"); | ||
956 | dump_stack(); | ||
957 | return; | ||
958 | } | ||
959 | |||
960 | ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n", | ||
961 | vha->host_no, vha); | ||
962 | /* | ||
963 | * Mutex needed to sync with qla_tgt_fc_port_[added,deleted]. | ||
964 | * Lock is needed, because we still can get an incoming packet. | ||
965 | */ | ||
966 | mutex_lock(&ha->tgt.tgt_mutex); | ||
967 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
968 | tgt->tgt_stop = 1; | ||
969 | qlt_clear_tgt_db(tgt, true); | ||
970 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
971 | mutex_unlock(&ha->tgt.tgt_mutex); | ||
972 | |||
973 | flush_delayed_work_sync(&tgt->sess_del_work); | ||
974 | |||
975 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf009, | ||
976 | "Waiting for sess works (tgt %p)", tgt); | ||
977 | spin_lock_irqsave(&tgt->sess_work_lock, flags); | ||
978 | while (!list_empty(&tgt->sess_works_list)) { | ||
979 | spin_unlock_irqrestore(&tgt->sess_work_lock, flags); | ||
980 | flush_scheduled_work(); | ||
981 | spin_lock_irqsave(&tgt->sess_work_lock, flags); | ||
982 | } | ||
983 | spin_unlock_irqrestore(&tgt->sess_work_lock, flags); | ||
984 | |||
985 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00a, | ||
986 | "Waiting for tgt %p: list_empty(sess_list)=%d " | ||
987 | "sess_count=%d\n", tgt, list_empty(&tgt->sess_list), | ||
988 | tgt->sess_count); | ||
989 | |||
990 | wait_event(tgt->waitQ, test_tgt_sess_count(tgt)); | ||
991 | |||
992 | /* Big hammer */ | ||
993 | if (!ha->flags.host_shutting_down && qla_tgt_mode_enabled(vha)) | ||
994 | qlt_disable_vha(vha); | ||
995 | |||
996 | /* Wait for sessions to clear out (just in case) */ | ||
997 | wait_event(tgt->waitQ, test_tgt_sess_count(tgt)); | ||
998 | } | ||
999 | EXPORT_SYMBOL(qlt_stop_phase1); | ||
1000 | |||
1001 | /* Called by tcm_qla2xxx configfs code */ | ||
1002 | void qlt_stop_phase2(struct qla_tgt *tgt) | ||
1003 | { | ||
1004 | struct qla_hw_data *ha = tgt->ha; | ||
1005 | unsigned long flags; | ||
1006 | |||
1007 | if (tgt->tgt_stopped) { | ||
1008 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf04f, | ||
1009 | "Already in tgt->tgt_stopped state\n"); | ||
1010 | dump_stack(); | ||
1011 | return; | ||
1012 | } | ||
1013 | |||
1014 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00b, | ||
1015 | "Waiting for %d IRQ commands to complete (tgt %p)", | ||
1016 | tgt->irq_cmd_count, tgt); | ||
1017 | |||
1018 | mutex_lock(&ha->tgt.tgt_mutex); | ||
1019 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1020 | while (tgt->irq_cmd_count != 0) { | ||
1021 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1022 | udelay(2); | ||
1023 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1024 | } | ||
1025 | tgt->tgt_stop = 0; | ||
1026 | tgt->tgt_stopped = 1; | ||
1027 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1028 | mutex_unlock(&ha->tgt.tgt_mutex); | ||
1029 | |||
1030 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00c, "Stop of tgt %p finished", | ||
1031 | tgt); | ||
1032 | } | ||
1033 | EXPORT_SYMBOL(qlt_stop_phase2); | ||
1034 | |||
1035 | /* Called from qlt_remove_target() -> qla2x00_remove_one() */ | ||
1036 | void qlt_release(struct qla_tgt *tgt) | ||
1037 | { | ||
1038 | struct qla_hw_data *ha = tgt->ha; | ||
1039 | |||
1040 | if ((ha->tgt.qla_tgt != NULL) && !tgt->tgt_stopped) | ||
1041 | qlt_stop_phase2(tgt); | ||
1042 | |||
1043 | ha->tgt.qla_tgt = NULL; | ||
1044 | |||
1045 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00d, | ||
1046 | "Release of tgt %p finished\n", tgt); | ||
1047 | |||
1048 | kfree(tgt); | ||
1049 | } | ||
1050 | |||
1051 | /* ha->hardware_lock supposed to be held on entry */ | ||
1052 | static int qlt_sched_sess_work(struct qla_tgt *tgt, int type, | ||
1053 | const void *param, unsigned int param_size) | ||
1054 | { | ||
1055 | struct qla_tgt_sess_work_param *prm; | ||
1056 | unsigned long flags; | ||
1057 | |||
1058 | prm = kzalloc(sizeof(*prm), GFP_ATOMIC); | ||
1059 | if (!prm) { | ||
1060 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf050, | ||
1061 | "qla_target(%d): Unable to create session " | ||
1062 | "work, command will be refused", 0); | ||
1063 | return -ENOMEM; | ||
1064 | } | ||
1065 | |||
1066 | ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00e, | ||
1067 | "Scheduling work (type %d, prm %p)" | ||
1068 | " to find session for param %p (size %d, tgt %p)\n", | ||
1069 | type, prm, param, param_size, tgt); | ||
1070 | |||
1071 | prm->type = type; | ||
1072 | memcpy(&prm->tm_iocb, param, param_size); | ||
1073 | |||
1074 | spin_lock_irqsave(&tgt->sess_work_lock, flags); | ||
1075 | list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list); | ||
1076 | spin_unlock_irqrestore(&tgt->sess_work_lock, flags); | ||
1077 | |||
1078 | schedule_work(&tgt->sess_work); | ||
1079 | |||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | /* | ||
1084 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
1085 | */ | ||
1086 | static void qlt_send_notify_ack(struct scsi_qla_host *vha, | ||
1087 | struct imm_ntfy_from_isp *ntfy, | ||
1088 | uint32_t add_flags, uint16_t resp_code, int resp_code_valid, | ||
1089 | uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan) | ||
1090 | { | ||
1091 | struct qla_hw_data *ha = vha->hw; | ||
1092 | request_t *pkt; | ||
1093 | struct nack_to_isp *nack; | ||
1094 | |||
1095 | ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha); | ||
1096 | |||
1097 | /* Send marker if required */ | ||
1098 | if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) | ||
1099 | return; | ||
1100 | |||
1101 | pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); | ||
1102 | if (!pkt) { | ||
1103 | ql_dbg(ql_dbg_tgt, vha, 0xe049, | ||
1104 | "qla_target(%d): %s failed: unable to allocate " | ||
1105 | "request packet\n", vha->vp_idx, __func__); | ||
1106 | return; | ||
1107 | } | ||
1108 | |||
1109 | if (ha->tgt.qla_tgt != NULL) | ||
1110 | ha->tgt.qla_tgt->notify_ack_expected++; | ||
1111 | |||
1112 | pkt->entry_type = NOTIFY_ACK_TYPE; | ||
1113 | pkt->entry_count = 1; | ||
1114 | |||
1115 | nack = (struct nack_to_isp *)pkt; | ||
1116 | nack->ox_id = ntfy->ox_id; | ||
1117 | |||
1118 | nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; | ||
1119 | if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { | ||
1120 | nack->u.isp24.flags = ntfy->u.isp24.flags & | ||
1121 | __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); | ||
1122 | } | ||
1123 | nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; | ||
1124 | nack->u.isp24.status = ntfy->u.isp24.status; | ||
1125 | nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode; | ||
1126 | nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address; | ||
1127 | nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs; | ||
1128 | nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui; | ||
1129 | nack->u.isp24.srr_flags = cpu_to_le16(srr_flags); | ||
1130 | nack->u.isp24.srr_reject_code = srr_reject_code; | ||
1131 | nack->u.isp24.srr_reject_code_expl = srr_explan; | ||
1132 | nack->u.isp24.vp_index = ntfy->u.isp24.vp_index; | ||
1133 | |||
1134 | ql_dbg(ql_dbg_tgt, vha, 0xe005, | ||
1135 | "qla_target(%d): Sending 24xx Notify Ack %d\n", | ||
1136 | vha->vp_idx, nack->u.isp24.status); | ||
1137 | |||
1138 | qla2x00_start_iocbs(vha, vha->req); | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
1143 | */ | ||
1144 | static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, | ||
1145 | struct abts_recv_from_24xx *abts, uint32_t status, | ||
1146 | bool ids_reversed) | ||
1147 | { | ||
1148 | struct qla_hw_data *ha = vha->hw; | ||
1149 | struct abts_resp_to_24xx *resp; | ||
1150 | uint32_t f_ctl; | ||
1151 | uint8_t *p; | ||
1152 | |||
1153 | ql_dbg(ql_dbg_tgt, vha, 0xe006, | ||
1154 | "Sending task mgmt ABTS response (ha=%p, atio=%p, status=%x\n", | ||
1155 | ha, abts, status); | ||
1156 | |||
1157 | /* Send marker if required */ | ||
1158 | if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) | ||
1159 | return; | ||
1160 | |||
1161 | resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); | ||
1162 | if (!resp) { | ||
1163 | ql_dbg(ql_dbg_tgt, vha, 0xe04a, | ||
1164 | "qla_target(%d): %s failed: unable to allocate " | ||
1165 | "request packet", vha->vp_idx, __func__); | ||
1166 | return; | ||
1167 | } | ||
1168 | |||
1169 | resp->entry_type = ABTS_RESP_24XX; | ||
1170 | resp->entry_count = 1; | ||
1171 | resp->nport_handle = abts->nport_handle; | ||
1172 | resp->vp_index = vha->vp_idx; | ||
1173 | resp->sof_type = abts->sof_type; | ||
1174 | resp->exchange_address = abts->exchange_address; | ||
1175 | resp->fcp_hdr_le = abts->fcp_hdr_le; | ||
1176 | f_ctl = __constant_cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP | | ||
1177 | F_CTL_LAST_SEQ | F_CTL_END_SEQ | | ||
1178 | F_CTL_SEQ_INITIATIVE); | ||
1179 | p = (uint8_t *)&f_ctl; | ||
1180 | resp->fcp_hdr_le.f_ctl[0] = *p++; | ||
1181 | resp->fcp_hdr_le.f_ctl[1] = *p++; | ||
1182 | resp->fcp_hdr_le.f_ctl[2] = *p; | ||
1183 | if (ids_reversed) { | ||
1184 | resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0]; | ||
1185 | resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1]; | ||
1186 | resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2]; | ||
1187 | resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0]; | ||
1188 | resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1]; | ||
1189 | resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2]; | ||
1190 | } else { | ||
1191 | resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0]; | ||
1192 | resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1]; | ||
1193 | resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2]; | ||
1194 | resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0]; | ||
1195 | resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1]; | ||
1196 | resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2]; | ||
1197 | } | ||
1198 | resp->exchange_addr_to_abort = abts->exchange_addr_to_abort; | ||
1199 | if (status == FCP_TMF_CMPL) { | ||
1200 | resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC; | ||
1201 | resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID; | ||
1202 | resp->payload.ba_acct.low_seq_cnt = 0x0000; | ||
1203 | resp->payload.ba_acct.high_seq_cnt = 0xFFFF; | ||
1204 | resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id; | ||
1205 | resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id; | ||
1206 | } else { | ||
1207 | resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_RJT; | ||
1208 | resp->payload.ba_rjt.reason_code = | ||
1209 | BA_RJT_REASON_CODE_UNABLE_TO_PERFORM; | ||
1210 | /* Other bytes are zero */ | ||
1211 | } | ||
1212 | |||
1213 | ha->tgt.qla_tgt->abts_resp_expected++; | ||
1214 | |||
1215 | qla2x00_start_iocbs(vha, vha->req); | ||
1216 | } | ||
1217 | |||
1218 | /* | ||
1219 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
1220 | */ | ||
1221 | static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, | ||
1222 | struct abts_resp_from_24xx_fw *entry) | ||
1223 | { | ||
1224 | struct ctio7_to_24xx *ctio; | ||
1225 | |||
1226 | ql_dbg(ql_dbg_tgt, vha, 0xe007, | ||
1227 | "Sending retry TERM EXCH CTIO7 (ha=%p)\n", vha->hw); | ||
1228 | /* Send marker if required */ | ||
1229 | if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) | ||
1230 | return; | ||
1231 | |||
1232 | ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); | ||
1233 | if (ctio == NULL) { | ||
1234 | ql_dbg(ql_dbg_tgt, vha, 0xe04b, | ||
1235 | "qla_target(%d): %s failed: unable to allocate " | ||
1236 | "request packet\n", vha->vp_idx, __func__); | ||
1237 | return; | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * We've got on entrance firmware's response on by us generated | ||
1242 | * ABTS response. So, in it ID fields are reversed. | ||
1243 | */ | ||
1244 | |||
1245 | ctio->entry_type = CTIO_TYPE7; | ||
1246 | ctio->entry_count = 1; | ||
1247 | ctio->nport_handle = entry->nport_handle; | ||
1248 | ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; | ||
1249 | ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); | ||
1250 | ctio->vp_index = vha->vp_idx; | ||
1251 | ctio->initiator_id[0] = entry->fcp_hdr_le.d_id[0]; | ||
1252 | ctio->initiator_id[1] = entry->fcp_hdr_le.d_id[1]; | ||
1253 | ctio->initiator_id[2] = entry->fcp_hdr_le.d_id[2]; | ||
1254 | ctio->exchange_addr = entry->exchange_addr_to_abort; | ||
1255 | ctio->u.status1.flags = | ||
1256 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | | ||
1257 | CTIO7_FLAGS_TERMINATE); | ||
1258 | ctio->u.status1.ox_id = entry->fcp_hdr_le.ox_id; | ||
1259 | |||
1260 | qla2x00_start_iocbs(vha, vha->req); | ||
1261 | |||
1262 | qlt_24xx_send_abts_resp(vha, (struct abts_recv_from_24xx *)entry, | ||
1263 | FCP_TMF_CMPL, true); | ||
1264 | } | ||
1265 | |||
1266 | /* ha->hardware_lock supposed to be held on entry */ | ||
1267 | static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, | ||
1268 | struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) | ||
1269 | { | ||
1270 | struct qla_hw_data *ha = vha->hw; | ||
1271 | struct qla_tgt_mgmt_cmd *mcmd; | ||
1272 | int rc; | ||
1273 | |||
1274 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, | ||
1275 | "qla_target(%d): task abort (tag=%d)\n", | ||
1276 | vha->vp_idx, abts->exchange_addr_to_abort); | ||
1277 | |||
1278 | mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); | ||
1279 | if (mcmd == NULL) { | ||
1280 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf051, | ||
1281 | "qla_target(%d): %s: Allocation of ABORT cmd failed", | ||
1282 | vha->vp_idx, __func__); | ||
1283 | return -ENOMEM; | ||
1284 | } | ||
1285 | memset(mcmd, 0, sizeof(*mcmd)); | ||
1286 | |||
1287 | mcmd->sess = sess; | ||
1288 | memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); | ||
1289 | |||
1290 | rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, | ||
1291 | abts->exchange_addr_to_abort); | ||
1292 | if (rc != 0) { | ||
1293 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, | ||
1294 | "qla_target(%d): tgt_ops->handle_tmr()" | ||
1295 | " failed: %d", vha->vp_idx, rc); | ||
1296 | mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); | ||
1297 | return -EFAULT; | ||
1298 | } | ||
1299 | |||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | /* | ||
1304 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
1305 | */ | ||
1306 | static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, | ||
1307 | struct abts_recv_from_24xx *abts) | ||
1308 | { | ||
1309 | struct qla_hw_data *ha = vha->hw; | ||
1310 | struct qla_tgt_sess *sess; | ||
1311 | uint32_t tag = abts->exchange_addr_to_abort; | ||
1312 | uint8_t s_id[3]; | ||
1313 | int rc; | ||
1314 | |||
1315 | if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) { | ||
1316 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053, | ||
1317 | "qla_target(%d): ABTS: Abort Sequence not " | ||
1318 | "supported\n", vha->vp_idx); | ||
1319 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); | ||
1320 | return; | ||
1321 | } | ||
1322 | |||
1323 | if (tag == ATIO_EXCHANGE_ADDRESS_UNKNOWN) { | ||
1324 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf010, | ||
1325 | "qla_target(%d): ABTS: Unknown Exchange " | ||
1326 | "Address received\n", vha->vp_idx); | ||
1327 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); | ||
1328 | return; | ||
1329 | } | ||
1330 | |||
1331 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf011, | ||
1332 | "qla_target(%d): task abort (s_id=%x:%x:%x, " | ||
1333 | "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id[2], | ||
1334 | abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag, | ||
1335 | le32_to_cpu(abts->fcp_hdr_le.parameter)); | ||
1336 | |||
1337 | s_id[0] = abts->fcp_hdr_le.s_id[2]; | ||
1338 | s_id[1] = abts->fcp_hdr_le.s_id[1]; | ||
1339 | s_id[2] = abts->fcp_hdr_le.s_id[0]; | ||
1340 | |||
1341 | sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); | ||
1342 | if (!sess) { | ||
1343 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, | ||
1344 | "qla_target(%d): task abort for non-existant session\n", | ||
1345 | vha->vp_idx); | ||
1346 | rc = qlt_sched_sess_work(ha->tgt.qla_tgt, | ||
1347 | QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); | ||
1348 | if (rc != 0) { | ||
1349 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, | ||
1350 | false); | ||
1351 | } | ||
1352 | return; | ||
1353 | } | ||
1354 | |||
1355 | rc = __qlt_24xx_handle_abts(vha, abts, sess); | ||
1356 | if (rc != 0) { | ||
1357 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054, | ||
1358 | "qla_target(%d): __qlt_24xx_handle_abts() failed: %d\n", | ||
1359 | vha->vp_idx, rc); | ||
1360 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); | ||
1361 | return; | ||
1362 | } | ||
1363 | } | ||
1364 | |||
1365 | /* | ||
1366 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
1367 | */ | ||
1368 | static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, | ||
1369 | struct qla_tgt_mgmt_cmd *mcmd, uint32_t resp_code) | ||
1370 | { | ||
1371 | struct atio_from_isp *atio = &mcmd->orig_iocb.atio; | ||
1372 | struct ctio7_to_24xx *ctio; | ||
1373 | |||
1374 | ql_dbg(ql_dbg_tgt, ha, 0xe008, | ||
1375 | "Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n", | ||
1376 | ha, atio, resp_code); | ||
1377 | |||
1378 | /* Send marker if required */ | ||
1379 | if (qlt_issue_marker(ha, 1) != QLA_SUCCESS) | ||
1380 | return; | ||
1381 | |||
1382 | ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(ha, NULL); | ||
1383 | if (ctio == NULL) { | ||
1384 | ql_dbg(ql_dbg_tgt, ha, 0xe04c, | ||
1385 | "qla_target(%d): %s failed: unable to allocate " | ||
1386 | "request packet\n", ha->vp_idx, __func__); | ||
1387 | return; | ||
1388 | } | ||
1389 | |||
1390 | ctio->entry_type = CTIO_TYPE7; | ||
1391 | ctio->entry_count = 1; | ||
1392 | ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; | ||
1393 | ctio->nport_handle = mcmd->sess->loop_id; | ||
1394 | ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); | ||
1395 | ctio->vp_index = ha->vp_idx; | ||
1396 | ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; | ||
1397 | ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; | ||
1398 | ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; | ||
1399 | ctio->exchange_addr = atio->u.isp24.exchange_addr; | ||
1400 | ctio->u.status1.flags = (atio->u.isp24.attr << 9) | | ||
1401 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | | ||
1402 | CTIO7_FLAGS_SEND_STATUS); | ||
1403 | ctio->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); | ||
1404 | ctio->u.status1.scsi_status = | ||
1405 | __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID); | ||
1406 | ctio->u.status1.response_len = __constant_cpu_to_le16(8); | ||
1407 | ((uint32_t *)ctio->u.status1.sense_data)[0] = cpu_to_be32(resp_code); | ||
1408 | |||
1409 | qla2x00_start_iocbs(ha, ha->req); | ||
1410 | } | ||
1411 | |||
1412 | void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) | ||
1413 | { | ||
1414 | mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); | ||
1415 | } | ||
1416 | EXPORT_SYMBOL(qlt_free_mcmd); | ||
1417 | |||
1418 | /* callback from target fabric module code */ | ||
1419 | void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) | ||
1420 | { | ||
1421 | struct scsi_qla_host *vha = mcmd->sess->vha; | ||
1422 | struct qla_hw_data *ha = vha->hw; | ||
1423 | unsigned long flags; | ||
1424 | |||
1425 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf013, | ||
1426 | "TM response mcmd (%p) status %#x state %#x", | ||
1427 | mcmd, mcmd->fc_tm_rsp, mcmd->flags); | ||
1428 | |||
1429 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1430 | if (mcmd->flags == QLA24XX_MGMT_SEND_NACK) | ||
1431 | qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy, | ||
1432 | 0, 0, 0, 0, 0, 0); | ||
1433 | else { | ||
1434 | if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK) | ||
1435 | qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts, | ||
1436 | mcmd->fc_tm_rsp, false); | ||
1437 | else | ||
1438 | qlt_24xx_send_task_mgmt_ctio(vha, mcmd, | ||
1439 | mcmd->fc_tm_rsp); | ||
1440 | } | ||
1441 | /* | ||
1442 | * Make the callback for ->free_mcmd() to queue_work() and invoke | ||
1443 | * target_put_sess_cmd() to drop cmd_kref to 1. The final | ||
1444 | * target_put_sess_cmd() call will be made from TFO->check_stop_free() | ||
1445 | * -> tcm_qla2xxx_check_stop_free() to release the TMR associated se_cmd | ||
1446 | * descriptor after TFO->queue_tm_rsp() -> tcm_qla2xxx_queue_tm_rsp() -> | ||
1447 | * qlt_xmit_tm_rsp() returns here.. | ||
1448 | */ | ||
1449 | ha->tgt.tgt_ops->free_mcmd(mcmd); | ||
1450 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1451 | } | ||
1452 | EXPORT_SYMBOL(qlt_xmit_tm_rsp); | ||
1453 | |||
1454 | /* No locks */ | ||
1455 | static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm) | ||
1456 | { | ||
1457 | struct qla_tgt_cmd *cmd = prm->cmd; | ||
1458 | |||
1459 | BUG_ON(cmd->sg_cnt == 0); | ||
1460 | |||
1461 | prm->sg = (struct scatterlist *)cmd->sg; | ||
1462 | prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, cmd->sg, | ||
1463 | cmd->sg_cnt, cmd->dma_data_direction); | ||
1464 | if (unlikely(prm->seg_cnt == 0)) | ||
1465 | goto out_err; | ||
1466 | |||
1467 | prm->cmd->sg_mapped = 1; | ||
1468 | |||
1469 | /* | ||
1470 | * If greater than four sg entries then we need to allocate | ||
1471 | * the continuation entries | ||
1472 | */ | ||
1473 | if (prm->seg_cnt > prm->tgt->datasegs_per_cmd) | ||
1474 | prm->req_cnt += DIV_ROUND_UP(prm->seg_cnt - | ||
1475 | prm->tgt->datasegs_per_cmd, prm->tgt->datasegs_per_cont); | ||
1476 | |||
1477 | ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe009, "seg_cnt=%d, req_cnt=%d\n", | ||
1478 | prm->seg_cnt, prm->req_cnt); | ||
1479 | return 0; | ||
1480 | |||
1481 | out_err: | ||
1482 | ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe04d, | ||
1483 | "qla_target(%d): PCI mapping failed: sg_cnt=%d", | ||
1484 | 0, prm->cmd->sg_cnt); | ||
1485 | return -1; | ||
1486 | } | ||
1487 | |||
1488 | static inline void qlt_unmap_sg(struct scsi_qla_host *vha, | ||
1489 | struct qla_tgt_cmd *cmd) | ||
1490 | { | ||
1491 | struct qla_hw_data *ha = vha->hw; | ||
1492 | |||
1493 | BUG_ON(!cmd->sg_mapped); | ||
1494 | pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); | ||
1495 | cmd->sg_mapped = 0; | ||
1496 | } | ||
1497 | |||
1498 | static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, | ||
1499 | uint32_t req_cnt) | ||
1500 | { | ||
1501 | struct qla_hw_data *ha = vha->hw; | ||
1502 | device_reg_t __iomem *reg = ha->iobase; | ||
1503 | uint32_t cnt; | ||
1504 | |||
1505 | if (vha->req->cnt < (req_cnt + 2)) { | ||
1506 | cnt = (uint16_t)RD_REG_DWORD(®->isp24.req_q_out); | ||
1507 | |||
1508 | ql_dbg(ql_dbg_tgt, vha, 0xe00a, | ||
1509 | "Request ring circled: cnt=%d, vha->->ring_index=%d, " | ||
1510 | "vha->req->cnt=%d, req_cnt=%d\n", cnt, | ||
1511 | vha->req->ring_index, vha->req->cnt, req_cnt); | ||
1512 | if (vha->req->ring_index < cnt) | ||
1513 | vha->req->cnt = cnt - vha->req->ring_index; | ||
1514 | else | ||
1515 | vha->req->cnt = vha->req->length - | ||
1516 | (vha->req->ring_index - cnt); | ||
1517 | } | ||
1518 | |||
1519 | if (unlikely(vha->req->cnt < (req_cnt + 2))) { | ||
1520 | ql_dbg(ql_dbg_tgt, vha, 0xe00b, | ||
1521 | "qla_target(%d): There is no room in the " | ||
1522 | "request ring: vha->req->ring_index=%d, vha->req->cnt=%d, " | ||
1523 | "req_cnt=%d\n", vha->vp_idx, vha->req->ring_index, | ||
1524 | vha->req->cnt, req_cnt); | ||
1525 | return -EAGAIN; | ||
1526 | } | ||
1527 | vha->req->cnt -= req_cnt; | ||
1528 | |||
1529 | return 0; | ||
1530 | } | ||
1531 | |||
1532 | /* | ||
1533 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
1534 | */ | ||
1535 | static inline void *qlt_get_req_pkt(struct scsi_qla_host *vha) | ||
1536 | { | ||
1537 | /* Adjust ring index. */ | ||
1538 | vha->req->ring_index++; | ||
1539 | if (vha->req->ring_index == vha->req->length) { | ||
1540 | vha->req->ring_index = 0; | ||
1541 | vha->req->ring_ptr = vha->req->ring; | ||
1542 | } else { | ||
1543 | vha->req->ring_ptr++; | ||
1544 | } | ||
1545 | return (cont_entry_t *)vha->req->ring_ptr; | ||
1546 | } | ||
1547 | |||
1548 | /* ha->hardware_lock supposed to be held on entry */ | ||
1549 | static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha) | ||
1550 | { | ||
1551 | struct qla_hw_data *ha = vha->hw; | ||
1552 | uint32_t h; | ||
1553 | |||
1554 | h = ha->tgt.current_handle; | ||
1555 | /* always increment cmd handle */ | ||
1556 | do { | ||
1557 | ++h; | ||
1558 | if (h > MAX_OUTSTANDING_COMMANDS) | ||
1559 | h = 1; /* 0 is QLA_TGT_NULL_HANDLE */ | ||
1560 | if (h == ha->tgt.current_handle) { | ||
1561 | ql_dbg(ql_dbg_tgt, vha, 0xe04e, | ||
1562 | "qla_target(%d): Ran out of " | ||
1563 | "empty cmd slots in ha %p\n", vha->vp_idx, ha); | ||
1564 | h = QLA_TGT_NULL_HANDLE; | ||
1565 | break; | ||
1566 | } | ||
1567 | } while ((h == QLA_TGT_NULL_HANDLE) || | ||
1568 | (h == QLA_TGT_SKIP_HANDLE) || | ||
1569 | (ha->tgt.cmds[h-1] != NULL)); | ||
1570 | |||
1571 | if (h != QLA_TGT_NULL_HANDLE) | ||
1572 | ha->tgt.current_handle = h; | ||
1573 | |||
1574 | return h; | ||
1575 | } | ||
1576 | |||
1577 | /* ha->hardware_lock supposed to be held on entry */ | ||
1578 | static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm, | ||
1579 | struct scsi_qla_host *vha) | ||
1580 | { | ||
1581 | uint32_t h; | ||
1582 | struct ctio7_to_24xx *pkt; | ||
1583 | struct qla_hw_data *ha = vha->hw; | ||
1584 | struct atio_from_isp *atio = &prm->cmd->atio; | ||
1585 | |||
1586 | pkt = (struct ctio7_to_24xx *)vha->req->ring_ptr; | ||
1587 | prm->pkt = pkt; | ||
1588 | memset(pkt, 0, sizeof(*pkt)); | ||
1589 | |||
1590 | pkt->entry_type = CTIO_TYPE7; | ||
1591 | pkt->entry_count = (uint8_t)prm->req_cnt; | ||
1592 | pkt->vp_index = vha->vp_idx; | ||
1593 | |||
1594 | h = qlt_make_handle(vha); | ||
1595 | if (unlikely(h == QLA_TGT_NULL_HANDLE)) { | ||
1596 | /* | ||
1597 | * CTIO type 7 from the firmware doesn't provide a way to | ||
1598 | * know the initiator's LOOP ID, hence we can't find | ||
1599 | * the session and, so, the command. | ||
1600 | */ | ||
1601 | return -EAGAIN; | ||
1602 | } else | ||
1603 | ha->tgt.cmds[h-1] = prm->cmd; | ||
1604 | |||
1605 | pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; | ||
1606 | pkt->nport_handle = prm->cmd->loop_id; | ||
1607 | pkt->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); | ||
1608 | pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; | ||
1609 | pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; | ||
1610 | pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; | ||
1611 | pkt->exchange_addr = atio->u.isp24.exchange_addr; | ||
1612 | pkt->u.status0.flags |= (atio->u.isp24.attr << 9); | ||
1613 | pkt->u.status0.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); | ||
1614 | pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset); | ||
1615 | |||
1616 | ql_dbg(ql_dbg_tgt, vha, 0xe00c, | ||
1617 | "qla_target(%d): handle(cmd) -> %08x, timeout %d, ox_id %#x\n", | ||
1618 | vha->vp_idx, pkt->handle, QLA_TGT_TIMEOUT, | ||
1619 | le16_to_cpu(pkt->u.status0.ox_id)); | ||
1620 | return 0; | ||
1621 | } | ||
1622 | |||
1623 | /* | ||
1624 | * ha->hardware_lock supposed to be held on entry. We have already made sure | ||
1625 | * that there is sufficient amount of request entries to not drop it. | ||
1626 | */ | ||
1627 | static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm, | ||
1628 | struct scsi_qla_host *vha) | ||
1629 | { | ||
1630 | int cnt; | ||
1631 | uint32_t *dword_ptr; | ||
1632 | int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr; | ||
1633 | |||
1634 | /* Build continuation packets */ | ||
1635 | while (prm->seg_cnt > 0) { | ||
1636 | cont_a64_entry_t *cont_pkt64 = | ||
1637 | (cont_a64_entry_t *)qlt_get_req_pkt(vha); | ||
1638 | |||
1639 | /* | ||
1640 | * Make sure that from cont_pkt64 none of | ||
1641 | * 64-bit specific fields used for 32-bit | ||
1642 | * addressing. Cast to (cont_entry_t *) for | ||
1643 | * that. | ||
1644 | */ | ||
1645 | |||
1646 | memset(cont_pkt64, 0, sizeof(*cont_pkt64)); | ||
1647 | |||
1648 | cont_pkt64->entry_count = 1; | ||
1649 | cont_pkt64->sys_define = 0; | ||
1650 | |||
1651 | if (enable_64bit_addressing) { | ||
1652 | cont_pkt64->entry_type = CONTINUE_A64_TYPE; | ||
1653 | dword_ptr = | ||
1654 | (uint32_t *)&cont_pkt64->dseg_0_address; | ||
1655 | } else { | ||
1656 | cont_pkt64->entry_type = CONTINUE_TYPE; | ||
1657 | dword_ptr = | ||
1658 | (uint32_t *)&((cont_entry_t *) | ||
1659 | cont_pkt64)->dseg_0_address; | ||
1660 | } | ||
1661 | |||
1662 | /* Load continuation entry data segments */ | ||
1663 | for (cnt = 0; | ||
1664 | cnt < prm->tgt->datasegs_per_cont && prm->seg_cnt; | ||
1665 | cnt++, prm->seg_cnt--) { | ||
1666 | *dword_ptr++ = | ||
1667 | cpu_to_le32(pci_dma_lo32 | ||
1668 | (sg_dma_address(prm->sg))); | ||
1669 | if (enable_64bit_addressing) { | ||
1670 | *dword_ptr++ = | ||
1671 | cpu_to_le32(pci_dma_hi32 | ||
1672 | (sg_dma_address | ||
1673 | (prm->sg))); | ||
1674 | } | ||
1675 | *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg)); | ||
1676 | |||
1677 | ql_dbg(ql_dbg_tgt, vha, 0xe00d, | ||
1678 | "S/G Segment Cont. phys_addr=%llx:%llx, len=%d\n", | ||
1679 | (long long unsigned int) | ||
1680 | pci_dma_hi32(sg_dma_address(prm->sg)), | ||
1681 | (long long unsigned int) | ||
1682 | pci_dma_lo32(sg_dma_address(prm->sg)), | ||
1683 | (int)sg_dma_len(prm->sg)); | ||
1684 | |||
1685 | prm->sg = sg_next(prm->sg); | ||
1686 | } | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | /* | ||
1691 | * ha->hardware_lock supposed to be held on entry. We have already made sure | ||
1692 | * that there is sufficient amount of request entries to not drop it. | ||
1693 | */ | ||
1694 | static void qlt_load_data_segments(struct qla_tgt_prm *prm, | ||
1695 | struct scsi_qla_host *vha) | ||
1696 | { | ||
1697 | int cnt; | ||
1698 | uint32_t *dword_ptr; | ||
1699 | int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr; | ||
1700 | struct ctio7_to_24xx *pkt24 = (struct ctio7_to_24xx *)prm->pkt; | ||
1701 | |||
1702 | ql_dbg(ql_dbg_tgt, vha, 0xe00e, | ||
1703 | "iocb->scsi_status=%x, iocb->flags=%x\n", | ||
1704 | le16_to_cpu(pkt24->u.status0.scsi_status), | ||
1705 | le16_to_cpu(pkt24->u.status0.flags)); | ||
1706 | |||
1707 | pkt24->u.status0.transfer_length = cpu_to_le32(prm->cmd->bufflen); | ||
1708 | |||
1709 | /* Setup packet address segment pointer */ | ||
1710 | dword_ptr = pkt24->u.status0.dseg_0_address; | ||
1711 | |||
1712 | /* Set total data segment count */ | ||
1713 | if (prm->seg_cnt) | ||
1714 | pkt24->dseg_count = cpu_to_le16(prm->seg_cnt); | ||
1715 | |||
1716 | if (prm->seg_cnt == 0) { | ||
1717 | /* No data transfer */ | ||
1718 | *dword_ptr++ = 0; | ||
1719 | *dword_ptr = 0; | ||
1720 | return; | ||
1721 | } | ||
1722 | |||
1723 | /* If scatter gather */ | ||
1724 | ql_dbg(ql_dbg_tgt, vha, 0xe00f, "%s", "Building S/G data segments..."); | ||
1725 | |||
1726 | /* Load command entry data segments */ | ||
1727 | for (cnt = 0; | ||
1728 | (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt; | ||
1729 | cnt++, prm->seg_cnt--) { | ||
1730 | *dword_ptr++ = | ||
1731 | cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg))); | ||
1732 | if (enable_64bit_addressing) { | ||
1733 | *dword_ptr++ = | ||
1734 | cpu_to_le32(pci_dma_hi32( | ||
1735 | sg_dma_address(prm->sg))); | ||
1736 | } | ||
1737 | *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg)); | ||
1738 | |||
1739 | ql_dbg(ql_dbg_tgt, vha, 0xe010, | ||
1740 | "S/G Segment phys_addr=%llx:%llx, len=%d\n", | ||
1741 | (long long unsigned int)pci_dma_hi32(sg_dma_address( | ||
1742 | prm->sg)), | ||
1743 | (long long unsigned int)pci_dma_lo32(sg_dma_address( | ||
1744 | prm->sg)), | ||
1745 | (int)sg_dma_len(prm->sg)); | ||
1746 | |||
1747 | prm->sg = sg_next(prm->sg); | ||
1748 | } | ||
1749 | |||
1750 | qlt_load_cont_data_segments(prm, vha); | ||
1751 | } | ||
1752 | |||
1753 | static inline int qlt_has_data(struct qla_tgt_cmd *cmd) | ||
1754 | { | ||
1755 | return cmd->bufflen > 0; | ||
1756 | } | ||
1757 | |||
1758 | /* | ||
1759 | * Called without ha->hardware_lock held | ||
1760 | */ | ||
1761 | static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, | ||
1762 | struct qla_tgt_prm *prm, int xmit_type, uint8_t scsi_status, | ||
1763 | uint32_t *full_req_cnt) | ||
1764 | { | ||
1765 | struct qla_tgt *tgt = cmd->tgt; | ||
1766 | struct scsi_qla_host *vha = tgt->vha; | ||
1767 | struct qla_hw_data *ha = vha->hw; | ||
1768 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
1769 | |||
1770 | if (unlikely(cmd->aborted)) { | ||
1771 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, | ||
1772 | "qla_target(%d): terminating exchange " | ||
1773 | "for aborted cmd=%p (se_cmd=%p, tag=%d)", vha->vp_idx, cmd, | ||
1774 | se_cmd, cmd->tag); | ||
1775 | |||
1776 | cmd->state = QLA_TGT_STATE_ABORTED; | ||
1777 | |||
1778 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); | ||
1779 | |||
1780 | /* !! At this point cmd could be already freed !! */ | ||
1781 | return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED; | ||
1782 | } | ||
1783 | |||
1784 | ql_dbg(ql_dbg_tgt, vha, 0xe011, "qla_target(%d): tag=%u\n", | ||
1785 | vha->vp_idx, cmd->tag); | ||
1786 | |||
1787 | prm->cmd = cmd; | ||
1788 | prm->tgt = tgt; | ||
1789 | prm->rq_result = scsi_status; | ||
1790 | prm->sense_buffer = &cmd->sense_buffer[0]; | ||
1791 | prm->sense_buffer_len = TRANSPORT_SENSE_BUFFER; | ||
1792 | prm->sg = NULL; | ||
1793 | prm->seg_cnt = -1; | ||
1794 | prm->req_cnt = 1; | ||
1795 | prm->add_status_pkt = 0; | ||
1796 | |||
1797 | ql_dbg(ql_dbg_tgt, vha, 0xe012, "rq_result=%x, xmit_type=%x\n", | ||
1798 | prm->rq_result, xmit_type); | ||
1799 | |||
1800 | /* Send marker if required */ | ||
1801 | if (qlt_issue_marker(vha, 0) != QLA_SUCCESS) | ||
1802 | return -EFAULT; | ||
1803 | |||
1804 | ql_dbg(ql_dbg_tgt, vha, 0xe013, "CTIO start: vha(%d)\n", vha->vp_idx); | ||
1805 | |||
1806 | if ((xmit_type & QLA_TGT_XMIT_DATA) && qlt_has_data(cmd)) { | ||
1807 | if (qlt_pci_map_calc_cnt(prm) != 0) | ||
1808 | return -EAGAIN; | ||
1809 | } | ||
1810 | |||
1811 | *full_req_cnt = prm->req_cnt; | ||
1812 | |||
1813 | if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { | ||
1814 | prm->residual = se_cmd->residual_count; | ||
1815 | ql_dbg(ql_dbg_tgt, vha, 0xe014, | ||
1816 | "Residual underflow: %d (tag %d, " | ||
1817 | "op %x, bufflen %d, rq_result %x)\n", prm->residual, | ||
1818 | cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, | ||
1819 | cmd->bufflen, prm->rq_result); | ||
1820 | prm->rq_result |= SS_RESIDUAL_UNDER; | ||
1821 | } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { | ||
1822 | prm->residual = se_cmd->residual_count; | ||
1823 | ql_dbg(ql_dbg_tgt, vha, 0xe015, | ||
1824 | "Residual overflow: %d (tag %d, " | ||
1825 | "op %x, bufflen %d, rq_result %x)\n", prm->residual, | ||
1826 | cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, | ||
1827 | cmd->bufflen, prm->rq_result); | ||
1828 | prm->rq_result |= SS_RESIDUAL_OVER; | ||
1829 | } | ||
1830 | |||
1831 | if (xmit_type & QLA_TGT_XMIT_STATUS) { | ||
1832 | /* | ||
1833 | * If QLA_TGT_XMIT_DATA is not set, add_status_pkt will be | ||
1834 | * ignored in *xmit_response() below | ||
1835 | */ | ||
1836 | if (qlt_has_data(cmd)) { | ||
1837 | if (QLA_TGT_SENSE_VALID(prm->sense_buffer) || | ||
1838 | (IS_FWI2_CAPABLE(ha) && | ||
1839 | (prm->rq_result != 0))) { | ||
1840 | prm->add_status_pkt = 1; | ||
1841 | (*full_req_cnt)++; | ||
1842 | } | ||
1843 | } | ||
1844 | } | ||
1845 | |||
1846 | ql_dbg(ql_dbg_tgt, vha, 0xe016, | ||
1847 | "req_cnt=%d, full_req_cnt=%d, add_status_pkt=%d\n", | ||
1848 | prm->req_cnt, *full_req_cnt, prm->add_status_pkt); | ||
1849 | |||
1850 | return 0; | ||
1851 | } | ||
1852 | |||
1853 | static inline int qlt_need_explicit_conf(struct qla_hw_data *ha, | ||
1854 | struct qla_tgt_cmd *cmd, int sending_sense) | ||
1855 | { | ||
1856 | if (ha->tgt.enable_class_2) | ||
1857 | return 0; | ||
1858 | |||
1859 | if (sending_sense) | ||
1860 | return cmd->conf_compl_supported; | ||
1861 | else | ||
1862 | return ha->tgt.enable_explicit_conf && | ||
1863 | cmd->conf_compl_supported; | ||
1864 | } | ||
1865 | |||
1866 | #ifdef CONFIG_QLA_TGT_DEBUG_SRR | ||
1867 | /* | ||
1868 | * Original taken from the XFS code | ||
1869 | */ | ||
1870 | static unsigned long qlt_srr_random(void) | ||
1871 | { | ||
1872 | static int Inited; | ||
1873 | static unsigned long RandomValue; | ||
1874 | static DEFINE_SPINLOCK(lock); | ||
1875 | /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */ | ||
1876 | register long rv; | ||
1877 | register long lo; | ||
1878 | register long hi; | ||
1879 | unsigned long flags; | ||
1880 | |||
1881 | spin_lock_irqsave(&lock, flags); | ||
1882 | if (!Inited) { | ||
1883 | RandomValue = jiffies; | ||
1884 | Inited = 1; | ||
1885 | } | ||
1886 | rv = RandomValue; | ||
1887 | hi = rv / 127773; | ||
1888 | lo = rv % 127773; | ||
1889 | rv = 16807 * lo - 2836 * hi; | ||
1890 | if (rv <= 0) | ||
1891 | rv += 2147483647; | ||
1892 | RandomValue = rv; | ||
1893 | spin_unlock_irqrestore(&lock, flags); | ||
1894 | return rv; | ||
1895 | } | ||
1896 | |||
1897 | static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) | ||
1898 | { | ||
1899 | #if 0 /* This is not a real status packets lost, so it won't lead to SRR */ | ||
1900 | if ((*xmit_type & QLA_TGT_XMIT_STATUS) && (qlt_srr_random() % 200) | ||
1901 | == 50) { | ||
1902 | *xmit_type &= ~QLA_TGT_XMIT_STATUS; | ||
1903 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015, | ||
1904 | "Dropping cmd %p (tag %d) status", cmd, cmd->tag); | ||
1905 | } | ||
1906 | #endif | ||
1907 | /* | ||
1908 | * It's currently not possible to simulate SRRs for FCP_WRITE without | ||
1909 | * a physical link layer failure, so don't even try here.. | ||
1910 | */ | ||
1911 | if (cmd->dma_data_direction != DMA_FROM_DEVICE) | ||
1912 | return; | ||
1913 | |||
1914 | if (qlt_has_data(cmd) && (cmd->sg_cnt > 1) && | ||
1915 | ((qlt_srr_random() % 100) == 20)) { | ||
1916 | int i, leave = 0; | ||
1917 | unsigned int tot_len = 0; | ||
1918 | |||
1919 | while (leave == 0) | ||
1920 | leave = qlt_srr_random() % cmd->sg_cnt; | ||
1921 | |||
1922 | for (i = 0; i < leave; i++) | ||
1923 | tot_len += cmd->sg[i].length; | ||
1924 | |||
1925 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016, | ||
1926 | "Cutting cmd %p (tag %d) buffer" | ||
1927 | " tail to len %d, sg_cnt %d (cmd->bufflen %d," | ||
1928 | " cmd->sg_cnt %d)", cmd, cmd->tag, tot_len, leave, | ||
1929 | cmd->bufflen, cmd->sg_cnt); | ||
1930 | |||
1931 | cmd->bufflen = tot_len; | ||
1932 | cmd->sg_cnt = leave; | ||
1933 | } | ||
1934 | |||
1935 | if (qlt_has_data(cmd) && ((qlt_srr_random() % 100) == 70)) { | ||
1936 | unsigned int offset = qlt_srr_random() % cmd->bufflen; | ||
1937 | |||
1938 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017, | ||
1939 | "Cutting cmd %p (tag %d) buffer head " | ||
1940 | "to offset %d (cmd->bufflen %d)", cmd, cmd->tag, offset, | ||
1941 | cmd->bufflen); | ||
1942 | if (offset == 0) | ||
1943 | *xmit_type &= ~QLA_TGT_XMIT_DATA; | ||
1944 | else if (qlt_set_data_offset(cmd, offset)) { | ||
1945 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018, | ||
1946 | "qlt_set_data_offset() failed (tag %d)", cmd->tag); | ||
1947 | } | ||
1948 | } | ||
1949 | } | ||
1950 | #else | ||
1951 | static inline void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) | ||
1952 | {} | ||
1953 | #endif | ||
1954 | |||
1955 | static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, | ||
1956 | struct qla_tgt_prm *prm) | ||
1957 | { | ||
1958 | prm->sense_buffer_len = min_t(uint32_t, prm->sense_buffer_len, | ||
1959 | (uint32_t)sizeof(ctio->u.status1.sense_data)); | ||
1960 | ctio->u.status0.flags |= | ||
1961 | __constant_cpu_to_le16(CTIO7_FLAGS_SEND_STATUS); | ||
1962 | if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) { | ||
1963 | ctio->u.status0.flags |= __constant_cpu_to_le16( | ||
1964 | CTIO7_FLAGS_EXPLICIT_CONFORM | | ||
1965 | CTIO7_FLAGS_CONFORM_REQ); | ||
1966 | } | ||
1967 | ctio->u.status0.residual = cpu_to_le32(prm->residual); | ||
1968 | ctio->u.status0.scsi_status = cpu_to_le16(prm->rq_result); | ||
1969 | if (QLA_TGT_SENSE_VALID(prm->sense_buffer)) { | ||
1970 | int i; | ||
1971 | |||
1972 | if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) { | ||
1973 | if (prm->cmd->se_cmd.scsi_status != 0) { | ||
1974 | ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe017, | ||
1975 | "Skipping EXPLICIT_CONFORM and " | ||
1976 | "CTIO7_FLAGS_CONFORM_REQ for FCP READ w/ " | ||
1977 | "non GOOD status\n"); | ||
1978 | goto skip_explict_conf; | ||
1979 | } | ||
1980 | ctio->u.status1.flags |= __constant_cpu_to_le16( | ||
1981 | CTIO7_FLAGS_EXPLICIT_CONFORM | | ||
1982 | CTIO7_FLAGS_CONFORM_REQ); | ||
1983 | } | ||
1984 | skip_explict_conf: | ||
1985 | ctio->u.status1.flags &= | ||
1986 | ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); | ||
1987 | ctio->u.status1.flags |= | ||
1988 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); | ||
1989 | ctio->u.status1.scsi_status |= | ||
1990 | __constant_cpu_to_le16(SS_SENSE_LEN_VALID); | ||
1991 | ctio->u.status1.sense_length = | ||
1992 | cpu_to_le16(prm->sense_buffer_len); | ||
1993 | for (i = 0; i < prm->sense_buffer_len/4; i++) | ||
1994 | ((uint32_t *)ctio->u.status1.sense_data)[i] = | ||
1995 | cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]); | ||
1996 | #if 0 | ||
1997 | if (unlikely((prm->sense_buffer_len % 4) != 0)) { | ||
1998 | static int q; | ||
1999 | if (q < 10) { | ||
2000 | ql_dbg(ql_dbg_tgt, vha, 0xe04f, | ||
2001 | "qla_target(%d): %d bytes of sense " | ||
2002 | "lost", prm->tgt->ha->vp_idx, | ||
2003 | prm->sense_buffer_len % 4); | ||
2004 | q++; | ||
2005 | } | ||
2006 | } | ||
2007 | #endif | ||
2008 | } else { | ||
2009 | ctio->u.status1.flags &= | ||
2010 | ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); | ||
2011 | ctio->u.status1.flags |= | ||
2012 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); | ||
2013 | ctio->u.status1.sense_length = 0; | ||
2014 | memset(ctio->u.status1.sense_data, 0, | ||
2015 | sizeof(ctio->u.status1.sense_data)); | ||
2016 | } | ||
2017 | |||
2018 | /* Sense with len > 24, is it possible ??? */ | ||
2019 | } | ||
2020 | |||
2021 | /* | ||
2022 | * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and * | ||
2023 | * QLA_TGT_XMIT_STATUS for >= 24xx silicon | ||
2024 | */ | ||
2025 | int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, | ||
2026 | uint8_t scsi_status) | ||
2027 | { | ||
2028 | struct scsi_qla_host *vha = cmd->vha; | ||
2029 | struct qla_hw_data *ha = vha->hw; | ||
2030 | struct ctio7_to_24xx *pkt; | ||
2031 | struct qla_tgt_prm prm; | ||
2032 | uint32_t full_req_cnt = 0; | ||
2033 | unsigned long flags = 0; | ||
2034 | int res; | ||
2035 | |||
2036 | memset(&prm, 0, sizeof(prm)); | ||
2037 | qlt_check_srr_debug(cmd, &xmit_type); | ||
2038 | |||
2039 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe018, | ||
2040 | "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, " | ||
2041 | "cmd->dma_data_direction=%d\n", (xmit_type & QLA_TGT_XMIT_STATUS) ? | ||
2042 | 1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction); | ||
2043 | |||
2044 | res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, | ||
2045 | &full_req_cnt); | ||
2046 | if (unlikely(res != 0)) { | ||
2047 | if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED) | ||
2048 | return 0; | ||
2049 | |||
2050 | return res; | ||
2051 | } | ||
2052 | |||
2053 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2054 | |||
2055 | /* Does F/W have an IOCBs for this request */ | ||
2056 | res = qlt_check_reserve_free_req(vha, full_req_cnt); | ||
2057 | if (unlikely(res)) | ||
2058 | goto out_unmap_unlock; | ||
2059 | |||
2060 | res = qlt_24xx_build_ctio_pkt(&prm, vha); | ||
2061 | if (unlikely(res != 0)) | ||
2062 | goto out_unmap_unlock; | ||
2063 | |||
2064 | |||
2065 | pkt = (struct ctio7_to_24xx *)prm.pkt; | ||
2066 | |||
2067 | if (qlt_has_data(cmd) && (xmit_type & QLA_TGT_XMIT_DATA)) { | ||
2068 | pkt->u.status0.flags |= | ||
2069 | __constant_cpu_to_le16(CTIO7_FLAGS_DATA_IN | | ||
2070 | CTIO7_FLAGS_STATUS_MODE_0); | ||
2071 | |||
2072 | qlt_load_data_segments(&prm, vha); | ||
2073 | |||
2074 | if (prm.add_status_pkt == 0) { | ||
2075 | if (xmit_type & QLA_TGT_XMIT_STATUS) { | ||
2076 | pkt->u.status0.scsi_status = | ||
2077 | cpu_to_le16(prm.rq_result); | ||
2078 | pkt->u.status0.residual = | ||
2079 | cpu_to_le32(prm.residual); | ||
2080 | pkt->u.status0.flags |= __constant_cpu_to_le16( | ||
2081 | CTIO7_FLAGS_SEND_STATUS); | ||
2082 | if (qlt_need_explicit_conf(ha, cmd, 0)) { | ||
2083 | pkt->u.status0.flags |= | ||
2084 | __constant_cpu_to_le16( | ||
2085 | CTIO7_FLAGS_EXPLICIT_CONFORM | | ||
2086 | CTIO7_FLAGS_CONFORM_REQ); | ||
2087 | } | ||
2088 | } | ||
2089 | |||
2090 | } else { | ||
2091 | /* | ||
2092 | * We have already made sure that there is sufficient | ||
2093 | * amount of request entries to not drop HW lock in | ||
2094 | * req_pkt(). | ||
2095 | */ | ||
2096 | struct ctio7_to_24xx *ctio = | ||
2097 | (struct ctio7_to_24xx *)qlt_get_req_pkt(vha); | ||
2098 | |||
2099 | ql_dbg(ql_dbg_tgt, vha, 0xe019, | ||
2100 | "Building additional status packet\n"); | ||
2101 | |||
2102 | memcpy(ctio, pkt, sizeof(*ctio)); | ||
2103 | ctio->entry_count = 1; | ||
2104 | ctio->dseg_count = 0; | ||
2105 | ctio->u.status1.flags &= ~__constant_cpu_to_le16( | ||
2106 | CTIO7_FLAGS_DATA_IN); | ||
2107 | |||
2108 | /* Real finish is ctio_m1's finish */ | ||
2109 | pkt->handle |= CTIO_INTERMEDIATE_HANDLE_MARK; | ||
2110 | pkt->u.status0.flags |= __constant_cpu_to_le16( | ||
2111 | CTIO7_FLAGS_DONT_RET_CTIO); | ||
2112 | qlt_24xx_init_ctio_to_isp((struct ctio7_to_24xx *)ctio, | ||
2113 | &prm); | ||
2114 | pr_debug("Status CTIO7: %p\n", ctio); | ||
2115 | } | ||
2116 | } else | ||
2117 | qlt_24xx_init_ctio_to_isp(pkt, &prm); | ||
2118 | |||
2119 | |||
2120 | cmd->state = QLA_TGT_STATE_PROCESSED; /* Mid-level is done processing */ | ||
2121 | |||
2122 | ql_dbg(ql_dbg_tgt, vha, 0xe01a, | ||
2123 | "Xmitting CTIO7 response pkt for 24xx: %p scsi_status: 0x%02x\n", | ||
2124 | pkt, scsi_status); | ||
2125 | |||
2126 | qla2x00_start_iocbs(vha, vha->req); | ||
2127 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2128 | |||
2129 | return 0; | ||
2130 | |||
2131 | out_unmap_unlock: | ||
2132 | if (cmd->sg_mapped) | ||
2133 | qlt_unmap_sg(vha, cmd); | ||
2134 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2135 | |||
2136 | return res; | ||
2137 | } | ||
2138 | EXPORT_SYMBOL(qlt_xmit_response); | ||
2139 | |||
2140 | int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) | ||
2141 | { | ||
2142 | struct ctio7_to_24xx *pkt; | ||
2143 | struct scsi_qla_host *vha = cmd->vha; | ||
2144 | struct qla_hw_data *ha = vha->hw; | ||
2145 | struct qla_tgt *tgt = cmd->tgt; | ||
2146 | struct qla_tgt_prm prm; | ||
2147 | unsigned long flags; | ||
2148 | int res = 0; | ||
2149 | |||
2150 | memset(&prm, 0, sizeof(prm)); | ||
2151 | prm.cmd = cmd; | ||
2152 | prm.tgt = tgt; | ||
2153 | prm.sg = NULL; | ||
2154 | prm.req_cnt = 1; | ||
2155 | |||
2156 | /* Send marker if required */ | ||
2157 | if (qlt_issue_marker(vha, 0) != QLA_SUCCESS) | ||
2158 | return -EIO; | ||
2159 | |||
2160 | ql_dbg(ql_dbg_tgt, vha, 0xe01b, "CTIO_start: vha(%d)", | ||
2161 | (int)vha->vp_idx); | ||
2162 | |||
2163 | /* Calculate number of entries and segments required */ | ||
2164 | if (qlt_pci_map_calc_cnt(&prm) != 0) | ||
2165 | return -EAGAIN; | ||
2166 | |||
2167 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2168 | |||
2169 | /* Does F/W have an IOCBs for this request */ | ||
2170 | res = qlt_check_reserve_free_req(vha, prm.req_cnt); | ||
2171 | if (res != 0) | ||
2172 | goto out_unlock_free_unmap; | ||
2173 | |||
2174 | res = qlt_24xx_build_ctio_pkt(&prm, vha); | ||
2175 | if (unlikely(res != 0)) | ||
2176 | goto out_unlock_free_unmap; | ||
2177 | pkt = (struct ctio7_to_24xx *)prm.pkt; | ||
2178 | pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | | ||
2179 | CTIO7_FLAGS_STATUS_MODE_0); | ||
2180 | qlt_load_data_segments(&prm, vha); | ||
2181 | |||
2182 | cmd->state = QLA_TGT_STATE_NEED_DATA; | ||
2183 | |||
2184 | qla2x00_start_iocbs(vha, vha->req); | ||
2185 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2186 | |||
2187 | return res; | ||
2188 | |||
2189 | out_unlock_free_unmap: | ||
2190 | if (cmd->sg_mapped) | ||
2191 | qlt_unmap_sg(vha, cmd); | ||
2192 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2193 | |||
2194 | return res; | ||
2195 | } | ||
2196 | EXPORT_SYMBOL(qlt_rdy_to_xfer); | ||
2197 | |||
2198 | /* If hardware_lock held on entry, might drop it, then reaquire */ | ||
2199 | /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ | ||
2200 | static int __qlt_send_term_exchange(struct scsi_qla_host *vha, | ||
2201 | struct qla_tgt_cmd *cmd, | ||
2202 | struct atio_from_isp *atio) | ||
2203 | { | ||
2204 | struct ctio7_to_24xx *ctio24; | ||
2205 | struct qla_hw_data *ha = vha->hw; | ||
2206 | request_t *pkt; | ||
2207 | int ret = 0; | ||
2208 | |||
2209 | ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha); | ||
2210 | |||
2211 | pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); | ||
2212 | if (pkt == NULL) { | ||
2213 | ql_dbg(ql_dbg_tgt, vha, 0xe050, | ||
2214 | "qla_target(%d): %s failed: unable to allocate " | ||
2215 | "request packet\n", vha->vp_idx, __func__); | ||
2216 | return -ENOMEM; | ||
2217 | } | ||
2218 | |||
2219 | if (cmd != NULL) { | ||
2220 | if (cmd->state < QLA_TGT_STATE_PROCESSED) { | ||
2221 | ql_dbg(ql_dbg_tgt, vha, 0xe051, | ||
2222 | "qla_target(%d): Terminating cmd %p with " | ||
2223 | "incorrect state %d\n", vha->vp_idx, cmd, | ||
2224 | cmd->state); | ||
2225 | } else | ||
2226 | ret = 1; | ||
2227 | } | ||
2228 | |||
2229 | pkt->entry_count = 1; | ||
2230 | pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; | ||
2231 | |||
2232 | ctio24 = (struct ctio7_to_24xx *)pkt; | ||
2233 | ctio24->entry_type = CTIO_TYPE7; | ||
2234 | ctio24->nport_handle = cmd ? cmd->loop_id : CTIO7_NHANDLE_UNRECOGNIZED; | ||
2235 | ctio24->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); | ||
2236 | ctio24->vp_index = vha->vp_idx; | ||
2237 | ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; | ||
2238 | ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; | ||
2239 | ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; | ||
2240 | ctio24->exchange_addr = atio->u.isp24.exchange_addr; | ||
2241 | ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | | ||
2242 | __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | | ||
2243 | CTIO7_FLAGS_TERMINATE); | ||
2244 | ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); | ||
2245 | |||
2246 | /* Most likely, it isn't needed */ | ||
2247 | ctio24->u.status1.residual = get_unaligned((uint32_t *) | ||
2248 | &atio->u.isp24.fcp_cmnd.add_cdb[ | ||
2249 | atio->u.isp24.fcp_cmnd.add_cdb_len]); | ||
2250 | if (ctio24->u.status1.residual != 0) | ||
2251 | ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER; | ||
2252 | |||
2253 | qla2x00_start_iocbs(vha, vha->req); | ||
2254 | return ret; | ||
2255 | } | ||
2256 | |||
2257 | static void qlt_send_term_exchange(struct scsi_qla_host *vha, | ||
2258 | struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) | ||
2259 | { | ||
2260 | unsigned long flags; | ||
2261 | int rc; | ||
2262 | |||
2263 | if (qlt_issue_marker(vha, ha_locked) < 0) | ||
2264 | return; | ||
2265 | |||
2266 | if (ha_locked) { | ||
2267 | rc = __qlt_send_term_exchange(vha, cmd, atio); | ||
2268 | goto done; | ||
2269 | } | ||
2270 | spin_lock_irqsave(&vha->hw->hardware_lock, flags); | ||
2271 | rc = __qlt_send_term_exchange(vha, cmd, atio); | ||
2272 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
2273 | done: | ||
2274 | if (rc == 1) { | ||
2275 | if (!ha_locked && !in_interrupt()) | ||
2276 | msleep(250); /* just in case */ | ||
2277 | |||
2278 | vha->hw->tgt.tgt_ops->free_cmd(cmd); | ||
2279 | } | ||
2280 | } | ||
2281 | |||
2282 | void qlt_free_cmd(struct qla_tgt_cmd *cmd) | ||
2283 | { | ||
2284 | BUG_ON(cmd->sg_mapped); | ||
2285 | |||
2286 | if (unlikely(cmd->free_sg)) | ||
2287 | kfree(cmd->sg); | ||
2288 | kmem_cache_free(qla_tgt_cmd_cachep, cmd); | ||
2289 | } | ||
2290 | EXPORT_SYMBOL(qlt_free_cmd); | ||
2291 | |||
2292 | /* ha->hardware_lock supposed to be held on entry */ | ||
2293 | static int qlt_prepare_srr_ctio(struct scsi_qla_host *vha, | ||
2294 | struct qla_tgt_cmd *cmd, void *ctio) | ||
2295 | { | ||
2296 | struct qla_tgt_srr_ctio *sc; | ||
2297 | struct qla_hw_data *ha = vha->hw; | ||
2298 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2299 | struct qla_tgt_srr_imm *imm; | ||
2300 | |||
2301 | tgt->ctio_srr_id++; | ||
2302 | |||
2303 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019, | ||
2304 | "qla_target(%d): CTIO with SRR status received\n", vha->vp_idx); | ||
2305 | |||
2306 | if (!ctio) { | ||
2307 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf055, | ||
2308 | "qla_target(%d): SRR CTIO, but ctio is NULL\n", | ||
2309 | vha->vp_idx); | ||
2310 | return -EINVAL; | ||
2311 | } | ||
2312 | |||
2313 | sc = kzalloc(sizeof(*sc), GFP_ATOMIC); | ||
2314 | if (sc != NULL) { | ||
2315 | sc->cmd = cmd; | ||
2316 | /* IRQ is already OFF */ | ||
2317 | spin_lock(&tgt->srr_lock); | ||
2318 | sc->srr_id = tgt->ctio_srr_id; | ||
2319 | list_add_tail(&sc->srr_list_entry, | ||
2320 | &tgt->srr_ctio_list); | ||
2321 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a, | ||
2322 | "CTIO SRR %p added (id %d)\n", sc, sc->srr_id); | ||
2323 | if (tgt->imm_srr_id == tgt->ctio_srr_id) { | ||
2324 | int found = 0; | ||
2325 | list_for_each_entry(imm, &tgt->srr_imm_list, | ||
2326 | srr_list_entry) { | ||
2327 | if (imm->srr_id == sc->srr_id) { | ||
2328 | found = 1; | ||
2329 | break; | ||
2330 | } | ||
2331 | } | ||
2332 | if (found) { | ||
2333 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01b, | ||
2334 | "Scheduling srr work\n"); | ||
2335 | schedule_work(&tgt->srr_work); | ||
2336 | } else { | ||
2337 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf056, | ||
2338 | "qla_target(%d): imm_srr_id " | ||
2339 | "== ctio_srr_id (%d), but there is no " | ||
2340 | "corresponding SRR IMM, deleting CTIO " | ||
2341 | "SRR %p\n", vha->vp_idx, | ||
2342 | tgt->ctio_srr_id, sc); | ||
2343 | list_del(&sc->srr_list_entry); | ||
2344 | spin_unlock(&tgt->srr_lock); | ||
2345 | |||
2346 | kfree(sc); | ||
2347 | return -EINVAL; | ||
2348 | } | ||
2349 | } | ||
2350 | spin_unlock(&tgt->srr_lock); | ||
2351 | } else { | ||
2352 | struct qla_tgt_srr_imm *ti; | ||
2353 | |||
2354 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf057, | ||
2355 | "qla_target(%d): Unable to allocate SRR CTIO entry\n", | ||
2356 | vha->vp_idx); | ||
2357 | spin_lock(&tgt->srr_lock); | ||
2358 | list_for_each_entry_safe(imm, ti, &tgt->srr_imm_list, | ||
2359 | srr_list_entry) { | ||
2360 | if (imm->srr_id == tgt->ctio_srr_id) { | ||
2361 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01c, | ||
2362 | "IMM SRR %p deleted (id %d)\n", | ||
2363 | imm, imm->srr_id); | ||
2364 | list_del(&imm->srr_list_entry); | ||
2365 | qlt_reject_free_srr_imm(vha, imm, 1); | ||
2366 | } | ||
2367 | } | ||
2368 | spin_unlock(&tgt->srr_lock); | ||
2369 | |||
2370 | return -ENOMEM; | ||
2371 | } | ||
2372 | |||
2373 | return 0; | ||
2374 | } | ||
2375 | |||
2376 | /* | ||
2377 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
2378 | */ | ||
2379 | static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, | ||
2380 | struct qla_tgt_cmd *cmd, uint32_t status) | ||
2381 | { | ||
2382 | int term = 0; | ||
2383 | |||
2384 | if (ctio != NULL) { | ||
2385 | struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio; | ||
2386 | term = !(c->flags & | ||
2387 | __constant_cpu_to_le16(OF_TERM_EXCH)); | ||
2388 | } else | ||
2389 | term = 1; | ||
2390 | |||
2391 | if (term) | ||
2392 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); | ||
2393 | |||
2394 | return term; | ||
2395 | } | ||
2396 | |||
2397 | /* ha->hardware_lock supposed to be held on entry */ | ||
2398 | static inline struct qla_tgt_cmd *qlt_get_cmd(struct scsi_qla_host *vha, | ||
2399 | uint32_t handle) | ||
2400 | { | ||
2401 | struct qla_hw_data *ha = vha->hw; | ||
2402 | |||
2403 | handle--; | ||
2404 | if (ha->tgt.cmds[handle] != NULL) { | ||
2405 | struct qla_tgt_cmd *cmd = ha->tgt.cmds[handle]; | ||
2406 | ha->tgt.cmds[handle] = NULL; | ||
2407 | return cmd; | ||
2408 | } else | ||
2409 | return NULL; | ||
2410 | } | ||
2411 | |||
2412 | /* ha->hardware_lock supposed to be held on entry */ | ||
2413 | static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha, | ||
2414 | uint32_t handle, void *ctio) | ||
2415 | { | ||
2416 | struct qla_tgt_cmd *cmd = NULL; | ||
2417 | |||
2418 | /* Clear out internal marks */ | ||
2419 | handle &= ~(CTIO_COMPLETION_HANDLE_MARK | | ||
2420 | CTIO_INTERMEDIATE_HANDLE_MARK); | ||
2421 | |||
2422 | if (handle != QLA_TGT_NULL_HANDLE) { | ||
2423 | if (unlikely(handle == QLA_TGT_SKIP_HANDLE)) { | ||
2424 | ql_dbg(ql_dbg_tgt, vha, 0xe01d, "%s", | ||
2425 | "SKIP_HANDLE CTIO\n"); | ||
2426 | return NULL; | ||
2427 | } | ||
2428 | /* handle-1 is actually used */ | ||
2429 | if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) { | ||
2430 | ql_dbg(ql_dbg_tgt, vha, 0xe052, | ||
2431 | "qla_target(%d): Wrong handle %x received\n", | ||
2432 | vha->vp_idx, handle); | ||
2433 | return NULL; | ||
2434 | } | ||
2435 | cmd = qlt_get_cmd(vha, handle); | ||
2436 | if (unlikely(cmd == NULL)) { | ||
2437 | ql_dbg(ql_dbg_tgt, vha, 0xe053, | ||
2438 | "qla_target(%d): Suspicious: unable to " | ||
2439 | "find the command with handle %x\n", vha->vp_idx, | ||
2440 | handle); | ||
2441 | return NULL; | ||
2442 | } | ||
2443 | } else if (ctio != NULL) { | ||
2444 | /* We can't get loop ID from CTIO7 */ | ||
2445 | ql_dbg(ql_dbg_tgt, vha, 0xe054, | ||
2446 | "qla_target(%d): Wrong CTIO received: QLA24xx doesn't " | ||
2447 | "support NULL handles\n", vha->vp_idx); | ||
2448 | return NULL; | ||
2449 | } | ||
2450 | |||
2451 | return cmd; | ||
2452 | } | ||
2453 | |||
2454 | /* | ||
2455 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
2456 | */ | ||
2457 | static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, | ||
2458 | uint32_t status, void *ctio) | ||
2459 | { | ||
2460 | struct qla_hw_data *ha = vha->hw; | ||
2461 | struct se_cmd *se_cmd; | ||
2462 | struct target_core_fabric_ops *tfo; | ||
2463 | struct qla_tgt_cmd *cmd; | ||
2464 | |||
2465 | ql_dbg(ql_dbg_tgt, vha, 0xe01e, | ||
2466 | "qla_target(%d): handle(ctio %p status %#x) <- %08x\n", | ||
2467 | vha->vp_idx, ctio, status, handle); | ||
2468 | |||
2469 | if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) { | ||
2470 | /* That could happen only in case of an error/reset/abort */ | ||
2471 | if (status != CTIO_SUCCESS) { | ||
2472 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01d, | ||
2473 | "Intermediate CTIO received" | ||
2474 | " (status %x)\n", status); | ||
2475 | } | ||
2476 | return; | ||
2477 | } | ||
2478 | |||
2479 | cmd = qlt_ctio_to_cmd(vha, handle, ctio); | ||
2480 | if (cmd == NULL) { | ||
2481 | if (status != CTIO_SUCCESS) | ||
2482 | qlt_term_ctio_exchange(vha, ctio, NULL, status); | ||
2483 | return; | ||
2484 | } | ||
2485 | se_cmd = &cmd->se_cmd; | ||
2486 | tfo = se_cmd->se_tfo; | ||
2487 | |||
2488 | if (cmd->sg_mapped) | ||
2489 | qlt_unmap_sg(vha, cmd); | ||
2490 | |||
2491 | if (unlikely(status != CTIO_SUCCESS)) { | ||
2492 | switch (status & 0xFFFF) { | ||
2493 | case CTIO_LIP_RESET: | ||
2494 | case CTIO_TARGET_RESET: | ||
2495 | case CTIO_ABORTED: | ||
2496 | case CTIO_TIMEOUT: | ||
2497 | case CTIO_INVALID_RX_ID: | ||
2498 | /* They are OK */ | ||
2499 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058, | ||
2500 | "qla_target(%d): CTIO with " | ||
2501 | "status %#x received, state %x, se_cmd %p, " | ||
2502 | "(LIP_RESET=e, ABORTED=2, TARGET_RESET=17, " | ||
2503 | "TIMEOUT=b, INVALID_RX_ID=8)\n", vha->vp_idx, | ||
2504 | status, cmd->state, se_cmd); | ||
2505 | break; | ||
2506 | |||
2507 | case CTIO_PORT_LOGGED_OUT: | ||
2508 | case CTIO_PORT_UNAVAILABLE: | ||
2509 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059, | ||
2510 | "qla_target(%d): CTIO with PORT LOGGED " | ||
2511 | "OUT (29) or PORT UNAVAILABLE (28) status %x " | ||
2512 | "received (state %x, se_cmd %p)\n", vha->vp_idx, | ||
2513 | status, cmd->state, se_cmd); | ||
2514 | break; | ||
2515 | |||
2516 | case CTIO_SRR_RECEIVED: | ||
2517 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05a, | ||
2518 | "qla_target(%d): CTIO with SRR_RECEIVED" | ||
2519 | " status %x received (state %x, se_cmd %p)\n", | ||
2520 | vha->vp_idx, status, cmd->state, se_cmd); | ||
2521 | if (qlt_prepare_srr_ctio(vha, cmd, ctio) != 0) | ||
2522 | break; | ||
2523 | else | ||
2524 | return; | ||
2525 | |||
2526 | default: | ||
2527 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b, | ||
2528 | "qla_target(%d): CTIO with error status " | ||
2529 | "0x%x received (state %x, se_cmd %p\n", | ||
2530 | vha->vp_idx, status, cmd->state, se_cmd); | ||
2531 | break; | ||
2532 | } | ||
2533 | |||
2534 | if (cmd->state != QLA_TGT_STATE_NEED_DATA) | ||
2535 | if (qlt_term_ctio_exchange(vha, ctio, cmd, status)) | ||
2536 | return; | ||
2537 | } | ||
2538 | |||
2539 | if (cmd->state == QLA_TGT_STATE_PROCESSED) { | ||
2540 | ql_dbg(ql_dbg_tgt, vha, 0xe01f, "Command %p finished\n", cmd); | ||
2541 | } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { | ||
2542 | int rx_status = 0; | ||
2543 | |||
2544 | cmd->state = QLA_TGT_STATE_DATA_IN; | ||
2545 | |||
2546 | if (unlikely(status != CTIO_SUCCESS)) | ||
2547 | rx_status = -EIO; | ||
2548 | else | ||
2549 | cmd->write_data_transferred = 1; | ||
2550 | |||
2551 | ql_dbg(ql_dbg_tgt, vha, 0xe020, | ||
2552 | "Data received, context %x, rx_status %d\n", | ||
2553 | 0x0, rx_status); | ||
2554 | |||
2555 | ha->tgt.tgt_ops->handle_data(cmd); | ||
2556 | return; | ||
2557 | } else if (cmd->state == QLA_TGT_STATE_ABORTED) { | ||
2558 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, | ||
2559 | "Aborted command %p (tag %d) finished\n", cmd, cmd->tag); | ||
2560 | } else { | ||
2561 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, | ||
2562 | "qla_target(%d): A command in state (%d) should " | ||
2563 | "not return a CTIO complete\n", vha->vp_idx, cmd->state); | ||
2564 | } | ||
2565 | |||
2566 | if (unlikely(status != CTIO_SUCCESS)) { | ||
2567 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01f, "Finishing failed CTIO\n"); | ||
2568 | dump_stack(); | ||
2569 | } | ||
2570 | |||
2571 | ha->tgt.tgt_ops->free_cmd(cmd); | ||
2572 | } | ||
2573 | |||
2574 | /* ha->hardware_lock supposed to be held on entry */ | ||
2575 | /* called via callback from qla2xxx */ | ||
2576 | void qlt_ctio_completion(struct scsi_qla_host *vha, uint32_t handle) | ||
2577 | { | ||
2578 | struct qla_hw_data *ha = vha->hw; | ||
2579 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2580 | |||
2581 | if (likely(tgt == NULL)) { | ||
2582 | ql_dbg(ql_dbg_tgt, vha, 0xe021, | ||
2583 | "CTIO, but target mode not enabled" | ||
2584 | " (ha %d %p handle %#x)", vha->vp_idx, ha, handle); | ||
2585 | return; | ||
2586 | } | ||
2587 | |||
2588 | tgt->irq_cmd_count++; | ||
2589 | qlt_do_ctio_completion(vha, handle, CTIO_SUCCESS, NULL); | ||
2590 | tgt->irq_cmd_count--; | ||
2591 | } | ||
2592 | |||
2593 | static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha, | ||
2594 | uint8_t task_codes) | ||
2595 | { | ||
2596 | int fcp_task_attr; | ||
2597 | |||
2598 | switch (task_codes) { | ||
2599 | case ATIO_SIMPLE_QUEUE: | ||
2600 | fcp_task_attr = MSG_SIMPLE_TAG; | ||
2601 | break; | ||
2602 | case ATIO_HEAD_OF_QUEUE: | ||
2603 | fcp_task_attr = MSG_HEAD_TAG; | ||
2604 | break; | ||
2605 | case ATIO_ORDERED_QUEUE: | ||
2606 | fcp_task_attr = MSG_ORDERED_TAG; | ||
2607 | break; | ||
2608 | case ATIO_ACA_QUEUE: | ||
2609 | fcp_task_attr = MSG_ACA_TAG; | ||
2610 | break; | ||
2611 | case ATIO_UNTAGGED: | ||
2612 | fcp_task_attr = MSG_SIMPLE_TAG; | ||
2613 | break; | ||
2614 | default: | ||
2615 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05d, | ||
2616 | "qla_target: unknown task code %x, use ORDERED instead\n", | ||
2617 | task_codes); | ||
2618 | fcp_task_attr = MSG_ORDERED_TAG; | ||
2619 | break; | ||
2620 | } | ||
2621 | |||
2622 | return fcp_task_attr; | ||
2623 | } | ||
2624 | |||
2625 | static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *, | ||
2626 | uint8_t *); | ||
2627 | /* | ||
2628 | * Process context for I/O path into tcm_qla2xxx code | ||
2629 | */ | ||
2630 | static void qlt_do_work(struct work_struct *work) | ||
2631 | { | ||
2632 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); | ||
2633 | scsi_qla_host_t *vha = cmd->vha; | ||
2634 | struct qla_hw_data *ha = vha->hw; | ||
2635 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2636 | struct qla_tgt_sess *sess = NULL; | ||
2637 | struct atio_from_isp *atio = &cmd->atio; | ||
2638 | unsigned char *cdb; | ||
2639 | unsigned long flags; | ||
2640 | uint32_t data_length; | ||
2641 | int ret, fcp_task_attr, data_dir, bidi = 0; | ||
2642 | |||
2643 | if (tgt->tgt_stop) | ||
2644 | goto out_term; | ||
2645 | |||
2646 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2647 | sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, | ||
2648 | atio->u.isp24.fcp_hdr.s_id); | ||
2649 | if (sess) { | ||
2650 | if (unlikely(sess->tearing_down)) { | ||
2651 | sess = NULL; | ||
2652 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2653 | goto out_term; | ||
2654 | } else { | ||
2655 | /* | ||
2656 | * Do the extra kref_get() before dropping | ||
2657 | * qla_hw_data->hardware_lock. | ||
2658 | */ | ||
2659 | kref_get(&sess->se_sess->sess_kref); | ||
2660 | } | ||
2661 | } | ||
2662 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2663 | |||
2664 | if (unlikely(!sess)) { | ||
2665 | uint8_t *s_id = atio->u.isp24.fcp_hdr.s_id; | ||
2666 | |||
2667 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, | ||
2668 | "qla_target(%d): Unable to find wwn login" | ||
2669 | " (s_id %x:%x:%x), trying to create it manually\n", | ||
2670 | vha->vp_idx, s_id[0], s_id[1], s_id[2]); | ||
2671 | |||
2672 | if (atio->u.raw.entry_count > 1) { | ||
2673 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, | ||
2674 | "Dropping multy entry cmd %p\n", cmd); | ||
2675 | goto out_term; | ||
2676 | } | ||
2677 | |||
2678 | mutex_lock(&ha->tgt.tgt_mutex); | ||
2679 | sess = qlt_make_local_sess(vha, s_id); | ||
2680 | /* sess has an extra creation ref. */ | ||
2681 | mutex_unlock(&ha->tgt.tgt_mutex); | ||
2682 | |||
2683 | if (!sess) | ||
2684 | goto out_term; | ||
2685 | } | ||
2686 | |||
2687 | cmd->sess = sess; | ||
2688 | cmd->loop_id = sess->loop_id; | ||
2689 | cmd->conf_compl_supported = sess->conf_compl_supported; | ||
2690 | |||
2691 | cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; | ||
2692 | cmd->tag = atio->u.isp24.exchange_addr; | ||
2693 | cmd->unpacked_lun = scsilun_to_int( | ||
2694 | (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); | ||
2695 | |||
2696 | if (atio->u.isp24.fcp_cmnd.rddata && | ||
2697 | atio->u.isp24.fcp_cmnd.wrdata) { | ||
2698 | bidi = 1; | ||
2699 | data_dir = DMA_TO_DEVICE; | ||
2700 | } else if (atio->u.isp24.fcp_cmnd.rddata) | ||
2701 | data_dir = DMA_FROM_DEVICE; | ||
2702 | else if (atio->u.isp24.fcp_cmnd.wrdata) | ||
2703 | data_dir = DMA_TO_DEVICE; | ||
2704 | else | ||
2705 | data_dir = DMA_NONE; | ||
2706 | |||
2707 | fcp_task_attr = qlt_get_fcp_task_attr(vha, | ||
2708 | atio->u.isp24.fcp_cmnd.task_attr); | ||
2709 | data_length = be32_to_cpu(get_unaligned((uint32_t *) | ||
2710 | &atio->u.isp24.fcp_cmnd.add_cdb[ | ||
2711 | atio->u.isp24.fcp_cmnd.add_cdb_len])); | ||
2712 | |||
2713 | ql_dbg(ql_dbg_tgt, vha, 0xe022, | ||
2714 | "qla_target: START qla command: %p lun: 0x%04x (tag %d)\n", | ||
2715 | cmd, cmd->unpacked_lun, cmd->tag); | ||
2716 | |||
2717 | ret = vha->hw->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length, | ||
2718 | fcp_task_attr, data_dir, bidi); | ||
2719 | if (ret != 0) | ||
2720 | goto out_term; | ||
2721 | /* | ||
2722 | * Drop extra session reference from qla_tgt_handle_cmd_for_atio*( | ||
2723 | */ | ||
2724 | ha->tgt.tgt_ops->put_sess(sess); | ||
2725 | return; | ||
2726 | |||
2727 | out_term: | ||
2728 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf020, "Terminating work cmd %p", cmd); | ||
2729 | /* | ||
2730 | * cmd has not sent to target yet, so pass NULL as the second argument | ||
2731 | */ | ||
2732 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2733 | qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); | ||
2734 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2735 | if (sess) | ||
2736 | ha->tgt.tgt_ops->put_sess(sess); | ||
2737 | } | ||
2738 | |||
2739 | /* ha->hardware_lock supposed to be held on entry */ | ||
2740 | static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, | ||
2741 | struct atio_from_isp *atio) | ||
2742 | { | ||
2743 | struct qla_hw_data *ha = vha->hw; | ||
2744 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2745 | struct qla_tgt_cmd *cmd; | ||
2746 | |||
2747 | if (unlikely(tgt->tgt_stop)) { | ||
2748 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf021, | ||
2749 | "New command while device %p is shutting down\n", tgt); | ||
2750 | return -EFAULT; | ||
2751 | } | ||
2752 | |||
2753 | cmd = kmem_cache_zalloc(qla_tgt_cmd_cachep, GFP_ATOMIC); | ||
2754 | if (!cmd) { | ||
2755 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05e, | ||
2756 | "qla_target(%d): Allocation of cmd failed\n", vha->vp_idx); | ||
2757 | return -ENOMEM; | ||
2758 | } | ||
2759 | |||
2760 | INIT_LIST_HEAD(&cmd->cmd_list); | ||
2761 | |||
2762 | memcpy(&cmd->atio, atio, sizeof(*atio)); | ||
2763 | cmd->state = QLA_TGT_STATE_NEW; | ||
2764 | cmd->tgt = ha->tgt.qla_tgt; | ||
2765 | cmd->vha = vha; | ||
2766 | |||
2767 | INIT_WORK(&cmd->work, qlt_do_work); | ||
2768 | queue_work(qla_tgt_wq, &cmd->work); | ||
2769 | return 0; | ||
2770 | |||
2771 | } | ||
2772 | |||
2773 | /* ha->hardware_lock supposed to be held on entry */ | ||
2774 | static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, | ||
2775 | int fn, void *iocb, int flags) | ||
2776 | { | ||
2777 | struct scsi_qla_host *vha = sess->vha; | ||
2778 | struct qla_hw_data *ha = vha->hw; | ||
2779 | struct qla_tgt_mgmt_cmd *mcmd; | ||
2780 | int res; | ||
2781 | uint8_t tmr_func; | ||
2782 | |||
2783 | mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); | ||
2784 | if (!mcmd) { | ||
2785 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10009, | ||
2786 | "qla_target(%d): Allocation of management " | ||
2787 | "command failed, some commands and their data could " | ||
2788 | "leak\n", vha->vp_idx); | ||
2789 | return -ENOMEM; | ||
2790 | } | ||
2791 | memset(mcmd, 0, sizeof(*mcmd)); | ||
2792 | mcmd->sess = sess; | ||
2793 | |||
2794 | if (iocb) { | ||
2795 | memcpy(&mcmd->orig_iocb.imm_ntfy, iocb, | ||
2796 | sizeof(mcmd->orig_iocb.imm_ntfy)); | ||
2797 | } | ||
2798 | mcmd->tmr_func = fn; | ||
2799 | mcmd->flags = flags; | ||
2800 | |||
2801 | switch (fn) { | ||
2802 | case QLA_TGT_CLEAR_ACA: | ||
2803 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10000, | ||
2804 | "qla_target(%d): CLEAR_ACA received\n", sess->vha->vp_idx); | ||
2805 | tmr_func = TMR_CLEAR_ACA; | ||
2806 | break; | ||
2807 | |||
2808 | case QLA_TGT_TARGET_RESET: | ||
2809 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10001, | ||
2810 | "qla_target(%d): TARGET_RESET received\n", | ||
2811 | sess->vha->vp_idx); | ||
2812 | tmr_func = TMR_TARGET_WARM_RESET; | ||
2813 | break; | ||
2814 | |||
2815 | case QLA_TGT_LUN_RESET: | ||
2816 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002, | ||
2817 | "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx); | ||
2818 | tmr_func = TMR_LUN_RESET; | ||
2819 | break; | ||
2820 | |||
2821 | case QLA_TGT_CLEAR_TS: | ||
2822 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10003, | ||
2823 | "qla_target(%d): CLEAR_TS received\n", sess->vha->vp_idx); | ||
2824 | tmr_func = TMR_CLEAR_TASK_SET; | ||
2825 | break; | ||
2826 | |||
2827 | case QLA_TGT_ABORT_TS: | ||
2828 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10004, | ||
2829 | "qla_target(%d): ABORT_TS received\n", sess->vha->vp_idx); | ||
2830 | tmr_func = TMR_ABORT_TASK_SET; | ||
2831 | break; | ||
2832 | #if 0 | ||
2833 | case QLA_TGT_ABORT_ALL: | ||
2834 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10005, | ||
2835 | "qla_target(%d): Doing ABORT_ALL_TASKS\n", | ||
2836 | sess->vha->vp_idx); | ||
2837 | tmr_func = 0; | ||
2838 | break; | ||
2839 | |||
2840 | case QLA_TGT_ABORT_ALL_SESS: | ||
2841 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10006, | ||
2842 | "qla_target(%d): Doing ABORT_ALL_TASKS_SESS\n", | ||
2843 | sess->vha->vp_idx); | ||
2844 | tmr_func = 0; | ||
2845 | break; | ||
2846 | |||
2847 | case QLA_TGT_NEXUS_LOSS_SESS: | ||
2848 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10007, | ||
2849 | "qla_target(%d): Doing NEXUS_LOSS_SESS\n", | ||
2850 | sess->vha->vp_idx); | ||
2851 | tmr_func = 0; | ||
2852 | break; | ||
2853 | |||
2854 | case QLA_TGT_NEXUS_LOSS: | ||
2855 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10008, | ||
2856 | "qla_target(%d): Doing NEXUS_LOSS\n", sess->vha->vp_idx); | ||
2857 | tmr_func = 0; | ||
2858 | break; | ||
2859 | #endif | ||
2860 | default: | ||
2861 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000a, | ||
2862 | "qla_target(%d): Unknown task mgmt fn 0x%x\n", | ||
2863 | sess->vha->vp_idx, fn); | ||
2864 | mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); | ||
2865 | return -ENOSYS; | ||
2866 | } | ||
2867 | |||
2868 | res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, tmr_func, 0); | ||
2869 | if (res != 0) { | ||
2870 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000b, | ||
2871 | "qla_target(%d): tgt.tgt_ops->handle_tmr() failed: %d\n", | ||
2872 | sess->vha->vp_idx, res); | ||
2873 | mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); | ||
2874 | return -EFAULT; | ||
2875 | } | ||
2876 | |||
2877 | return 0; | ||
2878 | } | ||
2879 | |||
2880 | /* ha->hardware_lock supposed to be held on entry */ | ||
2881 | static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) | ||
2882 | { | ||
2883 | struct atio_from_isp *a = (struct atio_from_isp *)iocb; | ||
2884 | struct qla_hw_data *ha = vha->hw; | ||
2885 | struct qla_tgt *tgt; | ||
2886 | struct qla_tgt_sess *sess; | ||
2887 | uint32_t lun, unpacked_lun; | ||
2888 | int lun_size, fn; | ||
2889 | |||
2890 | tgt = ha->tgt.qla_tgt; | ||
2891 | |||
2892 | lun = a->u.isp24.fcp_cmnd.lun; | ||
2893 | lun_size = sizeof(a->u.isp24.fcp_cmnd.lun); | ||
2894 | fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; | ||
2895 | sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, | ||
2896 | a->u.isp24.fcp_hdr.s_id); | ||
2897 | unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); | ||
2898 | |||
2899 | if (!sess) { | ||
2900 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf024, | ||
2901 | "qla_target(%d): task mgmt fn 0x%x for " | ||
2902 | "non-existant session\n", vha->vp_idx, fn); | ||
2903 | return qlt_sched_sess_work(tgt, QLA_TGT_SESS_WORK_TM, iocb, | ||
2904 | sizeof(struct atio_from_isp)); | ||
2905 | } | ||
2906 | |||
2907 | return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); | ||
2908 | } | ||
2909 | |||
2910 | /* ha->hardware_lock supposed to be held on entry */ | ||
2911 | static int __qlt_abort_task(struct scsi_qla_host *vha, | ||
2912 | struct imm_ntfy_from_isp *iocb, struct qla_tgt_sess *sess) | ||
2913 | { | ||
2914 | struct atio_from_isp *a = (struct atio_from_isp *)iocb; | ||
2915 | struct qla_hw_data *ha = vha->hw; | ||
2916 | struct qla_tgt_mgmt_cmd *mcmd; | ||
2917 | uint32_t lun, unpacked_lun; | ||
2918 | int rc; | ||
2919 | |||
2920 | mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); | ||
2921 | if (mcmd == NULL) { | ||
2922 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05f, | ||
2923 | "qla_target(%d): %s: Allocation of ABORT cmd failed\n", | ||
2924 | vha->vp_idx, __func__); | ||
2925 | return -ENOMEM; | ||
2926 | } | ||
2927 | memset(mcmd, 0, sizeof(*mcmd)); | ||
2928 | |||
2929 | mcmd->sess = sess; | ||
2930 | memcpy(&mcmd->orig_iocb.imm_ntfy, iocb, | ||
2931 | sizeof(mcmd->orig_iocb.imm_ntfy)); | ||
2932 | |||
2933 | lun = a->u.isp24.fcp_cmnd.lun; | ||
2934 | unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); | ||
2935 | |||
2936 | rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, TMR_ABORT_TASK, | ||
2937 | le16_to_cpu(iocb->u.isp2x.seq_id)); | ||
2938 | if (rc != 0) { | ||
2939 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf060, | ||
2940 | "qla_target(%d): tgt_ops->handle_tmr() failed: %d\n", | ||
2941 | vha->vp_idx, rc); | ||
2942 | mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); | ||
2943 | return -EFAULT; | ||
2944 | } | ||
2945 | |||
2946 | return 0; | ||
2947 | } | ||
2948 | |||
2949 | /* ha->hardware_lock supposed to be held on entry */ | ||
2950 | static int qlt_abort_task(struct scsi_qla_host *vha, | ||
2951 | struct imm_ntfy_from_isp *iocb) | ||
2952 | { | ||
2953 | struct qla_hw_data *ha = vha->hw; | ||
2954 | struct qla_tgt_sess *sess; | ||
2955 | int loop_id; | ||
2956 | |||
2957 | loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb); | ||
2958 | |||
2959 | sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); | ||
2960 | if (sess == NULL) { | ||
2961 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025, | ||
2962 | "qla_target(%d): task abort for unexisting " | ||
2963 | "session\n", vha->vp_idx); | ||
2964 | return qlt_sched_sess_work(ha->tgt.qla_tgt, | ||
2965 | QLA_TGT_SESS_WORK_ABORT, iocb, sizeof(*iocb)); | ||
2966 | } | ||
2967 | |||
2968 | return __qlt_abort_task(vha, iocb, sess); | ||
2969 | } | ||
2970 | |||
2971 | /* | ||
2972 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
2973 | */ | ||
2974 | static int qlt_24xx_handle_els(struct scsi_qla_host *vha, | ||
2975 | struct imm_ntfy_from_isp *iocb) | ||
2976 | { | ||
2977 | struct qla_hw_data *ha = vha->hw; | ||
2978 | int res = 0; | ||
2979 | |||
2980 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, | ||
2981 | "qla_target(%d): Port ID: 0x%02x:%02x:%02x" | ||
2982 | " ELS opcode: 0x%02x\n", vha->vp_idx, iocb->u.isp24.port_id[0], | ||
2983 | iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[2], | ||
2984 | iocb->u.isp24.status_subcode); | ||
2985 | |||
2986 | switch (iocb->u.isp24.status_subcode) { | ||
2987 | case ELS_PLOGI: | ||
2988 | case ELS_FLOGI: | ||
2989 | case ELS_PRLI: | ||
2990 | case ELS_LOGO: | ||
2991 | case ELS_PRLO: | ||
2992 | res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); | ||
2993 | break; | ||
2994 | case ELS_PDISC: | ||
2995 | case ELS_ADISC: | ||
2996 | { | ||
2997 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
2998 | if (tgt->link_reinit_iocb_pending) { | ||
2999 | qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, | ||
3000 | 0, 0, 0, 0, 0, 0); | ||
3001 | tgt->link_reinit_iocb_pending = 0; | ||
3002 | } | ||
3003 | res = 1; /* send notify ack */ | ||
3004 | break; | ||
3005 | } | ||
3006 | |||
3007 | default: | ||
3008 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061, | ||
3009 | "qla_target(%d): Unsupported ELS command %x " | ||
3010 | "received\n", vha->vp_idx, iocb->u.isp24.status_subcode); | ||
3011 | res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); | ||
3012 | break; | ||
3013 | } | ||
3014 | |||
3015 | return res; | ||
3016 | } | ||
3017 | |||
3018 | static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) | ||
3019 | { | ||
3020 | struct scatterlist *sg, *sgp, *sg_srr, *sg_srr_start = NULL; | ||
3021 | size_t first_offset = 0, rem_offset = offset, tmp = 0; | ||
3022 | int i, sg_srr_cnt, bufflen = 0; | ||
3023 | |||
3024 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe023, | ||
3025 | "Entering qla_tgt_set_data_offset: cmd: %p, cmd->sg: %p, " | ||
3026 | "cmd->sg_cnt: %u, direction: %d\n", | ||
3027 | cmd, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); | ||
3028 | |||
3029 | /* | ||
3030 | * FIXME: Reject non zero SRR relative offset until we can test | ||
3031 | * this code properly. | ||
3032 | */ | ||
3033 | pr_debug("Rejecting non zero SRR rel_offs: %u\n", offset); | ||
3034 | return -1; | ||
3035 | |||
3036 | if (!cmd->sg || !cmd->sg_cnt) { | ||
3037 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe055, | ||
3038 | "Missing cmd->sg or zero cmd->sg_cnt in" | ||
3039 | " qla_tgt_set_data_offset\n"); | ||
3040 | return -EINVAL; | ||
3041 | } | ||
3042 | /* | ||
3043 | * Walk the current cmd->sg list until we locate the new sg_srr_start | ||
3044 | */ | ||
3045 | for_each_sg(cmd->sg, sg, cmd->sg_cnt, i) { | ||
3046 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe024, | ||
3047 | "sg[%d]: %p page: %p, length: %d, offset: %d\n", | ||
3048 | i, sg, sg_page(sg), sg->length, sg->offset); | ||
3049 | |||
3050 | if ((sg->length + tmp) > offset) { | ||
3051 | first_offset = rem_offset; | ||
3052 | sg_srr_start = sg; | ||
3053 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe025, | ||
3054 | "Found matching sg[%d], using %p as sg_srr_start, " | ||
3055 | "and using first_offset: %zu\n", i, sg, | ||
3056 | first_offset); | ||
3057 | break; | ||
3058 | } | ||
3059 | tmp += sg->length; | ||
3060 | rem_offset -= sg->length; | ||
3061 | } | ||
3062 | |||
3063 | if (!sg_srr_start) { | ||
3064 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe056, | ||
3065 | "Unable to locate sg_srr_start for offset: %u\n", offset); | ||
3066 | return -EINVAL; | ||
3067 | } | ||
3068 | sg_srr_cnt = (cmd->sg_cnt - i); | ||
3069 | |||
3070 | sg_srr = kzalloc(sizeof(struct scatterlist) * sg_srr_cnt, GFP_KERNEL); | ||
3071 | if (!sg_srr) { | ||
3072 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe057, | ||
3073 | "Unable to allocate sgp\n"); | ||
3074 | return -ENOMEM; | ||
3075 | } | ||
3076 | sg_init_table(sg_srr, sg_srr_cnt); | ||
3077 | sgp = &sg_srr[0]; | ||
3078 | /* | ||
3079 | * Walk the remaining list for sg_srr_start, mapping to the newly | ||
3080 | * allocated sg_srr taking first_offset into account. | ||
3081 | */ | ||
3082 | for_each_sg(sg_srr_start, sg, sg_srr_cnt, i) { | ||
3083 | if (first_offset) { | ||
3084 | sg_set_page(sgp, sg_page(sg), | ||
3085 | (sg->length - first_offset), first_offset); | ||
3086 | first_offset = 0; | ||
3087 | } else { | ||
3088 | sg_set_page(sgp, sg_page(sg), sg->length, 0); | ||
3089 | } | ||
3090 | bufflen += sgp->length; | ||
3091 | |||
3092 | sgp = sg_next(sgp); | ||
3093 | if (!sgp) | ||
3094 | break; | ||
3095 | } | ||
3096 | |||
3097 | cmd->sg = sg_srr; | ||
3098 | cmd->sg_cnt = sg_srr_cnt; | ||
3099 | cmd->bufflen = bufflen; | ||
3100 | cmd->offset += offset; | ||
3101 | cmd->free_sg = 1; | ||
3102 | |||
3103 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe026, "New cmd->sg: %p\n", cmd->sg); | ||
3104 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe027, "New cmd->sg_cnt: %u\n", | ||
3105 | cmd->sg_cnt); | ||
3106 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe028, "New cmd->bufflen: %u\n", | ||
3107 | cmd->bufflen); | ||
3108 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe029, "New cmd->offset: %u\n", | ||
3109 | cmd->offset); | ||
3110 | |||
3111 | if (cmd->sg_cnt < 0) | ||
3112 | BUG(); | ||
3113 | |||
3114 | if (cmd->bufflen < 0) | ||
3115 | BUG(); | ||
3116 | |||
3117 | return 0; | ||
3118 | } | ||
3119 | |||
3120 | static inline int qlt_srr_adjust_data(struct qla_tgt_cmd *cmd, | ||
3121 | uint32_t srr_rel_offs, int *xmit_type) | ||
3122 | { | ||
3123 | int res = 0, rel_offs; | ||
3124 | |||
3125 | rel_offs = srr_rel_offs - cmd->offset; | ||
3126 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf027, "srr_rel_offs=%d, rel_offs=%d", | ||
3127 | srr_rel_offs, rel_offs); | ||
3128 | |||
3129 | *xmit_type = QLA_TGT_XMIT_ALL; | ||
3130 | |||
3131 | if (rel_offs < 0) { | ||
3132 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf062, | ||
3133 | "qla_target(%d): SRR rel_offs (%d) < 0", | ||
3134 | cmd->vha->vp_idx, rel_offs); | ||
3135 | res = -1; | ||
3136 | } else if (rel_offs == cmd->bufflen) | ||
3137 | *xmit_type = QLA_TGT_XMIT_STATUS; | ||
3138 | else if (rel_offs > 0) | ||
3139 | res = qlt_set_data_offset(cmd, rel_offs); | ||
3140 | |||
3141 | return res; | ||
3142 | } | ||
3143 | |||
3144 | /* No locks, thread context */ | ||
3145 | static void qlt_handle_srr(struct scsi_qla_host *vha, | ||
3146 | struct qla_tgt_srr_ctio *sctio, struct qla_tgt_srr_imm *imm) | ||
3147 | { | ||
3148 | struct imm_ntfy_from_isp *ntfy = | ||
3149 | (struct imm_ntfy_from_isp *)&imm->imm_ntfy; | ||
3150 | struct qla_hw_data *ha = vha->hw; | ||
3151 | struct qla_tgt_cmd *cmd = sctio->cmd; | ||
3152 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
3153 | unsigned long flags; | ||
3154 | int xmit_type = 0, resp = 0; | ||
3155 | uint32_t offset; | ||
3156 | uint16_t srr_ui; | ||
3157 | |||
3158 | offset = le32_to_cpu(ntfy->u.isp24.srr_rel_offs); | ||
3159 | srr_ui = ntfy->u.isp24.srr_ui; | ||
3160 | |||
3161 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf028, "SRR cmd %p, srr_ui %x\n", | ||
3162 | cmd, srr_ui); | ||
3163 | |||
3164 | switch (srr_ui) { | ||
3165 | case SRR_IU_STATUS: | ||
3166 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3167 | qlt_send_notify_ack(vha, ntfy, | ||
3168 | 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); | ||
3169 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3170 | xmit_type = QLA_TGT_XMIT_STATUS; | ||
3171 | resp = 1; | ||
3172 | break; | ||
3173 | case SRR_IU_DATA_IN: | ||
3174 | if (!cmd->sg || !cmd->sg_cnt) { | ||
3175 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf063, | ||
3176 | "Unable to process SRR_IU_DATA_IN due to" | ||
3177 | " missing cmd->sg, state: %d\n", cmd->state); | ||
3178 | dump_stack(); | ||
3179 | goto out_reject; | ||
3180 | } | ||
3181 | if (se_cmd->scsi_status != 0) { | ||
3182 | ql_dbg(ql_dbg_tgt, vha, 0xe02a, | ||
3183 | "Rejecting SRR_IU_DATA_IN with non GOOD " | ||
3184 | "scsi_status\n"); | ||
3185 | goto out_reject; | ||
3186 | } | ||
3187 | cmd->bufflen = se_cmd->data_length; | ||
3188 | |||
3189 | if (qlt_has_data(cmd)) { | ||
3190 | if (qlt_srr_adjust_data(cmd, offset, &xmit_type) != 0) | ||
3191 | goto out_reject; | ||
3192 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3193 | qlt_send_notify_ack(vha, ntfy, | ||
3194 | 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); | ||
3195 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3196 | resp = 1; | ||
3197 | } else { | ||
3198 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064, | ||
3199 | "qla_target(%d): SRR for in data for cmd " | ||
3200 | "without them (tag %d, SCSI status %d), " | ||
3201 | "reject", vha->vp_idx, cmd->tag, | ||
3202 | cmd->se_cmd.scsi_status); | ||
3203 | goto out_reject; | ||
3204 | } | ||
3205 | break; | ||
3206 | case SRR_IU_DATA_OUT: | ||
3207 | if (!cmd->sg || !cmd->sg_cnt) { | ||
3208 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf065, | ||
3209 | "Unable to process SRR_IU_DATA_OUT due to" | ||
3210 | " missing cmd->sg\n"); | ||
3211 | dump_stack(); | ||
3212 | goto out_reject; | ||
3213 | } | ||
3214 | if (se_cmd->scsi_status != 0) { | ||
3215 | ql_dbg(ql_dbg_tgt, vha, 0xe02b, | ||
3216 | "Rejecting SRR_IU_DATA_OUT" | ||
3217 | " with non GOOD scsi_status\n"); | ||
3218 | goto out_reject; | ||
3219 | } | ||
3220 | cmd->bufflen = se_cmd->data_length; | ||
3221 | |||
3222 | if (qlt_has_data(cmd)) { | ||
3223 | if (qlt_srr_adjust_data(cmd, offset, &xmit_type) != 0) | ||
3224 | goto out_reject; | ||
3225 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3226 | qlt_send_notify_ack(vha, ntfy, | ||
3227 | 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); | ||
3228 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3229 | if (xmit_type & QLA_TGT_XMIT_DATA) | ||
3230 | qlt_rdy_to_xfer(cmd); | ||
3231 | } else { | ||
3232 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066, | ||
3233 | "qla_target(%d): SRR for out data for cmd " | ||
3234 | "without them (tag %d, SCSI status %d), " | ||
3235 | "reject", vha->vp_idx, cmd->tag, | ||
3236 | cmd->se_cmd.scsi_status); | ||
3237 | goto out_reject; | ||
3238 | } | ||
3239 | break; | ||
3240 | default: | ||
3241 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf067, | ||
3242 | "qla_target(%d): Unknown srr_ui value %x", | ||
3243 | vha->vp_idx, srr_ui); | ||
3244 | goto out_reject; | ||
3245 | } | ||
3246 | |||
3247 | /* Transmit response in case of status and data-in cases */ | ||
3248 | if (resp) | ||
3249 | qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status); | ||
3250 | |||
3251 | return; | ||
3252 | |||
3253 | out_reject: | ||
3254 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3255 | qlt_send_notify_ack(vha, ntfy, 0, 0, 0, | ||
3256 | NOTIFY_ACK_SRR_FLAGS_REJECT, | ||
3257 | NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, | ||
3258 | NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); | ||
3259 | if (cmd->state == QLA_TGT_STATE_NEED_DATA) { | ||
3260 | cmd->state = QLA_TGT_STATE_DATA_IN; | ||
3261 | dump_stack(); | ||
3262 | } else | ||
3263 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); | ||
3264 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3265 | } | ||
3266 | |||
3267 | static void qlt_reject_free_srr_imm(struct scsi_qla_host *vha, | ||
3268 | struct qla_tgt_srr_imm *imm, int ha_locked) | ||
3269 | { | ||
3270 | struct qla_hw_data *ha = vha->hw; | ||
3271 | unsigned long flags = 0; | ||
3272 | |||
3273 | if (!ha_locked) | ||
3274 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3275 | |||
3276 | qlt_send_notify_ack(vha, (void *)&imm->imm_ntfy, 0, 0, 0, | ||
3277 | NOTIFY_ACK_SRR_FLAGS_REJECT, | ||
3278 | NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, | ||
3279 | NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); | ||
3280 | |||
3281 | if (!ha_locked) | ||
3282 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3283 | |||
3284 | kfree(imm); | ||
3285 | } | ||
3286 | |||
3287 | static void qlt_handle_srr_work(struct work_struct *work) | ||
3288 | { | ||
3289 | struct qla_tgt *tgt = container_of(work, struct qla_tgt, srr_work); | ||
3290 | struct scsi_qla_host *vha = tgt->vha; | ||
3291 | struct qla_tgt_srr_ctio *sctio; | ||
3292 | unsigned long flags; | ||
3293 | |||
3294 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf029, "Entering SRR work (tgt %p)\n", | ||
3295 | tgt); | ||
3296 | |||
3297 | restart: | ||
3298 | spin_lock_irqsave(&tgt->srr_lock, flags); | ||
3299 | list_for_each_entry(sctio, &tgt->srr_ctio_list, srr_list_entry) { | ||
3300 | struct qla_tgt_srr_imm *imm, *i, *ti; | ||
3301 | struct qla_tgt_cmd *cmd; | ||
3302 | struct se_cmd *se_cmd; | ||
3303 | |||
3304 | imm = NULL; | ||
3305 | list_for_each_entry_safe(i, ti, &tgt->srr_imm_list, | ||
3306 | srr_list_entry) { | ||
3307 | if (i->srr_id == sctio->srr_id) { | ||
3308 | list_del(&i->srr_list_entry); | ||
3309 | if (imm) { | ||
3310 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf068, | ||
3311 | "qla_target(%d): There must be " | ||
3312 | "only one IMM SRR per CTIO SRR " | ||
3313 | "(IMM SRR %p, id %d, CTIO %p\n", | ||
3314 | vha->vp_idx, i, i->srr_id, sctio); | ||
3315 | qlt_reject_free_srr_imm(tgt->vha, i, 0); | ||
3316 | } else | ||
3317 | imm = i; | ||
3318 | } | ||
3319 | } | ||
3320 | |||
3321 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02a, | ||
3322 | "IMM SRR %p, CTIO SRR %p (id %d)\n", imm, sctio, | ||
3323 | sctio->srr_id); | ||
3324 | |||
3325 | if (imm == NULL) { | ||
3326 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02b, | ||
3327 | "Not found matching IMM for SRR CTIO (id %d)\n", | ||
3328 | sctio->srr_id); | ||
3329 | continue; | ||
3330 | } else | ||
3331 | list_del(&sctio->srr_list_entry); | ||
3332 | |||
3333 | spin_unlock_irqrestore(&tgt->srr_lock, flags); | ||
3334 | |||
3335 | cmd = sctio->cmd; | ||
3336 | /* | ||
3337 | * Reset qla_tgt_cmd SRR values and SGL pointer+count to follow | ||
3338 | * tcm_qla2xxx_write_pending() and tcm_qla2xxx_queue_data_in() | ||
3339 | * logic.. | ||
3340 | */ | ||
3341 | cmd->offset = 0; | ||
3342 | if (cmd->free_sg) { | ||
3343 | kfree(cmd->sg); | ||
3344 | cmd->sg = NULL; | ||
3345 | cmd->free_sg = 0; | ||
3346 | } | ||
3347 | se_cmd = &cmd->se_cmd; | ||
3348 | |||
3349 | cmd->sg_cnt = se_cmd->t_data_nents; | ||
3350 | cmd->sg = se_cmd->t_data_sg; | ||
3351 | |||
3352 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c, | ||
3353 | "SRR cmd %p (se_cmd %p, tag %d, op %x), " | ||
3354 | "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag, | ||
3355 | se_cmd->t_task_cdb[0], cmd->sg_cnt, cmd->offset); | ||
3356 | |||
3357 | qlt_handle_srr(vha, sctio, imm); | ||
3358 | |||
3359 | kfree(imm); | ||
3360 | kfree(sctio); | ||
3361 | goto restart; | ||
3362 | } | ||
3363 | spin_unlock_irqrestore(&tgt->srr_lock, flags); | ||
3364 | } | ||
3365 | |||
3366 | /* ha->hardware_lock supposed to be held on entry */ | ||
3367 | static void qlt_prepare_srr_imm(struct scsi_qla_host *vha, | ||
3368 | struct imm_ntfy_from_isp *iocb) | ||
3369 | { | ||
3370 | struct qla_tgt_srr_imm *imm; | ||
3371 | struct qla_hw_data *ha = vha->hw; | ||
3372 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
3373 | struct qla_tgt_srr_ctio *sctio; | ||
3374 | |||
3375 | tgt->imm_srr_id++; | ||
3376 | |||
3377 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02d, "qla_target(%d): SRR received\n", | ||
3378 | vha->vp_idx); | ||
3379 | |||
3380 | imm = kzalloc(sizeof(*imm), GFP_ATOMIC); | ||
3381 | if (imm != NULL) { | ||
3382 | memcpy(&imm->imm_ntfy, iocb, sizeof(imm->imm_ntfy)); | ||
3383 | |||
3384 | /* IRQ is already OFF */ | ||
3385 | spin_lock(&tgt->srr_lock); | ||
3386 | imm->srr_id = tgt->imm_srr_id; | ||
3387 | list_add_tail(&imm->srr_list_entry, | ||
3388 | &tgt->srr_imm_list); | ||
3389 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02e, | ||
3390 | "IMM NTFY SRR %p added (id %d, ui %x)\n", | ||
3391 | imm, imm->srr_id, iocb->u.isp24.srr_ui); | ||
3392 | if (tgt->imm_srr_id == tgt->ctio_srr_id) { | ||
3393 | int found = 0; | ||
3394 | list_for_each_entry(sctio, &tgt->srr_ctio_list, | ||
3395 | srr_list_entry) { | ||
3396 | if (sctio->srr_id == imm->srr_id) { | ||
3397 | found = 1; | ||
3398 | break; | ||
3399 | } | ||
3400 | } | ||
3401 | if (found) { | ||
3402 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02f, "%s", | ||
3403 | "Scheduling srr work\n"); | ||
3404 | schedule_work(&tgt->srr_work); | ||
3405 | } else { | ||
3406 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf030, | ||
3407 | "qla_target(%d): imm_srr_id " | ||
3408 | "== ctio_srr_id (%d), but there is no " | ||
3409 | "corresponding SRR CTIO, deleting IMM " | ||
3410 | "SRR %p\n", vha->vp_idx, tgt->ctio_srr_id, | ||
3411 | imm); | ||
3412 | list_del(&imm->srr_list_entry); | ||
3413 | |||
3414 | kfree(imm); | ||
3415 | |||
3416 | spin_unlock(&tgt->srr_lock); | ||
3417 | goto out_reject; | ||
3418 | } | ||
3419 | } | ||
3420 | spin_unlock(&tgt->srr_lock); | ||
3421 | } else { | ||
3422 | struct qla_tgt_srr_ctio *ts; | ||
3423 | |||
3424 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf069, | ||
3425 | "qla_target(%d): Unable to allocate SRR IMM " | ||
3426 | "entry, SRR request will be rejected\n", vha->vp_idx); | ||
3427 | |||
3428 | /* IRQ is already OFF */ | ||
3429 | spin_lock(&tgt->srr_lock); | ||
3430 | list_for_each_entry_safe(sctio, ts, &tgt->srr_ctio_list, | ||
3431 | srr_list_entry) { | ||
3432 | if (sctio->srr_id == tgt->imm_srr_id) { | ||
3433 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf031, | ||
3434 | "CTIO SRR %p deleted (id %d)\n", | ||
3435 | sctio, sctio->srr_id); | ||
3436 | list_del(&sctio->srr_list_entry); | ||
3437 | qlt_send_term_exchange(vha, sctio->cmd, | ||
3438 | &sctio->cmd->atio, 1); | ||
3439 | kfree(sctio); | ||
3440 | } | ||
3441 | } | ||
3442 | spin_unlock(&tgt->srr_lock); | ||
3443 | goto out_reject; | ||
3444 | } | ||
3445 | |||
3446 | return; | ||
3447 | |||
3448 | out_reject: | ||
3449 | qlt_send_notify_ack(vha, iocb, 0, 0, 0, | ||
3450 | NOTIFY_ACK_SRR_FLAGS_REJECT, | ||
3451 | NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, | ||
3452 | NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); | ||
3453 | } | ||
3454 | |||
3455 | /* | ||
3456 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
3457 | */ | ||
3458 | static void qlt_handle_imm_notify(struct scsi_qla_host *vha, | ||
3459 | struct imm_ntfy_from_isp *iocb) | ||
3460 | { | ||
3461 | struct qla_hw_data *ha = vha->hw; | ||
3462 | uint32_t add_flags = 0; | ||
3463 | int send_notify_ack = 1; | ||
3464 | uint16_t status; | ||
3465 | |||
3466 | status = le16_to_cpu(iocb->u.isp2x.status); | ||
3467 | switch (status) { | ||
3468 | case IMM_NTFY_LIP_RESET: | ||
3469 | { | ||
3470 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf032, | ||
3471 | "qla_target(%d): LIP reset (loop %#x), subcode %x\n", | ||
3472 | vha->vp_idx, le16_to_cpu(iocb->u.isp24.nport_handle), | ||
3473 | iocb->u.isp24.status_subcode); | ||
3474 | |||
3475 | if (qlt_reset(vha, iocb, QLA_TGT_ABORT_ALL) == 0) | ||
3476 | send_notify_ack = 0; | ||
3477 | break; | ||
3478 | } | ||
3479 | |||
3480 | case IMM_NTFY_LIP_LINK_REINIT: | ||
3481 | { | ||
3482 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
3483 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033, | ||
3484 | "qla_target(%d): LINK REINIT (loop %#x, " | ||
3485 | "subcode %x)\n", vha->vp_idx, | ||
3486 | le16_to_cpu(iocb->u.isp24.nport_handle), | ||
3487 | iocb->u.isp24.status_subcode); | ||
3488 | if (tgt->link_reinit_iocb_pending) { | ||
3489 | qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, | ||
3490 | 0, 0, 0, 0, 0, 0); | ||
3491 | } | ||
3492 | memcpy(&tgt->link_reinit_iocb, iocb, sizeof(*iocb)); | ||
3493 | tgt->link_reinit_iocb_pending = 1; | ||
3494 | /* | ||
3495 | * QLogic requires to wait after LINK REINIT for possible | ||
3496 | * PDISC or ADISC ELS commands | ||
3497 | */ | ||
3498 | send_notify_ack = 0; | ||
3499 | break; | ||
3500 | } | ||
3501 | |||
3502 | case IMM_NTFY_PORT_LOGOUT: | ||
3503 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf034, | ||
3504 | "qla_target(%d): Port logout (loop " | ||
3505 | "%#x, subcode %x)\n", vha->vp_idx, | ||
3506 | le16_to_cpu(iocb->u.isp24.nport_handle), | ||
3507 | iocb->u.isp24.status_subcode); | ||
3508 | |||
3509 | if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS) == 0) | ||
3510 | send_notify_ack = 0; | ||
3511 | /* The sessions will be cleared in the callback, if needed */ | ||
3512 | break; | ||
3513 | |||
3514 | case IMM_NTFY_GLBL_TPRLO: | ||
3515 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf035, | ||
3516 | "qla_target(%d): Global TPRLO (%x)\n", vha->vp_idx, status); | ||
3517 | if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS) == 0) | ||
3518 | send_notify_ack = 0; | ||
3519 | /* The sessions will be cleared in the callback, if needed */ | ||
3520 | break; | ||
3521 | |||
3522 | case IMM_NTFY_PORT_CONFIG: | ||
3523 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf036, | ||
3524 | "qla_target(%d): Port config changed (%x)\n", vha->vp_idx, | ||
3525 | status); | ||
3526 | if (qlt_reset(vha, iocb, QLA_TGT_ABORT_ALL) == 0) | ||
3527 | send_notify_ack = 0; | ||
3528 | /* The sessions will be cleared in the callback, if needed */ | ||
3529 | break; | ||
3530 | |||
3531 | case IMM_NTFY_GLBL_LOGO: | ||
3532 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06a, | ||
3533 | "qla_target(%d): Link failure detected\n", | ||
3534 | vha->vp_idx); | ||
3535 | /* I_T nexus loss */ | ||
3536 | if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS) == 0) | ||
3537 | send_notify_ack = 0; | ||
3538 | break; | ||
3539 | |||
3540 | case IMM_NTFY_IOCB_OVERFLOW: | ||
3541 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06b, | ||
3542 | "qla_target(%d): Cannot provide requested " | ||
3543 | "capability (IOCB overflowed the immediate notify " | ||
3544 | "resource count)\n", vha->vp_idx); | ||
3545 | break; | ||
3546 | |||
3547 | case IMM_NTFY_ABORT_TASK: | ||
3548 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf037, | ||
3549 | "qla_target(%d): Abort Task (S %08x I %#x -> " | ||
3550 | "L %#x)\n", vha->vp_idx, | ||
3551 | le16_to_cpu(iocb->u.isp2x.seq_id), | ||
3552 | GET_TARGET_ID(ha, (struct atio_from_isp *)iocb), | ||
3553 | le16_to_cpu(iocb->u.isp2x.lun)); | ||
3554 | if (qlt_abort_task(vha, iocb) == 0) | ||
3555 | send_notify_ack = 0; | ||
3556 | break; | ||
3557 | |||
3558 | case IMM_NTFY_RESOURCE: | ||
3559 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06c, | ||
3560 | "qla_target(%d): Out of resources, host %ld\n", | ||
3561 | vha->vp_idx, vha->host_no); | ||
3562 | break; | ||
3563 | |||
3564 | case IMM_NTFY_MSG_RX: | ||
3565 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf038, | ||
3566 | "qla_target(%d): Immediate notify task %x\n", | ||
3567 | vha->vp_idx, iocb->u.isp2x.task_flags); | ||
3568 | if (qlt_handle_task_mgmt(vha, iocb) == 0) | ||
3569 | send_notify_ack = 0; | ||
3570 | break; | ||
3571 | |||
3572 | case IMM_NTFY_ELS: | ||
3573 | if (qlt_24xx_handle_els(vha, iocb) == 0) | ||
3574 | send_notify_ack = 0; | ||
3575 | break; | ||
3576 | |||
3577 | case IMM_NTFY_SRR: | ||
3578 | qlt_prepare_srr_imm(vha, iocb); | ||
3579 | send_notify_ack = 0; | ||
3580 | break; | ||
3581 | |||
3582 | default: | ||
3583 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06d, | ||
3584 | "qla_target(%d): Received unknown immediate " | ||
3585 | "notify status %x\n", vha->vp_idx, status); | ||
3586 | break; | ||
3587 | } | ||
3588 | |||
3589 | if (send_notify_ack) | ||
3590 | qlt_send_notify_ack(vha, iocb, add_flags, 0, 0, 0, 0, 0); | ||
3591 | } | ||
3592 | |||
3593 | /* | ||
3594 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
3595 | * This function sends busy to ISP 2xxx or 24xx. | ||
3596 | */ | ||
3597 | static void qlt_send_busy(struct scsi_qla_host *vha, | ||
3598 | struct atio_from_isp *atio, uint16_t status) | ||
3599 | { | ||
3600 | struct ctio7_to_24xx *ctio24; | ||
3601 | struct qla_hw_data *ha = vha->hw; | ||
3602 | request_t *pkt; | ||
3603 | struct qla_tgt_sess *sess = NULL; | ||
3604 | |||
3605 | sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, | ||
3606 | atio->u.isp24.fcp_hdr.s_id); | ||
3607 | if (!sess) { | ||
3608 | qlt_send_term_exchange(vha, NULL, atio, 1); | ||
3609 | return; | ||
3610 | } | ||
3611 | /* Sending marker isn't necessary, since we called from ISR */ | ||
3612 | |||
3613 | pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); | ||
3614 | if (!pkt) { | ||
3615 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06e, | ||
3616 | "qla_target(%d): %s failed: unable to allocate " | ||
3617 | "request packet", vha->vp_idx, __func__); | ||
3618 | return; | ||
3619 | } | ||
3620 | |||
3621 | pkt->entry_count = 1; | ||
3622 | pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; | ||
3623 | |||
3624 | ctio24 = (struct ctio7_to_24xx *)pkt; | ||
3625 | ctio24->entry_type = CTIO_TYPE7; | ||
3626 | ctio24->nport_handle = sess->loop_id; | ||
3627 | ctio24->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); | ||
3628 | ctio24->vp_index = vha->vp_idx; | ||
3629 | ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; | ||
3630 | ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; | ||
3631 | ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; | ||
3632 | ctio24->exchange_addr = atio->u.isp24.exchange_addr; | ||
3633 | ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | | ||
3634 | __constant_cpu_to_le16( | ||
3635 | CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS | | ||
3636 | CTIO7_FLAGS_DONT_RET_CTIO); | ||
3637 | /* | ||
3638 | * CTIO from fw w/o se_cmd doesn't provide enough info to retry it, | ||
3639 | * if the explicit conformation is used. | ||
3640 | */ | ||
3641 | ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); | ||
3642 | ctio24->u.status1.scsi_status = cpu_to_le16(status); | ||
3643 | ctio24->u.status1.residual = get_unaligned((uint32_t *) | ||
3644 | &atio->u.isp24.fcp_cmnd.add_cdb[ | ||
3645 | atio->u.isp24.fcp_cmnd.add_cdb_len]); | ||
3646 | if (ctio24->u.status1.residual != 0) | ||
3647 | ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER; | ||
3648 | |||
3649 | qla2x00_start_iocbs(vha, vha->req); | ||
3650 | } | ||
3651 | |||
3652 | /* ha->hardware_lock supposed to be held on entry */ | ||
3653 | /* called via callback from qla2xxx */ | ||
3654 | static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | ||
3655 | struct atio_from_isp *atio) | ||
3656 | { | ||
3657 | struct qla_hw_data *ha = vha->hw; | ||
3658 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
3659 | int rc; | ||
3660 | |||
3661 | if (unlikely(tgt == NULL)) { | ||
3662 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf039, | ||
3663 | "ATIO pkt, but no tgt (ha %p)", ha); | ||
3664 | return; | ||
3665 | } | ||
3666 | ql_dbg(ql_dbg_tgt, vha, 0xe02c, | ||
3667 | "qla_target(%d): ATIO pkt %p: type %02x count %02x", | ||
3668 | vha->vp_idx, atio, atio->u.raw.entry_type, | ||
3669 | atio->u.raw.entry_count); | ||
3670 | /* | ||
3671 | * In tgt_stop mode we also should allow all requests to pass. | ||
3672 | * Otherwise, some commands can stuck. | ||
3673 | */ | ||
3674 | |||
3675 | tgt->irq_cmd_count++; | ||
3676 | |||
3677 | switch (atio->u.raw.entry_type) { | ||
3678 | case ATIO_TYPE7: | ||
3679 | ql_dbg(ql_dbg_tgt, vha, 0xe02d, | ||
3680 | "ATIO_TYPE7 instance %d, lun %Lx, read/write %d/%d, " | ||
3681 | "add_cdb_len %d, data_length %04x, s_id %x:%x:%x\n", | ||
3682 | vha->vp_idx, atio->u.isp24.fcp_cmnd.lun, | ||
3683 | atio->u.isp24.fcp_cmnd.rddata, | ||
3684 | atio->u.isp24.fcp_cmnd.wrdata, | ||
3685 | atio->u.isp24.fcp_cmnd.add_cdb_len, | ||
3686 | be32_to_cpu(get_unaligned((uint32_t *) | ||
3687 | &atio->u.isp24.fcp_cmnd.add_cdb[ | ||
3688 | atio->u.isp24.fcp_cmnd.add_cdb_len])), | ||
3689 | atio->u.isp24.fcp_hdr.s_id[0], | ||
3690 | atio->u.isp24.fcp_hdr.s_id[1], | ||
3691 | atio->u.isp24.fcp_hdr.s_id[2]); | ||
3692 | |||
3693 | if (unlikely(atio->u.isp24.exchange_addr == | ||
3694 | ATIO_EXCHANGE_ADDRESS_UNKNOWN)) { | ||
3695 | ql_dbg(ql_dbg_tgt, vha, 0xe058, | ||
3696 | "qla_target(%d): ATIO_TYPE7 " | ||
3697 | "received with UNKNOWN exchange address, " | ||
3698 | "sending QUEUE_FULL\n", vha->vp_idx); | ||
3699 | qlt_send_busy(vha, atio, SAM_STAT_TASK_SET_FULL); | ||
3700 | break; | ||
3701 | } | ||
3702 | if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) | ||
3703 | rc = qlt_handle_cmd_for_atio(vha, atio); | ||
3704 | else | ||
3705 | rc = qlt_handle_task_mgmt(vha, atio); | ||
3706 | if (unlikely(rc != 0)) { | ||
3707 | if (rc == -ESRCH) { | ||
3708 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ | ||
3709 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); | ||
3710 | #else | ||
3711 | qlt_send_term_exchange(vha, NULL, atio, 1); | ||
3712 | #endif | ||
3713 | } else { | ||
3714 | if (tgt->tgt_stop) { | ||
3715 | ql_dbg(ql_dbg_tgt, vha, 0xe059, | ||
3716 | "qla_target: Unable to send " | ||
3717 | "command to target for req, " | ||
3718 | "ignoring.\n"); | ||
3719 | } else { | ||
3720 | ql_dbg(ql_dbg_tgt, vha, 0xe05a, | ||
3721 | "qla_target(%d): Unable to send " | ||
3722 | "command to target, sending BUSY " | ||
3723 | "status.\n", vha->vp_idx); | ||
3724 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); | ||
3725 | } | ||
3726 | } | ||
3727 | } | ||
3728 | break; | ||
3729 | |||
3730 | case IMMED_NOTIFY_TYPE: | ||
3731 | { | ||
3732 | if (unlikely(atio->u.isp2x.entry_status != 0)) { | ||
3733 | ql_dbg(ql_dbg_tgt, vha, 0xe05b, | ||
3734 | "qla_target(%d): Received ATIO packet %x " | ||
3735 | "with error status %x\n", vha->vp_idx, | ||
3736 | atio->u.raw.entry_type, | ||
3737 | atio->u.isp2x.entry_status); | ||
3738 | break; | ||
3739 | } | ||
3740 | ql_dbg(ql_dbg_tgt, vha, 0xe02e, "%s", "IMMED_NOTIFY ATIO"); | ||
3741 | qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)atio); | ||
3742 | break; | ||
3743 | } | ||
3744 | |||
3745 | default: | ||
3746 | ql_dbg(ql_dbg_tgt, vha, 0xe05c, | ||
3747 | "qla_target(%d): Received unknown ATIO atio " | ||
3748 | "type %x\n", vha->vp_idx, atio->u.raw.entry_type); | ||
3749 | break; | ||
3750 | } | ||
3751 | |||
3752 | tgt->irq_cmd_count--; | ||
3753 | } | ||
3754 | |||
3755 | /* ha->hardware_lock supposed to be held on entry */ | ||
3756 | /* called via callback from qla2xxx */ | ||
3757 | static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) | ||
3758 | { | ||
3759 | struct qla_hw_data *ha = vha->hw; | ||
3760 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
3761 | |||
3762 | if (unlikely(tgt == NULL)) { | ||
3763 | ql_dbg(ql_dbg_tgt, vha, 0xe05d, | ||
3764 | "qla_target(%d): Response pkt %x received, but no " | ||
3765 | "tgt (ha %p)\n", vha->vp_idx, pkt->entry_type, ha); | ||
3766 | return; | ||
3767 | } | ||
3768 | |||
3769 | ql_dbg(ql_dbg_tgt, vha, 0xe02f, | ||
3770 | "qla_target(%d): response pkt %p: T %02x C %02x S %02x " | ||
3771 | "handle %#x\n", vha->vp_idx, pkt, pkt->entry_type, | ||
3772 | pkt->entry_count, pkt->entry_status, pkt->handle); | ||
3773 | |||
3774 | /* | ||
3775 | * In tgt_stop mode we also should allow all requests to pass. | ||
3776 | * Otherwise, some commands can stuck. | ||
3777 | */ | ||
3778 | |||
3779 | tgt->irq_cmd_count++; | ||
3780 | |||
3781 | switch (pkt->entry_type) { | ||
3782 | case CTIO_TYPE7: | ||
3783 | { | ||
3784 | struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; | ||
3785 | ql_dbg(ql_dbg_tgt, vha, 0xe030, "CTIO_TYPE7: instance %d\n", | ||
3786 | vha->vp_idx); | ||
3787 | qlt_do_ctio_completion(vha, entry->handle, | ||
3788 | le16_to_cpu(entry->status)|(pkt->entry_status << 16), | ||
3789 | entry); | ||
3790 | break; | ||
3791 | } | ||
3792 | |||
3793 | case ACCEPT_TGT_IO_TYPE: | ||
3794 | { | ||
3795 | struct atio_from_isp *atio = (struct atio_from_isp *)pkt; | ||
3796 | int rc; | ||
3797 | ql_dbg(ql_dbg_tgt, vha, 0xe031, | ||
3798 | "ACCEPT_TGT_IO instance %d status %04x " | ||
3799 | "lun %04x read/write %d data_length %04x " | ||
3800 | "target_id %02x rx_id %04x\n ", vha->vp_idx, | ||
3801 | le16_to_cpu(atio->u.isp2x.status), | ||
3802 | le16_to_cpu(atio->u.isp2x.lun), | ||
3803 | atio->u.isp2x.execution_codes, | ||
3804 | le32_to_cpu(atio->u.isp2x.data_length), GET_TARGET_ID(ha, | ||
3805 | atio), atio->u.isp2x.rx_id); | ||
3806 | if (atio->u.isp2x.status != | ||
3807 | __constant_cpu_to_le16(ATIO_CDB_VALID)) { | ||
3808 | ql_dbg(ql_dbg_tgt, vha, 0xe05e, | ||
3809 | "qla_target(%d): ATIO with error " | ||
3810 | "status %x received\n", vha->vp_idx, | ||
3811 | le16_to_cpu(atio->u.isp2x.status)); | ||
3812 | break; | ||
3813 | } | ||
3814 | ql_dbg(ql_dbg_tgt, vha, 0xe032, | ||
3815 | "FCP CDB: 0x%02x, sizeof(cdb): %lu", | ||
3816 | atio->u.isp2x.cdb[0], (unsigned long | ||
3817 | int)sizeof(atio->u.isp2x.cdb)); | ||
3818 | |||
3819 | rc = qlt_handle_cmd_for_atio(vha, atio); | ||
3820 | if (unlikely(rc != 0)) { | ||
3821 | if (rc == -ESRCH) { | ||
3822 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ | ||
3823 | qlt_send_busy(vha, atio, 0); | ||
3824 | #else | ||
3825 | qlt_send_term_exchange(vha, NULL, atio, 1); | ||
3826 | #endif | ||
3827 | } else { | ||
3828 | if (tgt->tgt_stop) { | ||
3829 | ql_dbg(ql_dbg_tgt, vha, 0xe05f, | ||
3830 | "qla_target: Unable to send " | ||
3831 | "command to target, sending TERM " | ||
3832 | "EXCHANGE for rsp\n"); | ||
3833 | qlt_send_term_exchange(vha, NULL, | ||
3834 | atio, 1); | ||
3835 | } else { | ||
3836 | ql_dbg(ql_dbg_tgt, vha, 0xe060, | ||
3837 | "qla_target(%d): Unable to send " | ||
3838 | "command to target, sending BUSY " | ||
3839 | "status\n", vha->vp_idx); | ||
3840 | qlt_send_busy(vha, atio, 0); | ||
3841 | } | ||
3842 | } | ||
3843 | } | ||
3844 | } | ||
3845 | break; | ||
3846 | |||
3847 | case CONTINUE_TGT_IO_TYPE: | ||
3848 | { | ||
3849 | struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; | ||
3850 | ql_dbg(ql_dbg_tgt, vha, 0xe033, | ||
3851 | "CONTINUE_TGT_IO: instance %d\n", vha->vp_idx); | ||
3852 | qlt_do_ctio_completion(vha, entry->handle, | ||
3853 | le16_to_cpu(entry->status)|(pkt->entry_status << 16), | ||
3854 | entry); | ||
3855 | break; | ||
3856 | } | ||
3857 | |||
3858 | case CTIO_A64_TYPE: | ||
3859 | { | ||
3860 | struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; | ||
3861 | ql_dbg(ql_dbg_tgt, vha, 0xe034, "CTIO_A64: instance %d\n", | ||
3862 | vha->vp_idx); | ||
3863 | qlt_do_ctio_completion(vha, entry->handle, | ||
3864 | le16_to_cpu(entry->status)|(pkt->entry_status << 16), | ||
3865 | entry); | ||
3866 | break; | ||
3867 | } | ||
3868 | |||
3869 | case IMMED_NOTIFY_TYPE: | ||
3870 | ql_dbg(ql_dbg_tgt, vha, 0xe035, "%s", "IMMED_NOTIFY\n"); | ||
3871 | qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)pkt); | ||
3872 | break; | ||
3873 | |||
3874 | case NOTIFY_ACK_TYPE: | ||
3875 | if (tgt->notify_ack_expected > 0) { | ||
3876 | struct nack_to_isp *entry = (struct nack_to_isp *)pkt; | ||
3877 | ql_dbg(ql_dbg_tgt, vha, 0xe036, | ||
3878 | "NOTIFY_ACK seq %08x status %x\n", | ||
3879 | le16_to_cpu(entry->u.isp2x.seq_id), | ||
3880 | le16_to_cpu(entry->u.isp2x.status)); | ||
3881 | tgt->notify_ack_expected--; | ||
3882 | if (entry->u.isp2x.status != | ||
3883 | __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) { | ||
3884 | ql_dbg(ql_dbg_tgt, vha, 0xe061, | ||
3885 | "qla_target(%d): NOTIFY_ACK " | ||
3886 | "failed %x\n", vha->vp_idx, | ||
3887 | le16_to_cpu(entry->u.isp2x.status)); | ||
3888 | } | ||
3889 | } else { | ||
3890 | ql_dbg(ql_dbg_tgt, vha, 0xe062, | ||
3891 | "qla_target(%d): Unexpected NOTIFY_ACK received\n", | ||
3892 | vha->vp_idx); | ||
3893 | } | ||
3894 | break; | ||
3895 | |||
3896 | case ABTS_RECV_24XX: | ||
3897 | ql_dbg(ql_dbg_tgt, vha, 0xe037, | ||
3898 | "ABTS_RECV_24XX: instance %d\n", vha->vp_idx); | ||
3899 | qlt_24xx_handle_abts(vha, (struct abts_recv_from_24xx *)pkt); | ||
3900 | break; | ||
3901 | |||
3902 | case ABTS_RESP_24XX: | ||
3903 | if (tgt->abts_resp_expected > 0) { | ||
3904 | struct abts_resp_from_24xx_fw *entry = | ||
3905 | (struct abts_resp_from_24xx_fw *)pkt; | ||
3906 | ql_dbg(ql_dbg_tgt, vha, 0xe038, | ||
3907 | "ABTS_RESP_24XX: compl_status %x\n", | ||
3908 | entry->compl_status); | ||
3909 | tgt->abts_resp_expected--; | ||
3910 | if (le16_to_cpu(entry->compl_status) != | ||
3911 | ABTS_RESP_COMPL_SUCCESS) { | ||
3912 | if ((entry->error_subcode1 == 0x1E) && | ||
3913 | (entry->error_subcode2 == 0)) { | ||
3914 | /* | ||
3915 | * We've got a race here: aborted | ||
3916 | * exchange not terminated, i.e. | ||
3917 | * response for the aborted command was | ||
3918 | * sent between the abort request was | ||
3919 | * received and processed. | ||
3920 | * Unfortunately, the firmware has a | ||
3921 | * silly requirement that all aborted | ||
3922 | * exchanges must be explicitely | ||
3923 | * terminated, otherwise it refuses to | ||
3924 | * send responses for the abort | ||
3925 | * requests. So, we have to | ||
3926 | * (re)terminate the exchange and retry | ||
3927 | * the abort response. | ||
3928 | */ | ||
3929 | qlt_24xx_retry_term_exchange(vha, | ||
3930 | entry); | ||
3931 | } else | ||
3932 | ql_dbg(ql_dbg_tgt, vha, 0xe063, | ||
3933 | "qla_target(%d): ABTS_RESP_24XX " | ||
3934 | "failed %x (subcode %x:%x)", | ||
3935 | vha->vp_idx, entry->compl_status, | ||
3936 | entry->error_subcode1, | ||
3937 | entry->error_subcode2); | ||
3938 | } | ||
3939 | } else { | ||
3940 | ql_dbg(ql_dbg_tgt, vha, 0xe064, | ||
3941 | "qla_target(%d): Unexpected ABTS_RESP_24XX " | ||
3942 | "received\n", vha->vp_idx); | ||
3943 | } | ||
3944 | break; | ||
3945 | |||
3946 | default: | ||
3947 | ql_dbg(ql_dbg_tgt, vha, 0xe065, | ||
3948 | "qla_target(%d): Received unknown response pkt " | ||
3949 | "type %x\n", vha->vp_idx, pkt->entry_type); | ||
3950 | break; | ||
3951 | } | ||
3952 | |||
3953 | tgt->irq_cmd_count--; | ||
3954 | } | ||
3955 | |||
3956 | /* | ||
3957 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | ||
3958 | */ | ||
3959 | void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, | ||
3960 | uint16_t *mailbox) | ||
3961 | { | ||
3962 | struct qla_hw_data *ha = vha->hw; | ||
3963 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
3964 | int reason_code; | ||
3965 | |||
3966 | ql_dbg(ql_dbg_tgt, vha, 0xe039, | ||
3967 | "scsi(%ld): ha state %d init_done %d oper_mode %d topo %d\n", | ||
3968 | vha->host_no, atomic_read(&vha->loop_state), vha->flags.init_done, | ||
3969 | ha->operating_mode, ha->current_topology); | ||
3970 | |||
3971 | if (!ha->tgt.tgt_ops) | ||
3972 | return; | ||
3973 | |||
3974 | if (unlikely(tgt == NULL)) { | ||
3975 | ql_dbg(ql_dbg_tgt, vha, 0xe03a, | ||
3976 | "ASYNC EVENT %#x, but no tgt (ha %p)\n", code, ha); | ||
3977 | return; | ||
3978 | } | ||
3979 | |||
3980 | if (((code == MBA_POINT_TO_POINT) || (code == MBA_CHG_IN_CONNECTION)) && | ||
3981 | IS_QLA2100(ha)) | ||
3982 | return; | ||
3983 | /* | ||
3984 | * In tgt_stop mode we also should allow all requests to pass. | ||
3985 | * Otherwise, some commands can stuck. | ||
3986 | */ | ||
3987 | |||
3988 | tgt->irq_cmd_count++; | ||
3989 | |||
3990 | switch (code) { | ||
3991 | case MBA_RESET: /* Reset */ | ||
3992 | case MBA_SYSTEM_ERR: /* System Error */ | ||
3993 | case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ | ||
3994 | case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ | ||
3995 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03a, | ||
3996 | "qla_target(%d): System error async event %#x " | ||
3997 | "occured", vha->vp_idx, code); | ||
3998 | break; | ||
3999 | case MBA_WAKEUP_THRES: /* Request Queue Wake-up. */ | ||
4000 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
4001 | break; | ||
4002 | |||
4003 | case MBA_LOOP_UP: | ||
4004 | { | ||
4005 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b, | ||
4006 | "qla_target(%d): Async LOOP_UP occured " | ||
4007 | "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", vha->vp_idx, | ||
4008 | le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), | ||
4009 | le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); | ||
4010 | if (tgt->link_reinit_iocb_pending) { | ||
4011 | qlt_send_notify_ack(vha, (void *)&tgt->link_reinit_iocb, | ||
4012 | 0, 0, 0, 0, 0, 0); | ||
4013 | tgt->link_reinit_iocb_pending = 0; | ||
4014 | } | ||
4015 | break; | ||
4016 | } | ||
4017 | |||
4018 | case MBA_LIP_OCCURRED: | ||
4019 | case MBA_LOOP_DOWN: | ||
4020 | case MBA_LIP_RESET: | ||
4021 | case MBA_RSCN_UPDATE: | ||
4022 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c, | ||
4023 | "qla_target(%d): Async event %#x occured " | ||
4024 | "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", vha->vp_idx, code, | ||
4025 | le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), | ||
4026 | le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); | ||
4027 | break; | ||
4028 | |||
4029 | case MBA_PORT_UPDATE: | ||
4030 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d, | ||
4031 | "qla_target(%d): Port update async event %#x " | ||
4032 | "occured: updating the ports database (m[1]=%x, m[2]=%x, " | ||
4033 | "m[3]=%x, m[4]=%x)", vha->vp_idx, code, | ||
4034 | le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), | ||
4035 | le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); | ||
4036 | reason_code = le16_to_cpu(mailbox[2]); | ||
4037 | if (reason_code == 0x4) | ||
4038 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03e, | ||
4039 | "Async MB 2: Got PLOGI Complete\n"); | ||
4040 | else if (reason_code == 0x7) | ||
4041 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03f, | ||
4042 | "Async MB 2: Port Logged Out\n"); | ||
4043 | break; | ||
4044 | |||
4045 | default: | ||
4046 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf040, | ||
4047 | "qla_target(%d): Async event %#x occured: " | ||
4048 | "ignore (m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", vha->vp_idx, | ||
4049 | code, le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), | ||
4050 | le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); | ||
4051 | break; | ||
4052 | } | ||
4053 | |||
4054 | tgt->irq_cmd_count--; | ||
4055 | } | ||
4056 | |||
4057 | static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, | ||
4058 | uint16_t loop_id) | ||
4059 | { | ||
4060 | fc_port_t *fcport; | ||
4061 | int rc; | ||
4062 | |||
4063 | fcport = kzalloc(sizeof(*fcport), GFP_KERNEL); | ||
4064 | if (!fcport) { | ||
4065 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06f, | ||
4066 | "qla_target(%d): Allocation of tmp FC port failed", | ||
4067 | vha->vp_idx); | ||
4068 | return NULL; | ||
4069 | } | ||
4070 | |||
4071 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf041, "loop_id %d", loop_id); | ||
4072 | |||
4073 | fcport->loop_id = loop_id; | ||
4074 | |||
4075 | rc = qla2x00_get_port_database(vha, fcport, 0); | ||
4076 | if (rc != QLA_SUCCESS) { | ||
4077 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf070, | ||
4078 | "qla_target(%d): Failed to retrieve fcport " | ||
4079 | "information -- get_port_database() returned %x " | ||
4080 | "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id); | ||
4081 | kfree(fcport); | ||
4082 | return NULL; | ||
4083 | } | ||
4084 | |||
4085 | return fcport; | ||
4086 | } | ||
4087 | |||
4088 | /* Must be called under tgt_mutex */ | ||
4089 | static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *vha, | ||
4090 | uint8_t *s_id) | ||
4091 | { | ||
4092 | struct qla_hw_data *ha = vha->hw; | ||
4093 | struct qla_tgt_sess *sess = NULL; | ||
4094 | fc_port_t *fcport = NULL; | ||
4095 | int rc, global_resets; | ||
4096 | uint16_t loop_id = 0; | ||
4097 | |||
4098 | retry: | ||
4099 | global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); | ||
4100 | |||
4101 | rc = qla24xx_get_loop_id(vha, s_id, &loop_id); | ||
4102 | if (rc != 0) { | ||
4103 | if ((s_id[0] == 0xFF) && | ||
4104 | (s_id[1] == 0xFC)) { | ||
4105 | /* | ||
4106 | * This is Domain Controller, so it should be | ||
4107 | * OK to drop SCSI commands from it. | ||
4108 | */ | ||
4109 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042, | ||
4110 | "Unable to find initiator with S_ID %x:%x:%x", | ||
4111 | s_id[0], s_id[1], s_id[2]); | ||
4112 | } else | ||
4113 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf071, | ||
4114 | "qla_target(%d): Unable to find " | ||
4115 | "initiator with S_ID %x:%x:%x", | ||
4116 | vha->vp_idx, s_id[0], s_id[1], | ||
4117 | s_id[2]); | ||
4118 | return NULL; | ||
4119 | } | ||
4120 | |||
4121 | fcport = qlt_get_port_database(vha, loop_id); | ||
4122 | if (!fcport) | ||
4123 | return NULL; | ||
4124 | |||
4125 | if (global_resets != | ||
4126 | atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) { | ||
4127 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf043, | ||
4128 | "qla_target(%d): global reset during session discovery " | ||
4129 | "(counter was %d, new %d), retrying", vha->vp_idx, | ||
4130 | global_resets, | ||
4131 | atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)); | ||
4132 | goto retry; | ||
4133 | } | ||
4134 | |||
4135 | sess = qlt_create_sess(vha, fcport, true); | ||
4136 | |||
4137 | kfree(fcport); | ||
4138 | return sess; | ||
4139 | } | ||
4140 | |||
4141 | static void qlt_abort_work(struct qla_tgt *tgt, | ||
4142 | struct qla_tgt_sess_work_param *prm) | ||
4143 | { | ||
4144 | struct scsi_qla_host *vha = tgt->vha; | ||
4145 | struct qla_hw_data *ha = vha->hw; | ||
4146 | struct qla_tgt_sess *sess = NULL; | ||
4147 | unsigned long flags; | ||
4148 | uint32_t be_s_id; | ||
4149 | uint8_t s_id[3]; | ||
4150 | int rc; | ||
4151 | |||
4152 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4153 | |||
4154 | if (tgt->tgt_stop) | ||
4155 | goto out_term; | ||
4156 | |||
4157 | s_id[0] = prm->abts.fcp_hdr_le.s_id[2]; | ||
4158 | s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; | ||
4159 | s_id[2] = prm->abts.fcp_hdr_le.s_id[0]; | ||
4160 | |||
4161 | sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, | ||
4162 | (unsigned char *)&be_s_id); | ||
4163 | if (!sess) { | ||
4164 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4165 | |||
4166 | mutex_lock(&ha->tgt.tgt_mutex); | ||
4167 | sess = qlt_make_local_sess(vha, s_id); | ||
4168 | /* sess has got an extra creation ref */ | ||
4169 | mutex_unlock(&ha->tgt.tgt_mutex); | ||
4170 | |||
4171 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4172 | if (!sess) | ||
4173 | goto out_term; | ||
4174 | } else { | ||
4175 | kref_get(&sess->se_sess->sess_kref); | ||
4176 | } | ||
4177 | |||
4178 | if (tgt->tgt_stop) | ||
4179 | goto out_term; | ||
4180 | |||
4181 | rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); | ||
4182 | if (rc != 0) | ||
4183 | goto out_term; | ||
4184 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4185 | |||
4186 | ha->tgt.tgt_ops->put_sess(sess); | ||
4187 | return; | ||
4188 | |||
4189 | out_term: | ||
4190 | qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false); | ||
4191 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4192 | if (sess) | ||
4193 | ha->tgt.tgt_ops->put_sess(sess); | ||
4194 | } | ||
4195 | |||
4196 | static void qlt_tmr_work(struct qla_tgt *tgt, | ||
4197 | struct qla_tgt_sess_work_param *prm) | ||
4198 | { | ||
4199 | struct atio_from_isp *a = &prm->tm_iocb2; | ||
4200 | struct scsi_qla_host *vha = tgt->vha; | ||
4201 | struct qla_hw_data *ha = vha->hw; | ||
4202 | struct qla_tgt_sess *sess = NULL; | ||
4203 | unsigned long flags; | ||
4204 | uint8_t *s_id = NULL; /* to hide compiler warnings */ | ||
4205 | int rc; | ||
4206 | uint32_t lun, unpacked_lun; | ||
4207 | int lun_size, fn; | ||
4208 | void *iocb; | ||
4209 | |||
4210 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4211 | |||
4212 | if (tgt->tgt_stop) | ||
4213 | goto out_term; | ||
4214 | |||
4215 | s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id; | ||
4216 | sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); | ||
4217 | if (!sess) { | ||
4218 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4219 | |||
4220 | mutex_lock(&ha->tgt.tgt_mutex); | ||
4221 | sess = qlt_make_local_sess(vha, s_id); | ||
4222 | /* sess has got an extra creation ref */ | ||
4223 | mutex_unlock(&ha->tgt.tgt_mutex); | ||
4224 | |||
4225 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4226 | if (!sess) | ||
4227 | goto out_term; | ||
4228 | } else { | ||
4229 | kref_get(&sess->se_sess->sess_kref); | ||
4230 | } | ||
4231 | |||
4232 | iocb = a; | ||
4233 | lun = a->u.isp24.fcp_cmnd.lun; | ||
4234 | lun_size = sizeof(lun); | ||
4235 | fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; | ||
4236 | unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); | ||
4237 | |||
4238 | rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); | ||
4239 | if (rc != 0) | ||
4240 | goto out_term; | ||
4241 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4242 | |||
4243 | ha->tgt.tgt_ops->put_sess(sess); | ||
4244 | return; | ||
4245 | |||
4246 | out_term: | ||
4247 | qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1); | ||
4248 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4249 | if (sess) | ||
4250 | ha->tgt.tgt_ops->put_sess(sess); | ||
4251 | } | ||
4252 | |||
4253 | static void qlt_sess_work_fn(struct work_struct *work) | ||
4254 | { | ||
4255 | struct qla_tgt *tgt = container_of(work, struct qla_tgt, sess_work); | ||
4256 | struct scsi_qla_host *vha = tgt->vha; | ||
4257 | unsigned long flags; | ||
4258 | |||
4259 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf000, "Sess work (tgt %p)", tgt); | ||
4260 | |||
4261 | spin_lock_irqsave(&tgt->sess_work_lock, flags); | ||
4262 | while (!list_empty(&tgt->sess_works_list)) { | ||
4263 | struct qla_tgt_sess_work_param *prm = list_entry( | ||
4264 | tgt->sess_works_list.next, typeof(*prm), | ||
4265 | sess_works_list_entry); | ||
4266 | |||
4267 | /* | ||
4268 | * This work can be scheduled on several CPUs at time, so we | ||
4269 | * must delete the entry to eliminate double processing | ||
4270 | */ | ||
4271 | list_del(&prm->sess_works_list_entry); | ||
4272 | |||
4273 | spin_unlock_irqrestore(&tgt->sess_work_lock, flags); | ||
4274 | |||
4275 | switch (prm->type) { | ||
4276 | case QLA_TGT_SESS_WORK_ABORT: | ||
4277 | qlt_abort_work(tgt, prm); | ||
4278 | break; | ||
4279 | case QLA_TGT_SESS_WORK_TM: | ||
4280 | qlt_tmr_work(tgt, prm); | ||
4281 | break; | ||
4282 | default: | ||
4283 | BUG_ON(1); | ||
4284 | break; | ||
4285 | } | ||
4286 | |||
4287 | spin_lock_irqsave(&tgt->sess_work_lock, flags); | ||
4288 | |||
4289 | kfree(prm); | ||
4290 | } | ||
4291 | spin_unlock_irqrestore(&tgt->sess_work_lock, flags); | ||
4292 | } | ||
4293 | |||
4294 | /* Must be called under tgt_host_action_mutex */ | ||
4295 | int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) | ||
4296 | { | ||
4297 | struct qla_tgt *tgt; | ||
4298 | |||
4299 | if (!QLA_TGT_MODE_ENABLED()) | ||
4300 | return 0; | ||
4301 | |||
4302 | ql_dbg(ql_dbg_tgt, base_vha, 0xe03b, | ||
4303 | "Registering target for host %ld(%p)", base_vha->host_no, ha); | ||
4304 | |||
4305 | BUG_ON((ha->tgt.qla_tgt != NULL) || (ha->tgt.tgt_ops != NULL)); | ||
4306 | |||
4307 | tgt = kzalloc(sizeof(struct qla_tgt), GFP_KERNEL); | ||
4308 | if (!tgt) { | ||
4309 | ql_dbg(ql_dbg_tgt, base_vha, 0xe066, | ||
4310 | "Unable to allocate struct qla_tgt\n"); | ||
4311 | return -ENOMEM; | ||
4312 | } | ||
4313 | |||
4314 | if (!(base_vha->host->hostt->supported_mode & MODE_TARGET)) | ||
4315 | base_vha->host->hostt->supported_mode |= MODE_TARGET; | ||
4316 | |||
4317 | tgt->ha = ha; | ||
4318 | tgt->vha = base_vha; | ||
4319 | init_waitqueue_head(&tgt->waitQ); | ||
4320 | INIT_LIST_HEAD(&tgt->sess_list); | ||
4321 | INIT_LIST_HEAD(&tgt->del_sess_list); | ||
4322 | INIT_DELAYED_WORK(&tgt->sess_del_work, | ||
4323 | (void (*)(struct work_struct *))qlt_del_sess_work_fn); | ||
4324 | spin_lock_init(&tgt->sess_work_lock); | ||
4325 | INIT_WORK(&tgt->sess_work, qlt_sess_work_fn); | ||
4326 | INIT_LIST_HEAD(&tgt->sess_works_list); | ||
4327 | spin_lock_init(&tgt->srr_lock); | ||
4328 | INIT_LIST_HEAD(&tgt->srr_ctio_list); | ||
4329 | INIT_LIST_HEAD(&tgt->srr_imm_list); | ||
4330 | INIT_WORK(&tgt->srr_work, qlt_handle_srr_work); | ||
4331 | atomic_set(&tgt->tgt_global_resets_count, 0); | ||
4332 | |||
4333 | ha->tgt.qla_tgt = tgt; | ||
4334 | |||
4335 | ql_dbg(ql_dbg_tgt, base_vha, 0xe067, | ||
4336 | "qla_target(%d): using 64 Bit PCI addressing", | ||
4337 | base_vha->vp_idx); | ||
4338 | tgt->tgt_enable_64bit_addr = 1; | ||
4339 | /* 3 is reserved */ | ||
4340 | tgt->sg_tablesize = QLA_TGT_MAX_SG_24XX(base_vha->req->length - 3); | ||
4341 | tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX; | ||
4342 | tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX; | ||
4343 | |||
4344 | mutex_lock(&qla_tgt_mutex); | ||
4345 | list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist); | ||
4346 | mutex_unlock(&qla_tgt_mutex); | ||
4347 | |||
4348 | return 0; | ||
4349 | } | ||
4350 | |||
4351 | /* Must be called under tgt_host_action_mutex */ | ||
4352 | int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) | ||
4353 | { | ||
4354 | if (!ha->tgt.qla_tgt) | ||
4355 | return 0; | ||
4356 | |||
4357 | mutex_lock(&qla_tgt_mutex); | ||
4358 | list_del(&ha->tgt.qla_tgt->tgt_list_entry); | ||
4359 | mutex_unlock(&qla_tgt_mutex); | ||
4360 | |||
4361 | ql_dbg(ql_dbg_tgt, vha, 0xe03c, "Unregistering target for host %ld(%p)", | ||
4362 | vha->host_no, ha); | ||
4363 | qlt_release(ha->tgt.qla_tgt); | ||
4364 | |||
4365 | return 0; | ||
4366 | } | ||
4367 | |||
4368 | static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, | ||
4369 | unsigned char *b) | ||
4370 | { | ||
4371 | int i; | ||
4372 | |||
4373 | pr_debug("qla2xxx HW vha->node_name: "); | ||
4374 | for (i = 0; i < WWN_SIZE; i++) | ||
4375 | pr_debug("%02x ", vha->node_name[i]); | ||
4376 | pr_debug("\n"); | ||
4377 | pr_debug("qla2xxx HW vha->port_name: "); | ||
4378 | for (i = 0; i < WWN_SIZE; i++) | ||
4379 | pr_debug("%02x ", vha->port_name[i]); | ||
4380 | pr_debug("\n"); | ||
4381 | |||
4382 | pr_debug("qla2xxx passed configfs WWPN: "); | ||
4383 | put_unaligned_be64(wwpn, b); | ||
4384 | for (i = 0; i < WWN_SIZE; i++) | ||
4385 | pr_debug("%02x ", b[i]); | ||
4386 | pr_debug("\n"); | ||
4387 | } | ||
4388 | |||
4389 | /** | ||
4390 | * qla_tgt_lport_register - register lport with external module | ||
4391 | * | ||
4392 | * @qla_tgt_ops: Pointer for tcm_qla2xxx qla_tgt_ops | ||
4393 | * @wwpn: Passwd FC target WWPN | ||
4394 | * @callback: lport initialization callback for tcm_qla2xxx code | ||
4395 | * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data | ||
4396 | */ | ||
4397 | int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, | ||
4398 | int (*callback)(struct scsi_qla_host *), void *target_lport_ptr) | ||
4399 | { | ||
4400 | struct qla_tgt *tgt; | ||
4401 | struct scsi_qla_host *vha; | ||
4402 | struct qla_hw_data *ha; | ||
4403 | struct Scsi_Host *host; | ||
4404 | unsigned long flags; | ||
4405 | int rc; | ||
4406 | u8 b[WWN_SIZE]; | ||
4407 | |||
4408 | mutex_lock(&qla_tgt_mutex); | ||
4409 | list_for_each_entry(tgt, &qla_tgt_glist, tgt_list_entry) { | ||
4410 | vha = tgt->vha; | ||
4411 | ha = vha->hw; | ||
4412 | |||
4413 | host = vha->host; | ||
4414 | if (!host) | ||
4415 | continue; | ||
4416 | |||
4417 | if (ha->tgt.tgt_ops != NULL) | ||
4418 | continue; | ||
4419 | |||
4420 | if (!(host->hostt->supported_mode & MODE_TARGET)) | ||
4421 | continue; | ||
4422 | |||
4423 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4424 | if (host->active_mode & MODE_TARGET) { | ||
4425 | pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", | ||
4426 | host->host_no); | ||
4427 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4428 | continue; | ||
4429 | } | ||
4430 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4431 | |||
4432 | if (!scsi_host_get(host)) { | ||
4433 | ql_dbg(ql_dbg_tgt, vha, 0xe068, | ||
4434 | "Unable to scsi_host_get() for" | ||
4435 | " qla2xxx scsi_host\n"); | ||
4436 | continue; | ||
4437 | } | ||
4438 | qlt_lport_dump(vha, wwpn, b); | ||
4439 | |||
4440 | if (memcmp(vha->port_name, b, WWN_SIZE)) { | ||
4441 | scsi_host_put(host); | ||
4442 | continue; | ||
4443 | } | ||
4444 | /* | ||
4445 | * Setup passed parameters ahead of invoking callback | ||
4446 | */ | ||
4447 | ha->tgt.tgt_ops = qla_tgt_ops; | ||
4448 | ha->tgt.target_lport_ptr = target_lport_ptr; | ||
4449 | rc = (*callback)(vha); | ||
4450 | if (rc != 0) { | ||
4451 | ha->tgt.tgt_ops = NULL; | ||
4452 | ha->tgt.target_lport_ptr = NULL; | ||
4453 | } | ||
4454 | mutex_unlock(&qla_tgt_mutex); | ||
4455 | return rc; | ||
4456 | } | ||
4457 | mutex_unlock(&qla_tgt_mutex); | ||
4458 | |||
4459 | return -ENODEV; | ||
4460 | } | ||
4461 | EXPORT_SYMBOL(qlt_lport_register); | ||
4462 | |||
4463 | /** | ||
4464 | * qla_tgt_lport_deregister - Degister lport | ||
4465 | * | ||
4466 | * @vha: Registered scsi_qla_host pointer | ||
4467 | */ | ||
4468 | void qlt_lport_deregister(struct scsi_qla_host *vha) | ||
4469 | { | ||
4470 | struct qla_hw_data *ha = vha->hw; | ||
4471 | struct Scsi_Host *sh = vha->host; | ||
4472 | /* | ||
4473 | * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data | ||
4474 | */ | ||
4475 | ha->tgt.target_lport_ptr = NULL; | ||
4476 | ha->tgt.tgt_ops = NULL; | ||
4477 | /* | ||
4478 | * Release the Scsi_Host reference for the underlying qla2xxx host | ||
4479 | */ | ||
4480 | scsi_host_put(sh); | ||
4481 | } | ||
4482 | EXPORT_SYMBOL(qlt_lport_deregister); | ||
4483 | |||
4484 | /* Must be called under HW lock */ | ||
4485 | void qlt_set_mode(struct scsi_qla_host *vha) | ||
4486 | { | ||
4487 | struct qla_hw_data *ha = vha->hw; | ||
4488 | |||
4489 | switch (ql2x_ini_mode) { | ||
4490 | case QLA2XXX_INI_MODE_DISABLED: | ||
4491 | case QLA2XXX_INI_MODE_EXCLUSIVE: | ||
4492 | vha->host->active_mode = MODE_TARGET; | ||
4493 | break; | ||
4494 | case QLA2XXX_INI_MODE_ENABLED: | ||
4495 | vha->host->active_mode |= MODE_TARGET; | ||
4496 | break; | ||
4497 | default: | ||
4498 | break; | ||
4499 | } | ||
4500 | |||
4501 | if (ha->tgt.ini_mode_force_reverse) | ||
4502 | qla_reverse_ini_mode(vha); | ||
4503 | } | ||
4504 | |||
4505 | /* Must be called under HW lock */ | ||
4506 | void qlt_clear_mode(struct scsi_qla_host *vha) | ||
4507 | { | ||
4508 | struct qla_hw_data *ha = vha->hw; | ||
4509 | |||
4510 | switch (ql2x_ini_mode) { | ||
4511 | case QLA2XXX_INI_MODE_DISABLED: | ||
4512 | vha->host->active_mode = MODE_UNKNOWN; | ||
4513 | break; | ||
4514 | case QLA2XXX_INI_MODE_EXCLUSIVE: | ||
4515 | vha->host->active_mode = MODE_INITIATOR; | ||
4516 | break; | ||
4517 | case QLA2XXX_INI_MODE_ENABLED: | ||
4518 | vha->host->active_mode &= ~MODE_TARGET; | ||
4519 | break; | ||
4520 | default: | ||
4521 | break; | ||
4522 | } | ||
4523 | |||
4524 | if (ha->tgt.ini_mode_force_reverse) | ||
4525 | qla_reverse_ini_mode(vha); | ||
4526 | } | ||
4527 | |||
4528 | /* | ||
4529 | * qla_tgt_enable_vha - NO LOCK HELD | ||
4530 | * | ||
4531 | * host_reset, bring up w/ Target Mode Enabled | ||
4532 | */ | ||
4533 | void | ||
4534 | qlt_enable_vha(struct scsi_qla_host *vha) | ||
4535 | { | ||
4536 | struct qla_hw_data *ha = vha->hw; | ||
4537 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
4538 | unsigned long flags; | ||
4539 | |||
4540 | if (!tgt) { | ||
4541 | ql_dbg(ql_dbg_tgt, vha, 0xe069, | ||
4542 | "Unable to locate qla_tgt pointer from" | ||
4543 | " struct qla_hw_data\n"); | ||
4544 | dump_stack(); | ||
4545 | return; | ||
4546 | } | ||
4547 | |||
4548 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4549 | tgt->tgt_stopped = 0; | ||
4550 | qlt_set_mode(vha); | ||
4551 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4552 | |||
4553 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
4554 | qla2xxx_wake_dpc(vha); | ||
4555 | qla2x00_wait_for_hba_online(vha); | ||
4556 | } | ||
4557 | EXPORT_SYMBOL(qlt_enable_vha); | ||
4558 | |||
4559 | /* | ||
4560 | * qla_tgt_disable_vha - NO LOCK HELD | ||
4561 | * | ||
4562 | * Disable Target Mode and reset the adapter | ||
4563 | */ | ||
4564 | void | ||
4565 | qlt_disable_vha(struct scsi_qla_host *vha) | ||
4566 | { | ||
4567 | struct qla_hw_data *ha = vha->hw; | ||
4568 | struct qla_tgt *tgt = ha->tgt.qla_tgt; | ||
4569 | unsigned long flags; | ||
4570 | |||
4571 | if (!tgt) { | ||
4572 | ql_dbg(ql_dbg_tgt, vha, 0xe06a, | ||
4573 | "Unable to locate qla_tgt pointer from" | ||
4574 | " struct qla_hw_data\n"); | ||
4575 | dump_stack(); | ||
4576 | return; | ||
4577 | } | ||
4578 | |||
4579 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
4580 | qlt_clear_mode(vha); | ||
4581 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
4582 | |||
4583 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
4584 | qla2xxx_wake_dpc(vha); | ||
4585 | qla2x00_wait_for_hba_online(vha); | ||
4586 | } | ||
4587 | |||
4588 | /* | ||
4589 | * Called from qla_init.c:qla24xx_vport_create() contex to setup | ||
4590 | * the target mode specific struct scsi_qla_host and struct qla_hw_data | ||
4591 | * members. | ||
4592 | */ | ||
4593 | void | ||
4594 | qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha) | ||
4595 | { | ||
4596 | if (!qla_tgt_mode_enabled(vha)) | ||
4597 | return; | ||
4598 | |||
4599 | mutex_init(&ha->tgt.tgt_mutex); | ||
4600 | mutex_init(&ha->tgt.tgt_host_action_mutex); | ||
4601 | |||
4602 | qlt_clear_mode(vha); | ||
4603 | |||
4604 | /* | ||
4605 | * NOTE: Currently the value is kept the same for <24xx and | ||
4606 | * >=24xx ISPs. If it is necessary to change it, | ||
4607 | * the check should be added for specific ISPs, | ||
4608 | * assigning the value appropriately. | ||
4609 | */ | ||
4610 | ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; | ||
4611 | } | ||
4612 | |||
4613 | void | ||
4614 | qlt_rff_id(struct scsi_qla_host *vha, struct ct_sns_req *ct_req) | ||
4615 | { | ||
4616 | /* | ||
4617 | * FC-4 Feature bit 0 indicates target functionality to the name server. | ||
4618 | */ | ||
4619 | if (qla_tgt_mode_enabled(vha)) { | ||
4620 | if (qla_ini_mode_enabled(vha)) | ||
4621 | ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1; | ||
4622 | else | ||
4623 | ct_req->req.rff_id.fc4_feature = BIT_0; | ||
4624 | } else if (qla_ini_mode_enabled(vha)) { | ||
4625 | ct_req->req.rff_id.fc4_feature = BIT_1; | ||
4626 | } | ||
4627 | } | ||
4628 | |||
4629 | /* | ||
4630 | * qlt_init_atio_q_entries() - Initializes ATIO queue entries. | ||
4631 | * @ha: HA context | ||
4632 | * | ||
4633 | * Beginning of ATIO ring has initialization control block already built | ||
4634 | * by nvram config routine. | ||
4635 | * | ||
4636 | * Returns 0 on success. | ||
4637 | */ | ||
4638 | void | ||
4639 | qlt_init_atio_q_entries(struct scsi_qla_host *vha) | ||
4640 | { | ||
4641 | struct qla_hw_data *ha = vha->hw; | ||
4642 | uint16_t cnt; | ||
4643 | struct atio_from_isp *pkt = (struct atio_from_isp *)ha->tgt.atio_ring; | ||
4644 | |||
4645 | if (!qla_tgt_mode_enabled(vha)) | ||
4646 | return; | ||
4647 | |||
4648 | for (cnt = 0; cnt < ha->tgt.atio_q_length; cnt++) { | ||
4649 | pkt->u.raw.signature = ATIO_PROCESSED; | ||
4650 | pkt++; | ||
4651 | } | ||
4652 | |||
4653 | } | ||
4654 | |||
4655 | /* | ||
4656 | * qlt_24xx_process_atio_queue() - Process ATIO queue entries. | ||
4657 | * @ha: SCSI driver HA context | ||
4658 | */ | ||
4659 | void | ||
4660 | qlt_24xx_process_atio_queue(struct scsi_qla_host *vha) | ||
4661 | { | ||
4662 | struct qla_hw_data *ha = vha->hw; | ||
4663 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
4664 | struct atio_from_isp *pkt; | ||
4665 | int cnt, i; | ||
4666 | |||
4667 | if (!vha->flags.online) | ||
4668 | return; | ||
4669 | |||
4670 | while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) { | ||
4671 | pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; | ||
4672 | cnt = pkt->u.raw.entry_count; | ||
4673 | |||
4674 | qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt); | ||
4675 | |||
4676 | for (i = 0; i < cnt; i++) { | ||
4677 | ha->tgt.atio_ring_index++; | ||
4678 | if (ha->tgt.atio_ring_index == ha->tgt.atio_q_length) { | ||
4679 | ha->tgt.atio_ring_index = 0; | ||
4680 | ha->tgt.atio_ring_ptr = ha->tgt.atio_ring; | ||
4681 | } else | ||
4682 | ha->tgt.atio_ring_ptr++; | ||
4683 | |||
4684 | pkt->u.raw.signature = ATIO_PROCESSED; | ||
4685 | pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; | ||
4686 | } | ||
4687 | wmb(); | ||
4688 | } | ||
4689 | |||
4690 | /* Adjust ring index */ | ||
4691 | WRT_REG_DWORD(®->atio_q_out, ha->tgt.atio_ring_index); | ||
4692 | } | ||
4693 | |||
4694 | void | ||
4695 | qlt_24xx_config_rings(struct scsi_qla_host *vha, device_reg_t __iomem *reg) | ||
4696 | { | ||
4697 | struct qla_hw_data *ha = vha->hw; | ||
4698 | |||
4699 | /* FIXME: atio_q in/out for ha->mqenable=1..? */ | ||
4700 | if (ha->mqenable) { | ||
4701 | #if 0 | ||
4702 | WRT_REG_DWORD(®->isp25mq.atio_q_in, 0); | ||
4703 | WRT_REG_DWORD(®->isp25mq.atio_q_out, 0); | ||
4704 | RD_REG_DWORD(®->isp25mq.atio_q_out); | ||
4705 | #endif | ||
4706 | } else { | ||
4707 | /* Setup APTIO registers for target mode */ | ||
4708 | WRT_REG_DWORD(®->isp24.atio_q_in, 0); | ||
4709 | WRT_REG_DWORD(®->isp24.atio_q_out, 0); | ||
4710 | RD_REG_DWORD(®->isp24.atio_q_out); | ||
4711 | } | ||
4712 | } | ||
4713 | |||
4714 | void | ||
4715 | qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) | ||
4716 | { | ||
4717 | struct qla_hw_data *ha = vha->hw; | ||
4718 | |||
4719 | if (qla_tgt_mode_enabled(vha)) { | ||
4720 | if (!ha->tgt.saved_set) { | ||
4721 | /* We save only once */ | ||
4722 | ha->tgt.saved_exchange_count = nv->exchange_count; | ||
4723 | ha->tgt.saved_firmware_options_1 = | ||
4724 | nv->firmware_options_1; | ||
4725 | ha->tgt.saved_firmware_options_2 = | ||
4726 | nv->firmware_options_2; | ||
4727 | ha->tgt.saved_firmware_options_3 = | ||
4728 | nv->firmware_options_3; | ||
4729 | ha->tgt.saved_set = 1; | ||
4730 | } | ||
4731 | |||
4732 | nv->exchange_count = __constant_cpu_to_le16(0xFFFF); | ||
4733 | |||
4734 | /* Enable target mode */ | ||
4735 | nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4); | ||
4736 | |||
4737 | /* Disable ini mode, if requested */ | ||
4738 | if (!qla_ini_mode_enabled(vha)) | ||
4739 | nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_5); | ||
4740 | |||
4741 | /* Disable Full Login after LIP */ | ||
4742 | nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); | ||
4743 | /* Enable initial LIP */ | ||
4744 | nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9); | ||
4745 | /* Enable FC tapes support */ | ||
4746 | nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); | ||
4747 | /* Disable Full Login after LIP */ | ||
4748 | nv->host_p &= __constant_cpu_to_le32(~BIT_10); | ||
4749 | /* Enable target PRLI control */ | ||
4750 | nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_14); | ||
4751 | } else { | ||
4752 | if (ha->tgt.saved_set) { | ||
4753 | nv->exchange_count = ha->tgt.saved_exchange_count; | ||
4754 | nv->firmware_options_1 = | ||
4755 | ha->tgt.saved_firmware_options_1; | ||
4756 | nv->firmware_options_2 = | ||
4757 | ha->tgt.saved_firmware_options_2; | ||
4758 | nv->firmware_options_3 = | ||
4759 | ha->tgt.saved_firmware_options_3; | ||
4760 | } | ||
4761 | return; | ||
4762 | } | ||
4763 | |||
4764 | /* out-of-order frames reassembly */ | ||
4765 | nv->firmware_options_3 |= BIT_6|BIT_9; | ||
4766 | |||
4767 | if (ha->tgt.enable_class_2) { | ||
4768 | if (vha->flags.init_done) | ||
4769 | fc_host_supported_classes(vha->host) = | ||
4770 | FC_COS_CLASS2 | FC_COS_CLASS3; | ||
4771 | |||
4772 | nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_8); | ||
4773 | } else { | ||
4774 | if (vha->flags.init_done) | ||
4775 | fc_host_supported_classes(vha->host) = FC_COS_CLASS3; | ||
4776 | |||
4777 | nv->firmware_options_2 &= ~__constant_cpu_to_le32(BIT_8); | ||
4778 | } | ||
4779 | } | ||
4780 | |||
4781 | void | ||
4782 | qlt_24xx_config_nvram_stage2(struct scsi_qla_host *vha, | ||
4783 | struct init_cb_24xx *icb) | ||
4784 | { | ||
4785 | struct qla_hw_data *ha = vha->hw; | ||
4786 | |||
4787 | if (ha->tgt.node_name_set) { | ||
4788 | memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE); | ||
4789 | icb->firmware_options_1 |= __constant_cpu_to_le32(BIT_14); | ||
4790 | } | ||
4791 | } | ||
4792 | |||
4793 | int | ||
4794 | qlt_24xx_process_response_error(struct scsi_qla_host *vha, | ||
4795 | struct sts_entry_24xx *pkt) | ||
4796 | { | ||
4797 | switch (pkt->entry_type) { | ||
4798 | case ABTS_RECV_24XX: | ||
4799 | case ABTS_RESP_24XX: | ||
4800 | case CTIO_TYPE7: | ||
4801 | case NOTIFY_ACK_TYPE: | ||
4802 | return 1; | ||
4803 | default: | ||
4804 | return 0; | ||
4805 | } | ||
4806 | } | ||
4807 | |||
4808 | void | ||
4809 | qlt_modify_vp_config(struct scsi_qla_host *vha, | ||
4810 | struct vp_config_entry_24xx *vpmod) | ||
4811 | { | ||
4812 | if (qla_tgt_mode_enabled(vha)) | ||
4813 | vpmod->options_idx1 &= ~BIT_5; | ||
4814 | /* Disable ini mode, if requested */ | ||
4815 | if (!qla_ini_mode_enabled(vha)) | ||
4816 | vpmod->options_idx1 &= ~BIT_4; | ||
4817 | } | ||
4818 | |||
4819 | void | ||
4820 | qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) | ||
4821 | { | ||
4822 | if (!QLA_TGT_MODE_ENABLED()) | ||
4823 | return; | ||
4824 | |||
4825 | mutex_init(&ha->tgt.tgt_mutex); | ||
4826 | mutex_init(&ha->tgt.tgt_host_action_mutex); | ||
4827 | qlt_clear_mode(base_vha); | ||
4828 | } | ||
4829 | |||
4830 | int | ||
4831 | qlt_mem_alloc(struct qla_hw_data *ha) | ||
4832 | { | ||
4833 | if (!QLA_TGT_MODE_ENABLED()) | ||
4834 | return 0; | ||
4835 | |||
4836 | ha->tgt.tgt_vp_map = kzalloc(sizeof(struct qla_tgt_vp_map) * | ||
4837 | MAX_MULTI_ID_FABRIC, GFP_KERNEL); | ||
4838 | if (!ha->tgt.tgt_vp_map) | ||
4839 | return -ENOMEM; | ||
4840 | |||
4841 | ha->tgt.atio_ring = dma_alloc_coherent(&ha->pdev->dev, | ||
4842 | (ha->tgt.atio_q_length + 1) * sizeof(struct atio_from_isp), | ||
4843 | &ha->tgt.atio_dma, GFP_KERNEL); | ||
4844 | if (!ha->tgt.atio_ring) { | ||
4845 | kfree(ha->tgt.tgt_vp_map); | ||
4846 | return -ENOMEM; | ||
4847 | } | ||
4848 | return 0; | ||
4849 | } | ||
4850 | |||
4851 | void | ||
4852 | qlt_mem_free(struct qla_hw_data *ha) | ||
4853 | { | ||
4854 | if (!QLA_TGT_MODE_ENABLED()) | ||
4855 | return; | ||
4856 | |||
4857 | if (ha->tgt.atio_ring) { | ||
4858 | dma_free_coherent(&ha->pdev->dev, (ha->tgt.atio_q_length + 1) * | ||
4859 | sizeof(struct atio_from_isp), ha->tgt.atio_ring, | ||
4860 | ha->tgt.atio_dma); | ||
4861 | } | ||
4862 | kfree(ha->tgt.tgt_vp_map); | ||
4863 | } | ||
4864 | |||
4865 | /* vport_slock to be held by the caller */ | ||
4866 | void | ||
4867 | qlt_update_vp_map(struct scsi_qla_host *vha, int cmd) | ||
4868 | { | ||
4869 | if (!QLA_TGT_MODE_ENABLED()) | ||
4870 | return; | ||
4871 | |||
4872 | switch (cmd) { | ||
4873 | case SET_VP_IDX: | ||
4874 | vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha; | ||
4875 | break; | ||
4876 | case SET_AL_PA: | ||
4877 | vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = vha->vp_idx; | ||
4878 | break; | ||
4879 | case RESET_VP_IDX: | ||
4880 | vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL; | ||
4881 | break; | ||
4882 | case RESET_AL_PA: | ||
4883 | vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = 0; | ||
4884 | break; | ||
4885 | } | ||
4886 | } | ||
4887 | |||
4888 | static int __init qlt_parse_ini_mode(void) | ||
4889 | { | ||
4890 | if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0) | ||
4891 | ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE; | ||
4892 | else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DISABLED) == 0) | ||
4893 | ql2x_ini_mode = QLA2XXX_INI_MODE_DISABLED; | ||
4894 | else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_ENABLED) == 0) | ||
4895 | ql2x_ini_mode = QLA2XXX_INI_MODE_ENABLED; | ||
4896 | else | ||
4897 | return false; | ||
4898 | |||
4899 | return true; | ||
4900 | } | ||
4901 | |||
4902 | int __init qlt_init(void) | ||
4903 | { | ||
4904 | int ret; | ||
4905 | |||
4906 | if (!qlt_parse_ini_mode()) { | ||
4907 | ql_log(ql_log_fatal, NULL, 0xe06b, | ||
4908 | "qlt_parse_ini_mode() failed\n"); | ||
4909 | return -EINVAL; | ||
4910 | } | ||
4911 | |||
4912 | if (!QLA_TGT_MODE_ENABLED()) | ||
4913 | return 0; | ||
4914 | |||
4915 | qla_tgt_cmd_cachep = kmem_cache_create("qla_tgt_cmd_cachep", | ||
4916 | sizeof(struct qla_tgt_cmd), __alignof__(struct qla_tgt_cmd), 0, | ||
4917 | NULL); | ||
4918 | if (!qla_tgt_cmd_cachep) { | ||
4919 | ql_log(ql_log_fatal, NULL, 0xe06c, | ||
4920 | "kmem_cache_create for qla_tgt_cmd_cachep failed\n"); | ||
4921 | return -ENOMEM; | ||
4922 | } | ||
4923 | |||
4924 | qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep", | ||
4925 | sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct | ||
4926 | qla_tgt_mgmt_cmd), 0, NULL); | ||
4927 | if (!qla_tgt_mgmt_cmd_cachep) { | ||
4928 | ql_log(ql_log_fatal, NULL, 0xe06d, | ||
4929 | "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n"); | ||
4930 | ret = -ENOMEM; | ||
4931 | goto out; | ||
4932 | } | ||
4933 | |||
4934 | qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab, | ||
4935 | mempool_free_slab, qla_tgt_mgmt_cmd_cachep); | ||
4936 | if (!qla_tgt_mgmt_cmd_mempool) { | ||
4937 | ql_log(ql_log_fatal, NULL, 0xe06e, | ||
4938 | "mempool_create for qla_tgt_mgmt_cmd_mempool failed\n"); | ||
4939 | ret = -ENOMEM; | ||
4940 | goto out_mgmt_cmd_cachep; | ||
4941 | } | ||
4942 | |||
4943 | qla_tgt_wq = alloc_workqueue("qla_tgt_wq", 0, 0); | ||
4944 | if (!qla_tgt_wq) { | ||
4945 | ql_log(ql_log_fatal, NULL, 0xe06f, | ||
4946 | "alloc_workqueue for qla_tgt_wq failed\n"); | ||
4947 | ret = -ENOMEM; | ||
4948 | goto out_cmd_mempool; | ||
4949 | } | ||
4950 | /* | ||
4951 | * Return 1 to signal that initiator-mode is being disabled | ||
4952 | */ | ||
4953 | return (ql2x_ini_mode == QLA2XXX_INI_MODE_DISABLED) ? 1 : 0; | ||
4954 | |||
4955 | out_cmd_mempool: | ||
4956 | mempool_destroy(qla_tgt_mgmt_cmd_mempool); | ||
4957 | out_mgmt_cmd_cachep: | ||
4958 | kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep); | ||
4959 | out: | ||
4960 | kmem_cache_destroy(qla_tgt_cmd_cachep); | ||
4961 | return ret; | ||
4962 | } | ||
4963 | |||
4964 | void qlt_exit(void) | ||
4965 | { | ||
4966 | if (!QLA_TGT_MODE_ENABLED()) | ||
4967 | return; | ||
4968 | |||
4969 | destroy_workqueue(qla_tgt_wq); | ||
4970 | mempool_destroy(qla_tgt_mgmt_cmd_mempool); | ||
4971 | kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep); | ||
4972 | kmem_cache_destroy(qla_tgt_cmd_cachep); | ||
4973 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h new file mode 100644 index 000000000000..9ec19bc2f0fe --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_target.h | |||
@@ -0,0 +1,1005 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net> | ||
3 | * Copyright (C) 2004 - 2005 Leonid Stoljar | ||
4 | * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us> | ||
5 | * Copyright (C) 2007 - 2010 ID7 Ltd. | ||
6 | * | ||
7 | * Forward port and refactoring to modern qla2xxx and target/configfs | ||
8 | * | ||
9 | * Copyright (C) 2010-2011 Nicholas A. Bellinger <nab@kernel.org> | ||
10 | * | ||
11 | * Additional file for the target driver support. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | */ | ||
23 | /* | ||
24 | * This is the global def file that is useful for including from the | ||
25 | * target portion. | ||
26 | */ | ||
27 | |||
28 | #ifndef __QLA_TARGET_H | ||
29 | #define __QLA_TARGET_H | ||
30 | |||
31 | #include "qla_def.h" | ||
32 | |||
33 | /* | ||
34 | * Must be changed on any change in any initiator visible interfaces or | ||
35 | * data in the target add-on | ||
36 | */ | ||
37 | #define QLA2XXX_TARGET_MAGIC 269 | ||
38 | |||
39 | /* | ||
40 | * Must be changed on any change in any target visible interfaces or | ||
41 | * data in the initiator | ||
42 | */ | ||
43 | #define QLA2XXX_INITIATOR_MAGIC 57222 | ||
44 | |||
45 | #define QLA2XXX_INI_MODE_STR_EXCLUSIVE "exclusive" | ||
46 | #define QLA2XXX_INI_MODE_STR_DISABLED "disabled" | ||
47 | #define QLA2XXX_INI_MODE_STR_ENABLED "enabled" | ||
48 | |||
49 | #define QLA2XXX_INI_MODE_EXCLUSIVE 0 | ||
50 | #define QLA2XXX_INI_MODE_DISABLED 1 | ||
51 | #define QLA2XXX_INI_MODE_ENABLED 2 | ||
52 | |||
53 | #define QLA2XXX_COMMAND_COUNT_INIT 250 | ||
54 | #define QLA2XXX_IMMED_NOTIFY_COUNT_INIT 250 | ||
55 | |||
56 | /* | ||
57 | * Used to mark which completion handles (for RIO Status's) are for CTIO's | ||
58 | * vs. regular (non-target) info. This is checked for in | ||
59 | * qla2x00_process_response_queue() to see if a handle coming back in a | ||
60 | * multi-complete should come to the tgt driver or be handled there by qla2xxx | ||
61 | */ | ||
62 | #define CTIO_COMPLETION_HANDLE_MARK BIT_29 | ||
63 | #if (CTIO_COMPLETION_HANDLE_MARK <= MAX_OUTSTANDING_COMMANDS) | ||
64 | #error "CTIO_COMPLETION_HANDLE_MARK not larger than MAX_OUTSTANDING_COMMANDS" | ||
65 | #endif | ||
66 | #define HANDLE_IS_CTIO_COMP(h) (h & CTIO_COMPLETION_HANDLE_MARK) | ||
67 | |||
68 | /* Used to mark CTIO as intermediate */ | ||
69 | #define CTIO_INTERMEDIATE_HANDLE_MARK BIT_30 | ||
70 | |||
71 | #ifndef OF_SS_MODE_0 | ||
72 | /* | ||
73 | * ISP target entries - Flags bit definitions. | ||
74 | */ | ||
75 | #define OF_SS_MODE_0 0 | ||
76 | #define OF_SS_MODE_1 1 | ||
77 | #define OF_SS_MODE_2 2 | ||
78 | #define OF_SS_MODE_3 3 | ||
79 | |||
80 | #define OF_EXPL_CONF BIT_5 /* Explicit Confirmation Requested */ | ||
81 | #define OF_DATA_IN BIT_6 /* Data in to initiator */ | ||
82 | /* (data from target to initiator) */ | ||
83 | #define OF_DATA_OUT BIT_7 /* Data out from initiator */ | ||
84 | /* (data from initiator to target) */ | ||
85 | #define OF_NO_DATA (BIT_7 | BIT_6) | ||
86 | #define OF_INC_RC BIT_8 /* Increment command resource count */ | ||
87 | #define OF_FAST_POST BIT_9 /* Enable mailbox fast posting. */ | ||
88 | #define OF_CONF_REQ BIT_13 /* Confirmation Requested */ | ||
89 | #define OF_TERM_EXCH BIT_14 /* Terminate exchange */ | ||
90 | #define OF_SSTS BIT_15 /* Send SCSI status */ | ||
91 | #endif | ||
92 | |||
93 | #ifndef QLA_TGT_DATASEGS_PER_CMD32 | ||
94 | #define QLA_TGT_DATASEGS_PER_CMD32 3 | ||
95 | #define QLA_TGT_DATASEGS_PER_CONT32 7 | ||
96 | #define QLA_TGT_MAX_SG32(ql) \ | ||
97 | (((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD32 + \ | ||
98 | QLA_TGT_DATASEGS_PER_CONT32*((ql) - 1)) : 0) | ||
99 | |||
100 | #define QLA_TGT_DATASEGS_PER_CMD64 2 | ||
101 | #define QLA_TGT_DATASEGS_PER_CONT64 5 | ||
102 | #define QLA_TGT_MAX_SG64(ql) \ | ||
103 | (((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD64 + \ | ||
104 | QLA_TGT_DATASEGS_PER_CONT64*((ql) - 1)) : 0) | ||
105 | #endif | ||
106 | |||
107 | #ifndef QLA_TGT_DATASEGS_PER_CMD_24XX | ||
108 | #define QLA_TGT_DATASEGS_PER_CMD_24XX 1 | ||
109 | #define QLA_TGT_DATASEGS_PER_CONT_24XX 5 | ||
110 | #define QLA_TGT_MAX_SG_24XX(ql) \ | ||
111 | (min(1270, ((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD_24XX + \ | ||
112 | QLA_TGT_DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0)) | ||
113 | #endif | ||
114 | #endif | ||
115 | |||
116 | #define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \ | ||
117 | ? le16_to_cpu((iocb)->u.isp2x.target.extended) \ | ||
118 | : (uint16_t)(iocb)->u.isp2x.target.id.standard) | ||
119 | |||
120 | #ifndef IMMED_NOTIFY_TYPE | ||
121 | #define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */ | ||
122 | /* | ||
123 | * ISP queue - immediate notify entry structure definition. | ||
124 | * This is sent by the ISP to the Target driver. | ||
125 | * This IOCB would have report of events sent by the | ||
126 | * initiator, that needs to be handled by the target | ||
127 | * driver immediately. | ||
128 | */ | ||
129 | struct imm_ntfy_from_isp { | ||
130 | uint8_t entry_type; /* Entry type. */ | ||
131 | uint8_t entry_count; /* Entry count. */ | ||
132 | uint8_t sys_define; /* System defined. */ | ||
133 | uint8_t entry_status; /* Entry Status. */ | ||
134 | union { | ||
135 | struct { | ||
136 | uint32_t sys_define_2; /* System defined. */ | ||
137 | target_id_t target; | ||
138 | uint16_t lun; | ||
139 | uint8_t target_id; | ||
140 | uint8_t reserved_1; | ||
141 | uint16_t status_modifier; | ||
142 | uint16_t status; | ||
143 | uint16_t task_flags; | ||
144 | uint16_t seq_id; | ||
145 | uint16_t srr_rx_id; | ||
146 | uint32_t srr_rel_offs; | ||
147 | uint16_t srr_ui; | ||
148 | #define SRR_IU_DATA_IN 0x1 | ||
149 | #define SRR_IU_DATA_OUT 0x5 | ||
150 | #define SRR_IU_STATUS 0x7 | ||
151 | uint16_t srr_ox_id; | ||
152 | uint8_t reserved_2[28]; | ||
153 | } isp2x; | ||
154 | struct { | ||
155 | uint32_t reserved; | ||
156 | uint16_t nport_handle; | ||
157 | uint16_t reserved_2; | ||
158 | uint16_t flags; | ||
159 | #define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1 | ||
160 | #define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0 | ||
161 | uint16_t srr_rx_id; | ||
162 | uint16_t status; | ||
163 | uint8_t status_subcode; | ||
164 | uint8_t reserved_3; | ||
165 | uint32_t exchange_address; | ||
166 | uint32_t srr_rel_offs; | ||
167 | uint16_t srr_ui; | ||
168 | uint16_t srr_ox_id; | ||
169 | uint8_t reserved_4[19]; | ||
170 | uint8_t vp_index; | ||
171 | uint32_t reserved_5; | ||
172 | uint8_t port_id[3]; | ||
173 | uint8_t reserved_6; | ||
174 | } isp24; | ||
175 | } u; | ||
176 | uint16_t reserved_7; | ||
177 | uint16_t ox_id; | ||
178 | } __packed; | ||
179 | #endif | ||
180 | |||
181 | #ifndef NOTIFY_ACK_TYPE | ||
182 | #define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */ | ||
183 | /* | ||
184 | * ISP queue - notify acknowledge entry structure definition. | ||
185 | * This is sent to the ISP from the target driver. | ||
186 | */ | ||
187 | struct nack_to_isp { | ||
188 | uint8_t entry_type; /* Entry type. */ | ||
189 | uint8_t entry_count; /* Entry count. */ | ||
190 | uint8_t sys_define; /* System defined. */ | ||
191 | uint8_t entry_status; /* Entry Status. */ | ||
192 | union { | ||
193 | struct { | ||
194 | uint32_t sys_define_2; /* System defined. */ | ||
195 | target_id_t target; | ||
196 | uint8_t target_id; | ||
197 | uint8_t reserved_1; | ||
198 | uint16_t flags; | ||
199 | uint16_t resp_code; | ||
200 | uint16_t status; | ||
201 | uint16_t task_flags; | ||
202 | uint16_t seq_id; | ||
203 | uint16_t srr_rx_id; | ||
204 | uint32_t srr_rel_offs; | ||
205 | uint16_t srr_ui; | ||
206 | uint16_t srr_flags; | ||
207 | uint16_t srr_reject_code; | ||
208 | uint8_t srr_reject_vendor_uniq; | ||
209 | uint8_t srr_reject_code_expl; | ||
210 | uint8_t reserved_2[24]; | ||
211 | } isp2x; | ||
212 | struct { | ||
213 | uint32_t handle; | ||
214 | uint16_t nport_handle; | ||
215 | uint16_t reserved_1; | ||
216 | uint16_t flags; | ||
217 | uint16_t srr_rx_id; | ||
218 | uint16_t status; | ||
219 | uint8_t status_subcode; | ||
220 | uint8_t reserved_3; | ||
221 | uint32_t exchange_address; | ||
222 | uint32_t srr_rel_offs; | ||
223 | uint16_t srr_ui; | ||
224 | uint16_t srr_flags; | ||
225 | uint8_t reserved_4[19]; | ||
226 | uint8_t vp_index; | ||
227 | uint8_t srr_reject_vendor_uniq; | ||
228 | uint8_t srr_reject_code_expl; | ||
229 | uint8_t srr_reject_code; | ||
230 | uint8_t reserved_5[5]; | ||
231 | } isp24; | ||
232 | } u; | ||
233 | uint8_t reserved[2]; | ||
234 | uint16_t ox_id; | ||
235 | } __packed; | ||
236 | #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 | ||
237 | #define NOTIFY_ACK_SRR_FLAGS_REJECT 1 | ||
238 | |||
239 | #define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9 | ||
240 | |||
241 | #define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0 | ||
242 | #define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a | ||
243 | |||
244 | #define NOTIFY_ACK_SUCCESS 0x01 | ||
245 | #endif | ||
246 | |||
247 | #ifndef ACCEPT_TGT_IO_TYPE | ||
248 | #define ACCEPT_TGT_IO_TYPE 0x16 /* Accept target I/O entry. */ | ||
249 | #endif | ||
250 | |||
251 | #ifndef CONTINUE_TGT_IO_TYPE | ||
252 | #define CONTINUE_TGT_IO_TYPE 0x17 | ||
253 | /* | ||
254 | * ISP queue - Continue Target I/O (CTIO) entry for status mode 0 structure. | ||
255 | * This structure is sent to the ISP 2xxx from target driver. | ||
256 | */ | ||
257 | struct ctio_to_2xxx { | ||
258 | uint8_t entry_type; /* Entry type. */ | ||
259 | uint8_t entry_count; /* Entry count. */ | ||
260 | uint8_t sys_define; /* System defined. */ | ||
261 | uint8_t entry_status; /* Entry Status. */ | ||
262 | uint32_t handle; /* System defined handle */ | ||
263 | target_id_t target; | ||
264 | uint16_t rx_id; | ||
265 | uint16_t flags; | ||
266 | uint16_t status; | ||
267 | uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ | ||
268 | uint16_t dseg_count; /* Data segment count. */ | ||
269 | uint32_t relative_offset; | ||
270 | uint32_t residual; | ||
271 | uint16_t reserved_1[3]; | ||
272 | uint16_t scsi_status; | ||
273 | uint32_t transfer_length; | ||
274 | uint32_t dseg_0_address; /* Data segment 0 address. */ | ||
275 | uint32_t dseg_0_length; /* Data segment 0 length. */ | ||
276 | uint32_t dseg_1_address; /* Data segment 1 address. */ | ||
277 | uint32_t dseg_1_length; /* Data segment 1 length. */ | ||
278 | uint32_t dseg_2_address; /* Data segment 2 address. */ | ||
279 | uint32_t dseg_2_length; /* Data segment 2 length. */ | ||
280 | } __packed; | ||
281 | #define ATIO_PATH_INVALID 0x07 | ||
282 | #define ATIO_CANT_PROV_CAP 0x16 | ||
283 | #define ATIO_CDB_VALID 0x3D | ||
284 | |||
285 | #define ATIO_EXEC_READ BIT_1 | ||
286 | #define ATIO_EXEC_WRITE BIT_0 | ||
287 | #endif | ||
288 | |||
289 | #ifndef CTIO_A64_TYPE | ||
290 | #define CTIO_A64_TYPE 0x1F | ||
291 | #define CTIO_SUCCESS 0x01 | ||
292 | #define CTIO_ABORTED 0x02 | ||
293 | #define CTIO_INVALID_RX_ID 0x08 | ||
294 | #define CTIO_TIMEOUT 0x0B | ||
295 | #define CTIO_LIP_RESET 0x0E | ||
296 | #define CTIO_TARGET_RESET 0x17 | ||
297 | #define CTIO_PORT_UNAVAILABLE 0x28 | ||
298 | #define CTIO_PORT_LOGGED_OUT 0x29 | ||
299 | #define CTIO_PORT_CONF_CHANGED 0x2A | ||
300 | #define CTIO_SRR_RECEIVED 0x45 | ||
301 | #endif | ||
302 | |||
303 | #ifndef CTIO_RET_TYPE | ||
304 | #define CTIO_RET_TYPE 0x17 /* CTIO return entry */ | ||
305 | #define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */ | ||
306 | |||
307 | struct fcp_hdr { | ||
308 | uint8_t r_ctl; | ||
309 | uint8_t d_id[3]; | ||
310 | uint8_t cs_ctl; | ||
311 | uint8_t s_id[3]; | ||
312 | uint8_t type; | ||
313 | uint8_t f_ctl[3]; | ||
314 | uint8_t seq_id; | ||
315 | uint8_t df_ctl; | ||
316 | uint16_t seq_cnt; | ||
317 | uint16_t ox_id; | ||
318 | uint16_t rx_id; | ||
319 | uint32_t parameter; | ||
320 | } __packed; | ||
321 | |||
322 | struct fcp_hdr_le { | ||
323 | uint8_t d_id[3]; | ||
324 | uint8_t r_ctl; | ||
325 | uint8_t s_id[3]; | ||
326 | uint8_t cs_ctl; | ||
327 | uint8_t f_ctl[3]; | ||
328 | uint8_t type; | ||
329 | uint16_t seq_cnt; | ||
330 | uint8_t df_ctl; | ||
331 | uint8_t seq_id; | ||
332 | uint16_t rx_id; | ||
333 | uint16_t ox_id; | ||
334 | uint32_t parameter; | ||
335 | } __packed; | ||
336 | |||
337 | #define F_CTL_EXCH_CONTEXT_RESP BIT_23 | ||
338 | #define F_CTL_SEQ_CONTEXT_RESIP BIT_22 | ||
339 | #define F_CTL_LAST_SEQ BIT_20 | ||
340 | #define F_CTL_END_SEQ BIT_19 | ||
341 | #define F_CTL_SEQ_INITIATIVE BIT_16 | ||
342 | |||
343 | #define R_CTL_BASIC_LINK_SERV 0x80 | ||
344 | #define R_CTL_B_ACC 0x4 | ||
345 | #define R_CTL_B_RJT 0x5 | ||
346 | |||
347 | struct atio7_fcp_cmnd { | ||
348 | uint64_t lun; | ||
349 | uint8_t cmnd_ref; | ||
350 | uint8_t task_attr:3; | ||
351 | uint8_t reserved:5; | ||
352 | uint8_t task_mgmt_flags; | ||
353 | #define FCP_CMND_TASK_MGMT_CLEAR_ACA 6 | ||
354 | #define FCP_CMND_TASK_MGMT_TARGET_RESET 5 | ||
355 | #define FCP_CMND_TASK_MGMT_LU_RESET 4 | ||
356 | #define FCP_CMND_TASK_MGMT_CLEAR_TASK_SET 2 | ||
357 | #define FCP_CMND_TASK_MGMT_ABORT_TASK_SET 1 | ||
358 | uint8_t wrdata:1; | ||
359 | uint8_t rddata:1; | ||
360 | uint8_t add_cdb_len:6; | ||
361 | uint8_t cdb[16]; | ||
362 | /* | ||
363 | * add_cdb is optional and can absent from struct atio7_fcp_cmnd. Size 4 | ||
364 | * only to make sizeof(struct atio7_fcp_cmnd) be as expected by | ||
365 | * BUILD_BUG_ON in qlt_init(). | ||
366 | */ | ||
367 | uint8_t add_cdb[4]; | ||
368 | /* uint32_t data_length; */ | ||
369 | } __packed; | ||
370 | |||
371 | /* | ||
372 | * ISP queue - Accept Target I/O (ATIO) type entry IOCB structure. | ||
373 | * This is sent from the ISP to the target driver. | ||
374 | */ | ||
375 | struct atio_from_isp { | ||
376 | union { | ||
377 | struct { | ||
378 | uint16_t entry_hdr; | ||
379 | uint8_t sys_define; /* System defined. */ | ||
380 | uint8_t entry_status; /* Entry Status. */ | ||
381 | uint32_t sys_define_2; /* System defined. */ | ||
382 | target_id_t target; | ||
383 | uint16_t rx_id; | ||
384 | uint16_t flags; | ||
385 | uint16_t status; | ||
386 | uint8_t command_ref; | ||
387 | uint8_t task_codes; | ||
388 | uint8_t task_flags; | ||
389 | uint8_t execution_codes; | ||
390 | uint8_t cdb[MAX_CMDSZ]; | ||
391 | uint32_t data_length; | ||
392 | uint16_t lun; | ||
393 | uint8_t initiator_port_name[WWN_SIZE]; /* on qla23xx */ | ||
394 | uint16_t reserved_32[6]; | ||
395 | uint16_t ox_id; | ||
396 | } isp2x; | ||
397 | struct { | ||
398 | uint16_t entry_hdr; | ||
399 | uint8_t fcp_cmnd_len_low; | ||
400 | uint8_t fcp_cmnd_len_high:4; | ||
401 | uint8_t attr:4; | ||
402 | uint32_t exchange_addr; | ||
403 | #define ATIO_EXCHANGE_ADDRESS_UNKNOWN 0xFFFFFFFF | ||
404 | struct fcp_hdr fcp_hdr; | ||
405 | struct atio7_fcp_cmnd fcp_cmnd; | ||
406 | } isp24; | ||
407 | struct { | ||
408 | uint8_t entry_type; /* Entry type. */ | ||
409 | uint8_t entry_count; /* Entry count. */ | ||
410 | uint8_t data[58]; | ||
411 | uint32_t signature; | ||
412 | #define ATIO_PROCESSED 0xDEADDEAD /* Signature */ | ||
413 | } raw; | ||
414 | } u; | ||
415 | } __packed; | ||
416 | |||
417 | #define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */ | ||
418 | |||
419 | /* | ||
420 | * ISP queue - Continue Target I/O (ATIO) type 7 entry (for 24xx) structure. | ||
421 | * This structure is sent to the ISP 24xx from the target driver. | ||
422 | */ | ||
423 | |||
424 | struct ctio7_to_24xx { | ||
425 | uint8_t entry_type; /* Entry type. */ | ||
426 | uint8_t entry_count; /* Entry count. */ | ||
427 | uint8_t sys_define; /* System defined. */ | ||
428 | uint8_t entry_status; /* Entry Status. */ | ||
429 | uint32_t handle; /* System defined handle */ | ||
430 | uint16_t nport_handle; | ||
431 | #define CTIO7_NHANDLE_UNRECOGNIZED 0xFFFF | ||
432 | uint16_t timeout; | ||
433 | uint16_t dseg_count; /* Data segment count. */ | ||
434 | uint8_t vp_index; | ||
435 | uint8_t add_flags; | ||
436 | uint8_t initiator_id[3]; | ||
437 | uint8_t reserved; | ||
438 | uint32_t exchange_addr; | ||
439 | union { | ||
440 | struct { | ||
441 | uint16_t reserved1; | ||
442 | uint16_t flags; | ||
443 | uint32_t residual; | ||
444 | uint16_t ox_id; | ||
445 | uint16_t scsi_status; | ||
446 | uint32_t relative_offset; | ||
447 | uint32_t reserved2; | ||
448 | uint32_t transfer_length; | ||
449 | uint32_t reserved3; | ||
450 | /* Data segment 0 address. */ | ||
451 | uint32_t dseg_0_address[2]; | ||
452 | /* Data segment 0 length. */ | ||
453 | uint32_t dseg_0_length; | ||
454 | } status0; | ||
455 | struct { | ||
456 | uint16_t sense_length; | ||
457 | uint16_t flags; | ||
458 | uint32_t residual; | ||
459 | uint16_t ox_id; | ||
460 | uint16_t scsi_status; | ||
461 | uint16_t response_len; | ||
462 | uint16_t reserved; | ||
463 | uint8_t sense_data[24]; | ||
464 | } status1; | ||
465 | } u; | ||
466 | } __packed; | ||
467 | |||
468 | /* | ||
469 | * ISP queue - CTIO type 7 from ISP 24xx to target driver | ||
470 | * returned entry structure. | ||
471 | */ | ||
472 | struct ctio7_from_24xx { | ||
473 | uint8_t entry_type; /* Entry type. */ | ||
474 | uint8_t entry_count; /* Entry count. */ | ||
475 | uint8_t sys_define; /* System defined. */ | ||
476 | uint8_t entry_status; /* Entry Status. */ | ||
477 | uint32_t handle; /* System defined handle */ | ||
478 | uint16_t status; | ||
479 | uint16_t timeout; | ||
480 | uint16_t dseg_count; /* Data segment count. */ | ||
481 | uint8_t vp_index; | ||
482 | uint8_t reserved1[5]; | ||
483 | uint32_t exchange_address; | ||
484 | uint16_t reserved2; | ||
485 | uint16_t flags; | ||
486 | uint32_t residual; | ||
487 | uint16_t ox_id; | ||
488 | uint16_t reserved3; | ||
489 | uint32_t relative_offset; | ||
490 | uint8_t reserved4[24]; | ||
491 | } __packed; | ||
492 | |||
493 | /* CTIO7 flags values */ | ||
494 | #define CTIO7_FLAGS_SEND_STATUS BIT_15 | ||
495 | #define CTIO7_FLAGS_TERMINATE BIT_14 | ||
496 | #define CTIO7_FLAGS_CONFORM_REQ BIT_13 | ||
497 | #define CTIO7_FLAGS_DONT_RET_CTIO BIT_8 | ||
498 | #define CTIO7_FLAGS_STATUS_MODE_0 0 | ||
499 | #define CTIO7_FLAGS_STATUS_MODE_1 BIT_6 | ||
500 | #define CTIO7_FLAGS_EXPLICIT_CONFORM BIT_5 | ||
501 | #define CTIO7_FLAGS_CONFIRM_SATISF BIT_4 | ||
502 | #define CTIO7_FLAGS_DSD_PTR BIT_2 | ||
503 | #define CTIO7_FLAGS_DATA_IN BIT_1 | ||
504 | #define CTIO7_FLAGS_DATA_OUT BIT_0 | ||
505 | |||
506 | #define ELS_PLOGI 0x3 | ||
507 | #define ELS_FLOGI 0x4 | ||
508 | #define ELS_LOGO 0x5 | ||
509 | #define ELS_PRLI 0x20 | ||
510 | #define ELS_PRLO 0x21 | ||
511 | #define ELS_TPRLO 0x24 | ||
512 | #define ELS_PDISC 0x50 | ||
513 | #define ELS_ADISC 0x52 | ||
514 | |||
515 | /* | ||
516 | * ISP queue - ABTS received/response entries structure definition for 24xx. | ||
517 | */ | ||
518 | #define ABTS_RECV_24XX 0x54 /* ABTS received (for 24xx) */ | ||
519 | #define ABTS_RESP_24XX 0x55 /* ABTS responce (for 24xx) */ | ||
520 | |||
521 | /* | ||
522 | * ISP queue - ABTS received IOCB entry structure definition for 24xx. | ||
523 | * The ABTS BLS received from the wire is sent to the | ||
524 | * target driver by the ISP 24xx. | ||
525 | * The IOCB is placed on the response queue. | ||
526 | */ | ||
527 | struct abts_recv_from_24xx { | ||
528 | uint8_t entry_type; /* Entry type. */ | ||
529 | uint8_t entry_count; /* Entry count. */ | ||
530 | uint8_t sys_define; /* System defined. */ | ||
531 | uint8_t entry_status; /* Entry Status. */ | ||
532 | uint8_t reserved_1[6]; | ||
533 | uint16_t nport_handle; | ||
534 | uint8_t reserved_2[2]; | ||
535 | uint8_t vp_index; | ||
536 | uint8_t reserved_3:4; | ||
537 | uint8_t sof_type:4; | ||
538 | uint32_t exchange_address; | ||
539 | struct fcp_hdr_le fcp_hdr_le; | ||
540 | uint8_t reserved_4[16]; | ||
541 | uint32_t exchange_addr_to_abort; | ||
542 | } __packed; | ||
543 | |||
544 | #define ABTS_PARAM_ABORT_SEQ BIT_0 | ||
545 | |||
546 | struct ba_acc_le { | ||
547 | uint16_t reserved; | ||
548 | uint8_t seq_id_last; | ||
549 | uint8_t seq_id_valid; | ||
550 | #define SEQ_ID_VALID 0x80 | ||
551 | #define SEQ_ID_INVALID 0x00 | ||
552 | uint16_t rx_id; | ||
553 | uint16_t ox_id; | ||
554 | uint16_t high_seq_cnt; | ||
555 | uint16_t low_seq_cnt; | ||
556 | } __packed; | ||
557 | |||
558 | struct ba_rjt_le { | ||
559 | uint8_t vendor_uniq; | ||
560 | uint8_t reason_expl; | ||
561 | uint8_t reason_code; | ||
562 | #define BA_RJT_REASON_CODE_INVALID_COMMAND 0x1 | ||
563 | #define BA_RJT_REASON_CODE_UNABLE_TO_PERFORM 0x9 | ||
564 | uint8_t reserved; | ||
565 | } __packed; | ||
566 | |||
567 | /* | ||
568 | * ISP queue - ABTS Response IOCB entry structure definition for 24xx. | ||
569 | * The ABTS response to the ABTS received is sent by the | ||
570 | * target driver to the ISP 24xx. | ||
571 | * The IOCB is placed on the request queue. | ||
572 | */ | ||
573 | struct abts_resp_to_24xx { | ||
574 | uint8_t entry_type; /* Entry type. */ | ||
575 | uint8_t entry_count; /* Entry count. */ | ||
576 | uint8_t sys_define; /* System defined. */ | ||
577 | uint8_t entry_status; /* Entry Status. */ | ||
578 | uint32_t handle; | ||
579 | uint16_t reserved_1; | ||
580 | uint16_t nport_handle; | ||
581 | uint16_t control_flags; | ||
582 | #define ABTS_CONTR_FLG_TERM_EXCHG BIT_0 | ||
583 | uint8_t vp_index; | ||
584 | uint8_t reserved_3:4; | ||
585 | uint8_t sof_type:4; | ||
586 | uint32_t exchange_address; | ||
587 | struct fcp_hdr_le fcp_hdr_le; | ||
588 | union { | ||
589 | struct ba_acc_le ba_acct; | ||
590 | struct ba_rjt_le ba_rjt; | ||
591 | } __packed payload; | ||
592 | uint32_t reserved_4; | ||
593 | uint32_t exchange_addr_to_abort; | ||
594 | } __packed; | ||
595 | |||
596 | /* | ||
597 | * ISP queue - ABTS Response IOCB from ISP24xx Firmware entry structure. | ||
598 | * The ABTS response with completion status to the ABTS response | ||
599 | * (sent by the target driver to the ISP 24xx) is sent by the | ||
600 | * ISP24xx firmware to the target driver. | ||
601 | * The IOCB is placed on the response queue. | ||
602 | */ | ||
603 | struct abts_resp_from_24xx_fw { | ||
604 | uint8_t entry_type; /* Entry type. */ | ||
605 | uint8_t entry_count; /* Entry count. */ | ||
606 | uint8_t sys_define; /* System defined. */ | ||
607 | uint8_t entry_status; /* Entry Status. */ | ||
608 | uint32_t handle; | ||
609 | uint16_t compl_status; | ||
610 | #define ABTS_RESP_COMPL_SUCCESS 0 | ||
611 | #define ABTS_RESP_COMPL_SUBCODE_ERROR 0x31 | ||
612 | uint16_t nport_handle; | ||
613 | uint16_t reserved_1; | ||
614 | uint8_t reserved_2; | ||
615 | uint8_t reserved_3:4; | ||
616 | uint8_t sof_type:4; | ||
617 | uint32_t exchange_address; | ||
618 | struct fcp_hdr_le fcp_hdr_le; | ||
619 | uint8_t reserved_4[8]; | ||
620 | uint32_t error_subcode1; | ||
621 | #define ABTS_RESP_SUBCODE_ERR_ABORTED_EXCH_NOT_TERM 0x1E | ||
622 | uint32_t error_subcode2; | ||
623 | uint32_t exchange_addr_to_abort; | ||
624 | } __packed; | ||
625 | |||
626 | /********************************************************************\ | ||
627 | * Type Definitions used by initiator & target halves | ||
628 | \********************************************************************/ | ||
629 | |||
630 | struct qla_tgt_mgmt_cmd; | ||
631 | struct qla_tgt_sess; | ||
632 | |||
633 | /* | ||
634 | * This structure provides a template of function calls that the | ||
635 | * target driver (from within qla_target.c) can issue to the | ||
636 | * target module (tcm_qla2xxx). | ||
637 | */ | ||
638 | struct qla_tgt_func_tmpl { | ||
639 | |||
640 | int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *, | ||
641 | unsigned char *, uint32_t, int, int, int); | ||
642 | int (*handle_data)(struct qla_tgt_cmd *); | ||
643 | int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t, | ||
644 | uint32_t); | ||
645 | void (*free_cmd)(struct qla_tgt_cmd *); | ||
646 | void (*free_mcmd)(struct qla_tgt_mgmt_cmd *); | ||
647 | void (*free_session)(struct qla_tgt_sess *); | ||
648 | |||
649 | int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, | ||
650 | void *, uint8_t *, uint16_t); | ||
651 | struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, | ||
652 | const uint16_t); | ||
653 | struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, | ||
654 | const uint8_t *); | ||
655 | void (*clear_nacl_from_fcport_map)(struct qla_tgt_sess *); | ||
656 | void (*put_sess)(struct qla_tgt_sess *); | ||
657 | void (*shutdown_sess)(struct qla_tgt_sess *); | ||
658 | }; | ||
659 | |||
660 | int qla2x00_wait_for_hba_online(struct scsi_qla_host *); | ||
661 | |||
662 | #include <target/target_core_base.h> | ||
663 | |||
664 | #define QLA_TGT_TIMEOUT 10 /* in seconds */ | ||
665 | |||
666 | #define QLA_TGT_MAX_HW_PENDING_TIME 60 /* in seconds */ | ||
667 | |||
668 | /* Immediate notify status constants */ | ||
669 | #define IMM_NTFY_LIP_RESET 0x000E | ||
670 | #define IMM_NTFY_LIP_LINK_REINIT 0x000F | ||
671 | #define IMM_NTFY_IOCB_OVERFLOW 0x0016 | ||
672 | #define IMM_NTFY_ABORT_TASK 0x0020 | ||
673 | #define IMM_NTFY_PORT_LOGOUT 0x0029 | ||
674 | #define IMM_NTFY_PORT_CONFIG 0x002A | ||
675 | #define IMM_NTFY_GLBL_TPRLO 0x002D | ||
676 | #define IMM_NTFY_GLBL_LOGO 0x002E | ||
677 | #define IMM_NTFY_RESOURCE 0x0034 | ||
678 | #define IMM_NTFY_MSG_RX 0x0036 | ||
679 | #define IMM_NTFY_SRR 0x0045 | ||
680 | #define IMM_NTFY_ELS 0x0046 | ||
681 | |||
682 | /* Immediate notify task flags */ | ||
683 | #define IMM_NTFY_TASK_MGMT_SHIFT 8 | ||
684 | |||
685 | #define QLA_TGT_CLEAR_ACA 0x40 | ||
686 | #define QLA_TGT_TARGET_RESET 0x20 | ||
687 | #define QLA_TGT_LUN_RESET 0x10 | ||
688 | #define QLA_TGT_CLEAR_TS 0x04 | ||
689 | #define QLA_TGT_ABORT_TS 0x02 | ||
690 | #define QLA_TGT_ABORT_ALL_SESS 0xFFFF | ||
691 | #define QLA_TGT_ABORT_ALL 0xFFFE | ||
692 | #define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD | ||
693 | #define QLA_TGT_NEXUS_LOSS 0xFFFC | ||
694 | |||
695 | /* Notify Acknowledge flags */ | ||
696 | #define NOTIFY_ACK_RES_COUNT BIT_8 | ||
697 | #define NOTIFY_ACK_CLEAR_LIP_RESET BIT_5 | ||
698 | #define NOTIFY_ACK_TM_RESP_CODE_VALID BIT_4 | ||
699 | |||
700 | /* Command's states */ | ||
701 | #define QLA_TGT_STATE_NEW 0 /* New command + target processing */ | ||
702 | #define QLA_TGT_STATE_NEED_DATA 1 /* target needs data to continue */ | ||
703 | #define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */ | ||
704 | #define QLA_TGT_STATE_PROCESSED 3 /* target done processing */ | ||
705 | #define QLA_TGT_STATE_ABORTED 4 /* Command aborted */ | ||
706 | |||
707 | /* Special handles */ | ||
708 | #define QLA_TGT_NULL_HANDLE 0 | ||
709 | #define QLA_TGT_SKIP_HANDLE (0xFFFFFFFF & ~CTIO_COMPLETION_HANDLE_MARK) | ||
710 | |||
711 | /* ATIO task_codes field */ | ||
712 | #define ATIO_SIMPLE_QUEUE 0 | ||
713 | #define ATIO_HEAD_OF_QUEUE 1 | ||
714 | #define ATIO_ORDERED_QUEUE 2 | ||
715 | #define ATIO_ACA_QUEUE 4 | ||
716 | #define ATIO_UNTAGGED 5 | ||
717 | |||
718 | /* TM failed response codes, see FCP (9.4.11 FCP_RSP_INFO) */ | ||
719 | #define FC_TM_SUCCESS 0 | ||
720 | #define FC_TM_BAD_FCP_DATA 1 | ||
721 | #define FC_TM_BAD_CMD 2 | ||
722 | #define FC_TM_FCP_DATA_MISMATCH 3 | ||
723 | #define FC_TM_REJECT 4 | ||
724 | #define FC_TM_FAILED 5 | ||
725 | |||
726 | /* | ||
727 | * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was | ||
728 | * terminated, so no more actions is needed and success should be returned | ||
729 | * to target. | ||
730 | */ | ||
731 | #define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717 | ||
732 | |||
733 | #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) | ||
734 | #define pci_dma_lo32(a) (a & 0xffffffff) | ||
735 | #define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) | ||
736 | #else | ||
737 | #define pci_dma_lo32(a) (a & 0xffffffff) | ||
738 | #define pci_dma_hi32(a) 0 | ||
739 | #endif | ||
740 | |||
741 | #define QLA_TGT_SENSE_VALID(sense) ((sense != NULL) && \ | ||
742 | (((const uint8_t *)(sense))[0] & 0x70) == 0x70) | ||
743 | |||
744 | struct qla_port_24xx_data { | ||
745 | uint8_t port_name[WWN_SIZE]; | ||
746 | uint16_t loop_id; | ||
747 | uint16_t reserved; | ||
748 | }; | ||
749 | |||
750 | struct qla_tgt { | ||
751 | struct scsi_qla_host *vha; | ||
752 | struct qla_hw_data *ha; | ||
753 | |||
754 | /* | ||
755 | * To sync between IRQ handlers and qlt_target_release(). Needed, | ||
756 | * because req_pkt() can drop/reaquire HW lock inside. Protected by | ||
757 | * HW lock. | ||
758 | */ | ||
759 | int irq_cmd_count; | ||
760 | |||
761 | int datasegs_per_cmd, datasegs_per_cont, sg_tablesize; | ||
762 | |||
763 | /* Target's flags, serialized by pha->hardware_lock */ | ||
764 | unsigned int tgt_enable_64bit_addr:1; /* 64-bits PCI addr enabled */ | ||
765 | unsigned int link_reinit_iocb_pending:1; | ||
766 | |||
767 | /* | ||
768 | * Protected by tgt_mutex AND hardware_lock for writing and tgt_mutex | ||
769 | * OR hardware_lock for reading. | ||
770 | */ | ||
771 | int tgt_stop; /* the target mode driver is being stopped */ | ||
772 | int tgt_stopped; /* the target mode driver has been stopped */ | ||
773 | |||
774 | /* Count of sessions refering qla_tgt. Protected by hardware_lock. */ | ||
775 | int sess_count; | ||
776 | |||
777 | /* Protected by hardware_lock. Addition also protected by tgt_mutex. */ | ||
778 | struct list_head sess_list; | ||
779 | |||
780 | /* Protected by hardware_lock */ | ||
781 | struct list_head del_sess_list; | ||
782 | struct delayed_work sess_del_work; | ||
783 | |||
784 | spinlock_t sess_work_lock; | ||
785 | struct list_head sess_works_list; | ||
786 | struct work_struct sess_work; | ||
787 | |||
788 | struct imm_ntfy_from_isp link_reinit_iocb; | ||
789 | wait_queue_head_t waitQ; | ||
790 | int notify_ack_expected; | ||
791 | int abts_resp_expected; | ||
792 | int modify_lun_expected; | ||
793 | |||
794 | int ctio_srr_id; | ||
795 | int imm_srr_id; | ||
796 | spinlock_t srr_lock; | ||
797 | struct list_head srr_ctio_list; | ||
798 | struct list_head srr_imm_list; | ||
799 | struct work_struct srr_work; | ||
800 | |||
801 | atomic_t tgt_global_resets_count; | ||
802 | |||
803 | struct list_head tgt_list_entry; | ||
804 | }; | ||
805 | |||
806 | /* | ||
807 | * Equivilant to IT Nexus (Initiator-Target) | ||
808 | */ | ||
809 | struct qla_tgt_sess { | ||
810 | uint16_t loop_id; | ||
811 | port_id_t s_id; | ||
812 | |||
813 | unsigned int conf_compl_supported:1; | ||
814 | unsigned int deleted:1; | ||
815 | unsigned int local:1; | ||
816 | unsigned int tearing_down:1; | ||
817 | |||
818 | struct se_session *se_sess; | ||
819 | struct scsi_qla_host *vha; | ||
820 | struct qla_tgt *tgt; | ||
821 | |||
822 | struct list_head sess_list_entry; | ||
823 | unsigned long expires; | ||
824 | struct list_head del_list_entry; | ||
825 | |||
826 | uint8_t port_name[WWN_SIZE]; | ||
827 | struct work_struct free_work; | ||
828 | }; | ||
829 | |||
830 | struct qla_tgt_cmd { | ||
831 | struct qla_tgt_sess *sess; | ||
832 | int state; | ||
833 | struct se_cmd se_cmd; | ||
834 | struct work_struct free_work; | ||
835 | struct work_struct work; | ||
836 | /* Sense buffer that will be mapped into outgoing status */ | ||
837 | unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; | ||
838 | |||
839 | /* to save extra sess dereferences */ | ||
840 | unsigned int conf_compl_supported:1; | ||
841 | unsigned int sg_mapped:1; | ||
842 | unsigned int free_sg:1; | ||
843 | unsigned int aborted:1; /* Needed in case of SRR */ | ||
844 | unsigned int write_data_transferred:1; | ||
845 | |||
846 | struct scatterlist *sg; /* cmd data buffer SG vector */ | ||
847 | int sg_cnt; /* SG segments count */ | ||
848 | int bufflen; /* cmd buffer length */ | ||
849 | int offset; | ||
850 | uint32_t tag; | ||
851 | uint32_t unpacked_lun; | ||
852 | enum dma_data_direction dma_data_direction; | ||
853 | |||
854 | uint16_t loop_id; /* to save extra sess dereferences */ | ||
855 | struct qla_tgt *tgt; /* to save extra sess dereferences */ | ||
856 | struct scsi_qla_host *vha; | ||
857 | struct list_head cmd_list; | ||
858 | |||
859 | struct atio_from_isp atio; | ||
860 | }; | ||
861 | |||
862 | struct qla_tgt_sess_work_param { | ||
863 | struct list_head sess_works_list_entry; | ||
864 | |||
865 | #define QLA_TGT_SESS_WORK_ABORT 1 | ||
866 | #define QLA_TGT_SESS_WORK_TM 2 | ||
867 | int type; | ||
868 | |||
869 | union { | ||
870 | struct abts_recv_from_24xx abts; | ||
871 | struct imm_ntfy_from_isp tm_iocb; | ||
872 | struct atio_from_isp tm_iocb2; | ||
873 | }; | ||
874 | }; | ||
875 | |||
876 | struct qla_tgt_mgmt_cmd { | ||
877 | uint8_t tmr_func; | ||
878 | uint8_t fc_tm_rsp; | ||
879 | struct qla_tgt_sess *sess; | ||
880 | struct se_cmd se_cmd; | ||
881 | struct work_struct free_work; | ||
882 | unsigned int flags; | ||
883 | #define QLA24XX_MGMT_SEND_NACK 1 | ||
884 | union { | ||
885 | struct atio_from_isp atio; | ||
886 | struct imm_ntfy_from_isp imm_ntfy; | ||
887 | struct abts_recv_from_24xx abts; | ||
888 | } __packed orig_iocb; | ||
889 | }; | ||
890 | |||
891 | struct qla_tgt_prm { | ||
892 | struct qla_tgt_cmd *cmd; | ||
893 | struct qla_tgt *tgt; | ||
894 | void *pkt; | ||
895 | struct scatterlist *sg; /* cmd data buffer SG vector */ | ||
896 | int seg_cnt; | ||
897 | int req_cnt; | ||
898 | uint16_t rq_result; | ||
899 | uint16_t scsi_status; | ||
900 | unsigned char *sense_buffer; | ||
901 | int sense_buffer_len; | ||
902 | int residual; | ||
903 | int add_status_pkt; | ||
904 | }; | ||
905 | |||
906 | struct qla_tgt_srr_imm { | ||
907 | struct list_head srr_list_entry; | ||
908 | int srr_id; | ||
909 | struct imm_ntfy_from_isp imm_ntfy; | ||
910 | }; | ||
911 | |||
912 | struct qla_tgt_srr_ctio { | ||
913 | struct list_head srr_list_entry; | ||
914 | int srr_id; | ||
915 | struct qla_tgt_cmd *cmd; | ||
916 | }; | ||
917 | |||
918 | #define QLA_TGT_XMIT_DATA 1 | ||
919 | #define QLA_TGT_XMIT_STATUS 2 | ||
920 | #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) | ||
921 | |||
922 | #include <linux/version.h> | ||
923 | |||
924 | extern struct qla_tgt_data qla_target; | ||
925 | /* | ||
926 | * Internal function prototypes | ||
927 | */ | ||
928 | void qlt_disable_vha(struct scsi_qla_host *); | ||
929 | |||
930 | /* | ||
931 | * Function prototypes for qla_target.c logic used by qla2xxx LLD code. | ||
932 | */ | ||
933 | extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); | ||
934 | extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); | ||
935 | extern int qlt_lport_register(struct qla_tgt_func_tmpl *, u64, | ||
936 | int (*callback)(struct scsi_qla_host *), void *); | ||
937 | extern void qlt_lport_deregister(struct scsi_qla_host *); | ||
938 | extern void qlt_unreg_sess(struct qla_tgt_sess *); | ||
939 | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); | ||
940 | extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *); | ||
941 | extern void qlt_set_mode(struct scsi_qla_host *ha); | ||
942 | extern void qlt_clear_mode(struct scsi_qla_host *ha); | ||
943 | extern int __init qlt_init(void); | ||
944 | extern void qlt_exit(void); | ||
945 | extern void qlt_update_vp_map(struct scsi_qla_host *, int); | ||
946 | |||
947 | /* | ||
948 | * This macro is used during early initializations when host->active_mode | ||
949 | * is not set. Right now, ha value is ignored. | ||
950 | */ | ||
951 | #define QLA_TGT_MODE_ENABLED() (ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED) | ||
952 | |||
953 | static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha) | ||
954 | { | ||
955 | return ha->host->active_mode & MODE_TARGET; | ||
956 | } | ||
957 | |||
958 | static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha) | ||
959 | { | ||
960 | return ha->host->active_mode & MODE_INITIATOR; | ||
961 | } | ||
962 | |||
963 | static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha) | ||
964 | { | ||
965 | if (ha->host->active_mode & MODE_INITIATOR) | ||
966 | ha->host->active_mode &= ~MODE_INITIATOR; | ||
967 | else | ||
968 | ha->host->active_mode |= MODE_INITIATOR; | ||
969 | } | ||
970 | |||
971 | /* | ||
972 | * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. | ||
973 | */ | ||
974 | extern void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *, | ||
975 | struct atio_from_isp *); | ||
976 | extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); | ||
977 | extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); | ||
978 | extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); | ||
979 | extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); | ||
980 | extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); | ||
981 | extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); | ||
982 | extern void qlt_ctio_completion(struct scsi_qla_host *, uint32_t); | ||
983 | extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *); | ||
984 | extern void qlt_enable_vha(struct scsi_qla_host *); | ||
985 | extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *); | ||
986 | extern void qlt_rff_id(struct scsi_qla_host *, struct ct_sns_req *); | ||
987 | extern void qlt_init_atio_q_entries(struct scsi_qla_host *); | ||
988 | extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *); | ||
989 | extern void qlt_24xx_config_rings(struct scsi_qla_host *, | ||
990 | device_reg_t __iomem *); | ||
991 | extern void qlt_24xx_config_nvram_stage1(struct scsi_qla_host *, | ||
992 | struct nvram_24xx *); | ||
993 | extern void qlt_24xx_config_nvram_stage2(struct scsi_qla_host *, | ||
994 | struct init_cb_24xx *); | ||
995 | extern int qlt_24xx_process_response_error(struct scsi_qla_host *, | ||
996 | struct sts_entry_24xx *); | ||
997 | extern void qlt_modify_vp_config(struct scsi_qla_host *, | ||
998 | struct vp_config_entry_24xx *); | ||
999 | extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *); | ||
1000 | extern int qlt_mem_alloc(struct qla_hw_data *); | ||
1001 | extern void qlt_mem_free(struct qla_hw_data *); | ||
1002 | extern void qlt_stop_phase1(struct qla_tgt *); | ||
1003 | extern void qlt_stop_phase2(struct qla_tgt *); | ||
1004 | |||
1005 | #endif /* __QLA_TARGET_H */ | ||
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c new file mode 100644 index 000000000000..436598f57404 --- /dev/null +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
@@ -0,0 +1,1955 @@ | |||
1 | /******************************************************************************* | ||
2 | * This file contains tcm implementation using v4 configfs fabric infrastructure | ||
3 | * for QLogic target mode HBAs | ||
4 | * | ||
5 | * ?? Copyright 2010-2011 RisingTide Systems LLC. | ||
6 | * | ||
7 | * Licensed to the Linux Foundation under the General Public License (GPL) | ||
8 | * version 2. | ||
9 | * | ||
10 | * Author: Nicholas A. Bellinger <nab@risingtidesystems.com> | ||
11 | * | ||
12 | * tcm_qla2xxx_parse_wwn() and tcm_qla2xxx_format_wwn() contains code from | ||
13 | * the TCM_FC / Open-FCoE.org fabric module. | ||
14 | * | ||
15 | * Copyright (c) 2010 Cisco Systems, Inc | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <generated/utsrelease.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/list.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/kthread.h> | ||
37 | #include <linux/types.h> | ||
38 | #include <linux/string.h> | ||
39 | #include <linux/configfs.h> | ||
40 | #include <linux/ctype.h> | ||
41 | #include <linux/string.h> | ||
42 | #include <linux/ctype.h> | ||
43 | #include <asm/unaligned.h> | ||
44 | #include <scsi/scsi.h> | ||
45 | #include <scsi/scsi_host.h> | ||
46 | #include <scsi/scsi_device.h> | ||
47 | #include <scsi/scsi_cmnd.h> | ||
48 | #include <target/target_core_base.h> | ||
49 | #include <target/target_core_fabric.h> | ||
50 | #include <target/target_core_fabric_configfs.h> | ||
51 | #include <target/target_core_configfs.h> | ||
52 | #include <target/configfs_macros.h> | ||
53 | |||
54 | #include "qla_def.h" | ||
55 | #include "qla_target.h" | ||
56 | #include "tcm_qla2xxx.h" | ||
57 | |||
58 | struct workqueue_struct *tcm_qla2xxx_free_wq; | ||
59 | struct workqueue_struct *tcm_qla2xxx_cmd_wq; | ||
60 | |||
61 | static int tcm_qla2xxx_check_true(struct se_portal_group *se_tpg) | ||
62 | { | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | static int tcm_qla2xxx_check_false(struct se_portal_group *se_tpg) | ||
67 | { | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Parse WWN. | ||
73 | * If strict, we require lower-case hex and colon separators to be sure | ||
74 | * the name is the same as what would be generated by ft_format_wwn() | ||
75 | * so the name and wwn are mapped one-to-one. | ||
76 | */ | ||
77 | static ssize_t tcm_qla2xxx_parse_wwn(const char *name, u64 *wwn, int strict) | ||
78 | { | ||
79 | const char *cp; | ||
80 | char c; | ||
81 | u32 nibble; | ||
82 | u32 byte = 0; | ||
83 | u32 pos = 0; | ||
84 | u32 err; | ||
85 | |||
86 | *wwn = 0; | ||
87 | for (cp = name; cp < &name[TCM_QLA2XXX_NAMELEN - 1]; cp++) { | ||
88 | c = *cp; | ||
89 | if (c == '\n' && cp[1] == '\0') | ||
90 | continue; | ||
91 | if (strict && pos++ == 2 && byte++ < 7) { | ||
92 | pos = 0; | ||
93 | if (c == ':') | ||
94 | continue; | ||
95 | err = 1; | ||
96 | goto fail; | ||
97 | } | ||
98 | if (c == '\0') { | ||
99 | err = 2; | ||
100 | if (strict && byte != 8) | ||
101 | goto fail; | ||
102 | return cp - name; | ||
103 | } | ||
104 | err = 3; | ||
105 | if (isdigit(c)) | ||
106 | nibble = c - '0'; | ||
107 | else if (isxdigit(c) && (islower(c) || !strict)) | ||
108 | nibble = tolower(c) - 'a' + 10; | ||
109 | else | ||
110 | goto fail; | ||
111 | *wwn = (*wwn << 4) | nibble; | ||
112 | } | ||
113 | err = 4; | ||
114 | fail: | ||
115 | pr_debug("err %u len %zu pos %u byte %u\n", | ||
116 | err, cp - name, pos, byte); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | static ssize_t tcm_qla2xxx_format_wwn(char *buf, size_t len, u64 wwn) | ||
121 | { | ||
122 | u8 b[8]; | ||
123 | |||
124 | put_unaligned_be64(wwn, b); | ||
125 | return snprintf(buf, len, | ||
126 | "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", | ||
127 | b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); | ||
128 | } | ||
129 | |||
130 | static char *tcm_qla2xxx_get_fabric_name(void) | ||
131 | { | ||
132 | return "qla2xxx"; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * From drivers/scsi/scsi_transport_fc.c:fc_parse_wwn | ||
137 | */ | ||
138 | static int tcm_qla2xxx_npiv_extract_wwn(const char *ns, u64 *nm) | ||
139 | { | ||
140 | unsigned int i, j, value; | ||
141 | u8 wwn[8]; | ||
142 | |||
143 | memset(wwn, 0, sizeof(wwn)); | ||
144 | |||
145 | /* Validate and store the new name */ | ||
146 | for (i = 0, j = 0; i < 16; i++) { | ||
147 | value = hex_to_bin(*ns++); | ||
148 | if (value >= 0) | ||
149 | j = (j << 4) | value; | ||
150 | else | ||
151 | return -EINVAL; | ||
152 | |||
153 | if (i % 2) { | ||
154 | wwn[i/2] = j & 0xff; | ||
155 | j = 0; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | *nm = wwn_to_u64(wwn); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * This parsing logic follows drivers/scsi/scsi_transport_fc.c: | ||
165 | * store_fc_host_vport_create() | ||
166 | */ | ||
167 | static int tcm_qla2xxx_npiv_parse_wwn( | ||
168 | const char *name, | ||
169 | size_t count, | ||
170 | u64 *wwpn, | ||
171 | u64 *wwnn) | ||
172 | { | ||
173 | unsigned int cnt = count; | ||
174 | int rc; | ||
175 | |||
176 | *wwpn = 0; | ||
177 | *wwnn = 0; | ||
178 | |||
179 | /* count may include a LF at end of string */ | ||
180 | if (name[cnt-1] == '\n') | ||
181 | cnt--; | ||
182 | |||
183 | /* validate we have enough characters for WWPN */ | ||
184 | if ((cnt != (16+1+16)) || (name[16] != ':')) | ||
185 | return -EINVAL; | ||
186 | |||
187 | rc = tcm_qla2xxx_npiv_extract_wwn(&name[0], wwpn); | ||
188 | if (rc != 0) | ||
189 | return rc; | ||
190 | |||
191 | rc = tcm_qla2xxx_npiv_extract_wwn(&name[17], wwnn); | ||
192 | if (rc != 0) | ||
193 | return rc; | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static ssize_t tcm_qla2xxx_npiv_format_wwn(char *buf, size_t len, | ||
199 | u64 wwpn, u64 wwnn) | ||
200 | { | ||
201 | u8 b[8], b2[8]; | ||
202 | |||
203 | put_unaligned_be64(wwpn, b); | ||
204 | put_unaligned_be64(wwnn, b2); | ||
205 | return snprintf(buf, len, | ||
206 | "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x," | ||
207 | "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", | ||
208 | b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], | ||
209 | b2[0], b2[1], b2[2], b2[3], b2[4], b2[5], b2[6], b2[7]); | ||
210 | } | ||
211 | |||
212 | static char *tcm_qla2xxx_npiv_get_fabric_name(void) | ||
213 | { | ||
214 | return "qla2xxx_npiv"; | ||
215 | } | ||
216 | |||
217 | static u8 tcm_qla2xxx_get_fabric_proto_ident(struct se_portal_group *se_tpg) | ||
218 | { | ||
219 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
220 | struct tcm_qla2xxx_tpg, se_tpg); | ||
221 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
222 | u8 proto_id; | ||
223 | |||
224 | switch (lport->lport_proto_id) { | ||
225 | case SCSI_PROTOCOL_FCP: | ||
226 | default: | ||
227 | proto_id = fc_get_fabric_proto_ident(se_tpg); | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | return proto_id; | ||
232 | } | ||
233 | |||
234 | static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) | ||
235 | { | ||
236 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
237 | struct tcm_qla2xxx_tpg, se_tpg); | ||
238 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
239 | |||
240 | return &lport->lport_name[0]; | ||
241 | } | ||
242 | |||
243 | static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) | ||
244 | { | ||
245 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
246 | struct tcm_qla2xxx_tpg, se_tpg); | ||
247 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
248 | |||
249 | return &lport->lport_npiv_name[0]; | ||
250 | } | ||
251 | |||
252 | static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg) | ||
253 | { | ||
254 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
255 | struct tcm_qla2xxx_tpg, se_tpg); | ||
256 | return tpg->lport_tpgt; | ||
257 | } | ||
258 | |||
259 | static u32 tcm_qla2xxx_get_default_depth(struct se_portal_group *se_tpg) | ||
260 | { | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | static u32 tcm_qla2xxx_get_pr_transport_id( | ||
265 | struct se_portal_group *se_tpg, | ||
266 | struct se_node_acl *se_nacl, | ||
267 | struct t10_pr_registration *pr_reg, | ||
268 | int *format_code, | ||
269 | unsigned char *buf) | ||
270 | { | ||
271 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
272 | struct tcm_qla2xxx_tpg, se_tpg); | ||
273 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
274 | int ret = 0; | ||
275 | |||
276 | switch (lport->lport_proto_id) { | ||
277 | case SCSI_PROTOCOL_FCP: | ||
278 | default: | ||
279 | ret = fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg, | ||
280 | format_code, buf); | ||
281 | break; | ||
282 | } | ||
283 | |||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static u32 tcm_qla2xxx_get_pr_transport_id_len( | ||
288 | struct se_portal_group *se_tpg, | ||
289 | struct se_node_acl *se_nacl, | ||
290 | struct t10_pr_registration *pr_reg, | ||
291 | int *format_code) | ||
292 | { | ||
293 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
294 | struct tcm_qla2xxx_tpg, se_tpg); | ||
295 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
296 | int ret = 0; | ||
297 | |||
298 | switch (lport->lport_proto_id) { | ||
299 | case SCSI_PROTOCOL_FCP: | ||
300 | default: | ||
301 | ret = fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, | ||
302 | format_code); | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | static char *tcm_qla2xxx_parse_pr_out_transport_id( | ||
310 | struct se_portal_group *se_tpg, | ||
311 | const char *buf, | ||
312 | u32 *out_tid_len, | ||
313 | char **port_nexus_ptr) | ||
314 | { | ||
315 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
316 | struct tcm_qla2xxx_tpg, se_tpg); | ||
317 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
318 | char *tid = NULL; | ||
319 | |||
320 | switch (lport->lport_proto_id) { | ||
321 | case SCSI_PROTOCOL_FCP: | ||
322 | default: | ||
323 | tid = fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, | ||
324 | port_nexus_ptr); | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | return tid; | ||
329 | } | ||
330 | |||
331 | static int tcm_qla2xxx_check_demo_mode(struct se_portal_group *se_tpg) | ||
332 | { | ||
333 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
334 | struct tcm_qla2xxx_tpg, se_tpg); | ||
335 | |||
336 | return QLA_TPG_ATTRIB(tpg)->generate_node_acls; | ||
337 | } | ||
338 | |||
339 | static int tcm_qla2xxx_check_demo_mode_cache(struct se_portal_group *se_tpg) | ||
340 | { | ||
341 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
342 | struct tcm_qla2xxx_tpg, se_tpg); | ||
343 | |||
344 | return QLA_TPG_ATTRIB(tpg)->cache_dynamic_acls; | ||
345 | } | ||
346 | |||
347 | static int tcm_qla2xxx_check_demo_write_protect(struct se_portal_group *se_tpg) | ||
348 | { | ||
349 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
350 | struct tcm_qla2xxx_tpg, se_tpg); | ||
351 | |||
352 | return QLA_TPG_ATTRIB(tpg)->demo_mode_write_protect; | ||
353 | } | ||
354 | |||
355 | static int tcm_qla2xxx_check_prod_write_protect(struct se_portal_group *se_tpg) | ||
356 | { | ||
357 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
358 | struct tcm_qla2xxx_tpg, se_tpg); | ||
359 | |||
360 | return QLA_TPG_ATTRIB(tpg)->prod_mode_write_protect; | ||
361 | } | ||
362 | |||
363 | static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl( | ||
364 | struct se_portal_group *se_tpg) | ||
365 | { | ||
366 | struct tcm_qla2xxx_nacl *nacl; | ||
367 | |||
368 | nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL); | ||
369 | if (!nacl) { | ||
370 | pr_err("Unable to alocate struct tcm_qla2xxx_nacl\n"); | ||
371 | return NULL; | ||
372 | } | ||
373 | |||
374 | return &nacl->se_node_acl; | ||
375 | } | ||
376 | |||
377 | static void tcm_qla2xxx_release_fabric_acl( | ||
378 | struct se_portal_group *se_tpg, | ||
379 | struct se_node_acl *se_nacl) | ||
380 | { | ||
381 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, | ||
382 | struct tcm_qla2xxx_nacl, se_node_acl); | ||
383 | kfree(nacl); | ||
384 | } | ||
385 | |||
386 | static u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *se_tpg) | ||
387 | { | ||
388 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
389 | struct tcm_qla2xxx_tpg, se_tpg); | ||
390 | |||
391 | return tpg->lport_tpgt; | ||
392 | } | ||
393 | |||
394 | static void tcm_qla2xxx_complete_mcmd(struct work_struct *work) | ||
395 | { | ||
396 | struct qla_tgt_mgmt_cmd *mcmd = container_of(work, | ||
397 | struct qla_tgt_mgmt_cmd, free_work); | ||
398 | |||
399 | transport_generic_free_cmd(&mcmd->se_cmd, 0); | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Called from qla_target_template->free_mcmd(), and will call | ||
404 | * tcm_qla2xxx_release_cmd() via normal struct target_core_fabric_ops | ||
405 | * release callback. qla_hw_data->hardware_lock is expected to be held | ||
406 | */ | ||
407 | static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) | ||
408 | { | ||
409 | INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd); | ||
410 | queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work); | ||
411 | } | ||
412 | |||
413 | static void tcm_qla2xxx_complete_free(struct work_struct *work) | ||
414 | { | ||
415 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); | ||
416 | |||
417 | transport_generic_free_cmd(&cmd->se_cmd, 0); | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * Called from qla_target_template->free_cmd(), and will call | ||
422 | * tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops | ||
423 | * release callback. qla_hw_data->hardware_lock is expected to be held | ||
424 | */ | ||
425 | static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) | ||
426 | { | ||
427 | INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free); | ||
428 | queue_work(tcm_qla2xxx_free_wq, &cmd->work); | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Called from struct target_core_fabric_ops->check_stop_free() context | ||
433 | */ | ||
434 | static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) | ||
435 | { | ||
436 | return target_put_sess_cmd(se_cmd->se_sess, se_cmd); | ||
437 | } | ||
438 | |||
439 | /* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying | ||
440 | * fabric descriptor @se_cmd command to release | ||
441 | */ | ||
442 | static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) | ||
443 | { | ||
444 | struct qla_tgt_cmd *cmd; | ||
445 | |||
446 | if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { | ||
447 | struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd, | ||
448 | struct qla_tgt_mgmt_cmd, se_cmd); | ||
449 | qlt_free_mcmd(mcmd); | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); | ||
454 | qlt_free_cmd(cmd); | ||
455 | } | ||
456 | |||
457 | static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess) | ||
458 | { | ||
459 | struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; | ||
460 | struct scsi_qla_host *vha; | ||
461 | unsigned long flags; | ||
462 | |||
463 | BUG_ON(!sess); | ||
464 | vha = sess->vha; | ||
465 | |||
466 | spin_lock_irqsave(&vha->hw->hardware_lock, flags); | ||
467 | sess->tearing_down = 1; | ||
468 | target_splice_sess_cmd_list(se_sess); | ||
469 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
470 | |||
471 | return 1; | ||
472 | } | ||
473 | |||
474 | static void tcm_qla2xxx_close_session(struct se_session *se_sess) | ||
475 | { | ||
476 | struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; | ||
477 | struct scsi_qla_host *vha; | ||
478 | unsigned long flags; | ||
479 | |||
480 | BUG_ON(!sess); | ||
481 | vha = sess->vha; | ||
482 | |||
483 | spin_lock_irqsave(&vha->hw->hardware_lock, flags); | ||
484 | qlt_unreg_sess(sess); | ||
485 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
486 | } | ||
487 | |||
488 | static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess) | ||
489 | { | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * The LIO target core uses DMA_TO_DEVICE to mean that data is going | ||
495 | * to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean | ||
496 | * that data is coming from the target (eg handling a READ). However, | ||
497 | * this is just the opposite of what we have to tell the DMA mapping | ||
498 | * layer -- eg when handling a READ, the HBA will have to DMA the data | ||
499 | * out of memory so it can send it to the initiator, which means we | ||
500 | * need to use DMA_TO_DEVICE when we map the data. | ||
501 | */ | ||
502 | static enum dma_data_direction tcm_qla2xxx_mapping_dir(struct se_cmd *se_cmd) | ||
503 | { | ||
504 | if (se_cmd->se_cmd_flags & SCF_BIDI) | ||
505 | return DMA_BIDIRECTIONAL; | ||
506 | |||
507 | switch (se_cmd->data_direction) { | ||
508 | case DMA_TO_DEVICE: | ||
509 | return DMA_FROM_DEVICE; | ||
510 | case DMA_FROM_DEVICE: | ||
511 | return DMA_TO_DEVICE; | ||
512 | case DMA_NONE: | ||
513 | default: | ||
514 | return DMA_NONE; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) | ||
519 | { | ||
520 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | ||
521 | struct qla_tgt_cmd, se_cmd); | ||
522 | |||
523 | cmd->bufflen = se_cmd->data_length; | ||
524 | cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd); | ||
525 | |||
526 | cmd->sg_cnt = se_cmd->t_data_nents; | ||
527 | cmd->sg = se_cmd->t_data_sg; | ||
528 | |||
529 | /* | ||
530 | * qla_target.c:qlt_rdy_to_xfer() will call pci_map_sg() to setup | ||
531 | * the SGL mappings into PCIe memory for incoming FCP WRITE data. | ||
532 | */ | ||
533 | return qlt_rdy_to_xfer(cmd); | ||
534 | } | ||
535 | |||
536 | static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) | ||
537 | { | ||
538 | unsigned long flags; | ||
539 | /* | ||
540 | * Check for WRITE_PENDING status to determine if we need to wait for | ||
541 | * CTIO aborts to be posted via hardware in tcm_qla2xxx_handle_data(). | ||
542 | */ | ||
543 | spin_lock_irqsave(&se_cmd->t_state_lock, flags); | ||
544 | if (se_cmd->t_state == TRANSPORT_WRITE_PENDING || | ||
545 | se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { | ||
546 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | ||
547 | wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, | ||
548 | 3000); | ||
549 | return 0; | ||
550 | } | ||
551 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl) | ||
557 | { | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | static u32 tcm_qla2xxx_get_task_tag(struct se_cmd *se_cmd) | ||
562 | { | ||
563 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | ||
564 | struct qla_tgt_cmd, se_cmd); | ||
565 | |||
566 | return cmd->tag; | ||
567 | } | ||
568 | |||
569 | static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) | ||
570 | { | ||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | /* | ||
575 | * Called from process context in qla_target.c:qlt_do_work() code | ||
576 | */ | ||
577 | static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, | ||
578 | unsigned char *cdb, uint32_t data_length, int fcp_task_attr, | ||
579 | int data_dir, int bidi) | ||
580 | { | ||
581 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
582 | struct se_session *se_sess; | ||
583 | struct qla_tgt_sess *sess; | ||
584 | int flags = TARGET_SCF_ACK_KREF; | ||
585 | |||
586 | if (bidi) | ||
587 | flags |= TARGET_SCF_BIDI_OP; | ||
588 | |||
589 | sess = cmd->sess; | ||
590 | if (!sess) { | ||
591 | pr_err("Unable to locate struct qla_tgt_sess from qla_tgt_cmd\n"); | ||
592 | return -EINVAL; | ||
593 | } | ||
594 | |||
595 | se_sess = sess->se_sess; | ||
596 | if (!se_sess) { | ||
597 | pr_err("Unable to locate active struct se_session\n"); | ||
598 | return -EINVAL; | ||
599 | } | ||
600 | |||
601 | target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0], | ||
602 | cmd->unpacked_lun, data_length, fcp_task_attr, | ||
603 | data_dir, flags); | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static void tcm_qla2xxx_do_rsp(struct work_struct *work) | ||
608 | { | ||
609 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); | ||
610 | /* | ||
611 | * Dispatch ->queue_status from workqueue process context | ||
612 | */ | ||
613 | transport_generic_request_failure(&cmd->se_cmd); | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * Called from qla_target.c:qlt_do_ctio_completion() | ||
618 | */ | ||
619 | static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd) | ||
620 | { | ||
621 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
622 | unsigned long flags; | ||
623 | /* | ||
624 | * Ensure that the complete FCP WRITE payload has been received. | ||
625 | * Otherwise return an exception via CHECK_CONDITION status. | ||
626 | */ | ||
627 | if (!cmd->write_data_transferred) { | ||
628 | /* | ||
629 | * Check if se_cmd has already been aborted via LUN_RESET, and | ||
630 | * waiting upon completion in tcm_qla2xxx_write_pending_status() | ||
631 | */ | ||
632 | spin_lock_irqsave(&se_cmd->t_state_lock, flags); | ||
633 | if (se_cmd->transport_state & CMD_T_ABORTED) { | ||
634 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | ||
635 | complete(&se_cmd->t_transport_stop_comp); | ||
636 | return 0; | ||
637 | } | ||
638 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | ||
639 | |||
640 | se_cmd->scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; | ||
641 | INIT_WORK(&cmd->work, tcm_qla2xxx_do_rsp); | ||
642 | queue_work(tcm_qla2xxx_free_wq, &cmd->work); | ||
643 | return 0; | ||
644 | } | ||
645 | /* | ||
646 | * We now tell TCM to queue this WRITE CDB with TRANSPORT_PROCESS_WRITE | ||
647 | * status to the backstore processing thread. | ||
648 | */ | ||
649 | return transport_generic_handle_data(&cmd->se_cmd); | ||
650 | } | ||
651 | |||
652 | /* | ||
653 | * Called from qla_target.c:qlt_issue_task_mgmt() | ||
654 | */ | ||
655 | int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, uint32_t lun, | ||
656 | uint8_t tmr_func, uint32_t tag) | ||
657 | { | ||
658 | struct qla_tgt_sess *sess = mcmd->sess; | ||
659 | struct se_cmd *se_cmd = &mcmd->se_cmd; | ||
660 | |||
661 | return target_submit_tmr(se_cmd, sess->se_sess, NULL, lun, mcmd, | ||
662 | tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF); | ||
663 | } | ||
664 | |||
665 | static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) | ||
666 | { | ||
667 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | ||
668 | struct qla_tgt_cmd, se_cmd); | ||
669 | |||
670 | cmd->bufflen = se_cmd->data_length; | ||
671 | cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd); | ||
672 | cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); | ||
673 | |||
674 | cmd->sg_cnt = se_cmd->t_data_nents; | ||
675 | cmd->sg = se_cmd->t_data_sg; | ||
676 | cmd->offset = 0; | ||
677 | |||
678 | /* | ||
679 | * Now queue completed DATA_IN the qla2xxx LLD and response ring | ||
680 | */ | ||
681 | return qlt_xmit_response(cmd, QLA_TGT_XMIT_DATA|QLA_TGT_XMIT_STATUS, | ||
682 | se_cmd->scsi_status); | ||
683 | } | ||
684 | |||
685 | static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) | ||
686 | { | ||
687 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | ||
688 | struct qla_tgt_cmd, se_cmd); | ||
689 | int xmit_type = QLA_TGT_XMIT_STATUS; | ||
690 | |||
691 | cmd->bufflen = se_cmd->data_length; | ||
692 | cmd->sg = NULL; | ||
693 | cmd->sg_cnt = 0; | ||
694 | cmd->offset = 0; | ||
695 | cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd); | ||
696 | cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); | ||
697 | |||
698 | if (se_cmd->data_direction == DMA_FROM_DEVICE) { | ||
699 | /* | ||
700 | * For FCP_READ with CHECK_CONDITION status, clear cmd->bufflen | ||
701 | * for qla_tgt_xmit_response LLD code | ||
702 | */ | ||
703 | se_cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; | ||
704 | se_cmd->residual_count = se_cmd->data_length; | ||
705 | |||
706 | cmd->bufflen = 0; | ||
707 | } | ||
708 | /* | ||
709 | * Now queue status response to qla2xxx LLD code and response ring | ||
710 | */ | ||
711 | return qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status); | ||
712 | } | ||
713 | |||
714 | static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) | ||
715 | { | ||
716 | struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; | ||
717 | struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd, | ||
718 | struct qla_tgt_mgmt_cmd, se_cmd); | ||
719 | |||
720 | pr_debug("queue_tm_rsp: mcmd: %p func: 0x%02x response: 0x%02x\n", | ||
721 | mcmd, se_tmr->function, se_tmr->response); | ||
722 | /* | ||
723 | * Do translation between TCM TM response codes and | ||
724 | * QLA2xxx FC TM response codes. | ||
725 | */ | ||
726 | switch (se_tmr->response) { | ||
727 | case TMR_FUNCTION_COMPLETE: | ||
728 | mcmd->fc_tm_rsp = FC_TM_SUCCESS; | ||
729 | break; | ||
730 | case TMR_TASK_DOES_NOT_EXIST: | ||
731 | mcmd->fc_tm_rsp = FC_TM_BAD_CMD; | ||
732 | break; | ||
733 | case TMR_FUNCTION_REJECTED: | ||
734 | mcmd->fc_tm_rsp = FC_TM_REJECT; | ||
735 | break; | ||
736 | case TMR_LUN_DOES_NOT_EXIST: | ||
737 | default: | ||
738 | mcmd->fc_tm_rsp = FC_TM_FAILED; | ||
739 | break; | ||
740 | } | ||
741 | /* | ||
742 | * Queue the TM response to QLA2xxx LLD to build a | ||
743 | * CTIO response packet. | ||
744 | */ | ||
745 | qlt_xmit_tm_rsp(mcmd); | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static u16 tcm_qla2xxx_get_fabric_sense_len(void) | ||
751 | { | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static u16 tcm_qla2xxx_set_fabric_sense_len(struct se_cmd *se_cmd, | ||
756 | u32 sense_length) | ||
757 | { | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | /* Local pointer to allocated TCM configfs fabric module */ | ||
762 | struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs; | ||
763 | struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs; | ||
764 | |||
765 | static int tcm_qla2xxx_setup_nacl_from_rport( | ||
766 | struct se_portal_group *se_tpg, | ||
767 | struct se_node_acl *se_nacl, | ||
768 | struct tcm_qla2xxx_lport *lport, | ||
769 | struct tcm_qla2xxx_nacl *nacl, | ||
770 | u64 rport_wwnn) | ||
771 | { | ||
772 | struct scsi_qla_host *vha = lport->qla_vha; | ||
773 | struct Scsi_Host *sh = vha->host; | ||
774 | struct fc_host_attrs *fc_host = shost_to_fc_host(sh); | ||
775 | struct fc_rport *rport; | ||
776 | unsigned long flags; | ||
777 | void *node; | ||
778 | int rc; | ||
779 | |||
780 | /* | ||
781 | * Scan the existing rports, and create a session for the | ||
782 | * explict NodeACL is an matching rport->node_name already | ||
783 | * exists. | ||
784 | */ | ||
785 | spin_lock_irqsave(sh->host_lock, flags); | ||
786 | list_for_each_entry(rport, &fc_host->rports, peers) { | ||
787 | if (rport_wwnn != rport->node_name) | ||
788 | continue; | ||
789 | |||
790 | pr_debug("Located existing rport_wwpn and rport->node_name: 0x%016LX, port_id: 0x%04x\n", | ||
791 | rport->node_name, rport->port_id); | ||
792 | nacl->nport_id = rport->port_id; | ||
793 | |||
794 | spin_unlock_irqrestore(sh->host_lock, flags); | ||
795 | |||
796 | spin_lock_irqsave(&vha->hw->hardware_lock, flags); | ||
797 | node = btree_lookup32(&lport->lport_fcport_map, rport->port_id); | ||
798 | if (node) { | ||
799 | rc = btree_update32(&lport->lport_fcport_map, | ||
800 | rport->port_id, se_nacl); | ||
801 | } else { | ||
802 | rc = btree_insert32(&lport->lport_fcport_map, | ||
803 | rport->port_id, se_nacl, | ||
804 | GFP_ATOMIC); | ||
805 | } | ||
806 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
807 | |||
808 | if (rc) { | ||
809 | pr_err("Unable to insert se_nacl into fcport_map"); | ||
810 | WARN_ON(rc > 0); | ||
811 | return rc; | ||
812 | } | ||
813 | |||
814 | pr_debug("Inserted into fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%08x\n", | ||
815 | se_nacl, rport_wwnn, nacl->nport_id); | ||
816 | |||
817 | return 1; | ||
818 | } | ||
819 | spin_unlock_irqrestore(sh->host_lock, flags); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * Expected to be called with struct qla_hw_data->hardware_lock held | ||
826 | */ | ||
827 | static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) | ||
828 | { | ||
829 | struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; | ||
830 | struct se_portal_group *se_tpg = se_nacl->se_tpg; | ||
831 | struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; | ||
832 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, | ||
833 | struct tcm_qla2xxx_lport, lport_wwn); | ||
834 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, | ||
835 | struct tcm_qla2xxx_nacl, se_node_acl); | ||
836 | void *node; | ||
837 | |||
838 | pr_debug("fc_rport domain: port_id 0x%06x\n", nacl->nport_id); | ||
839 | |||
840 | node = btree_remove32(&lport->lport_fcport_map, nacl->nport_id); | ||
841 | WARN_ON(node && (node != se_nacl)); | ||
842 | |||
843 | pr_debug("Removed from fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%06x\n", | ||
844 | se_nacl, nacl->nport_wwnn, nacl->nport_id); | ||
845 | } | ||
846 | |||
847 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) | ||
848 | { | ||
849 | target_put_session(sess->se_sess); | ||
850 | } | ||
851 | |||
852 | static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) | ||
853 | { | ||
854 | tcm_qla2xxx_shutdown_session(sess->se_sess); | ||
855 | } | ||
856 | |||
857 | static struct se_node_acl *tcm_qla2xxx_make_nodeacl( | ||
858 | struct se_portal_group *se_tpg, | ||
859 | struct config_group *group, | ||
860 | const char *name) | ||
861 | { | ||
862 | struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; | ||
863 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, | ||
864 | struct tcm_qla2xxx_lport, lport_wwn); | ||
865 | struct se_node_acl *se_nacl, *se_nacl_new; | ||
866 | struct tcm_qla2xxx_nacl *nacl; | ||
867 | u64 wwnn; | ||
868 | u32 qla2xxx_nexus_depth; | ||
869 | int rc; | ||
870 | |||
871 | if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) | ||
872 | return ERR_PTR(-EINVAL); | ||
873 | |||
874 | se_nacl_new = tcm_qla2xxx_alloc_fabric_acl(se_tpg); | ||
875 | if (!se_nacl_new) | ||
876 | return ERR_PTR(-ENOMEM); | ||
877 | /* #warning FIXME: Hardcoded qla2xxx_nexus depth in tcm_qla2xxx_make_nodeacl */ | ||
878 | qla2xxx_nexus_depth = 1; | ||
879 | |||
880 | /* | ||
881 | * se_nacl_new may be released by core_tpg_add_initiator_node_acl() | ||
882 | * when converting a NodeACL from demo mode -> explict | ||
883 | */ | ||
884 | se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new, | ||
885 | name, qla2xxx_nexus_depth); | ||
886 | if (IS_ERR(se_nacl)) { | ||
887 | tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new); | ||
888 | return se_nacl; | ||
889 | } | ||
890 | /* | ||
891 | * Locate our struct tcm_qla2xxx_nacl and set the FC Nport WWPN | ||
892 | */ | ||
893 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
894 | nacl->nport_wwnn = wwnn; | ||
895 | tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); | ||
896 | /* | ||
897 | * Setup a se_nacl handle based on an a matching struct fc_rport setup | ||
898 | * via drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() | ||
899 | */ | ||
900 | rc = tcm_qla2xxx_setup_nacl_from_rport(se_tpg, se_nacl, lport, | ||
901 | nacl, wwnn); | ||
902 | if (rc < 0) { | ||
903 | tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new); | ||
904 | return ERR_PTR(rc); | ||
905 | } | ||
906 | |||
907 | return se_nacl; | ||
908 | } | ||
909 | |||
910 | static void tcm_qla2xxx_drop_nodeacl(struct se_node_acl *se_acl) | ||
911 | { | ||
912 | struct se_portal_group *se_tpg = se_acl->se_tpg; | ||
913 | struct tcm_qla2xxx_nacl *nacl = container_of(se_acl, | ||
914 | struct tcm_qla2xxx_nacl, se_node_acl); | ||
915 | |||
916 | core_tpg_del_initiator_node_acl(se_tpg, se_acl, 1); | ||
917 | kfree(nacl); | ||
918 | } | ||
919 | |||
920 | /* Start items for tcm_qla2xxx_tpg_attrib_cit */ | ||
921 | |||
922 | #define DEF_QLA_TPG_ATTRIB(name) \ | ||
923 | \ | ||
924 | static ssize_t tcm_qla2xxx_tpg_attrib_show_##name( \ | ||
925 | struct se_portal_group *se_tpg, \ | ||
926 | char *page) \ | ||
927 | { \ | ||
928 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \ | ||
929 | struct tcm_qla2xxx_tpg, se_tpg); \ | ||
930 | \ | ||
931 | return sprintf(page, "%u\n", QLA_TPG_ATTRIB(tpg)->name); \ | ||
932 | } \ | ||
933 | \ | ||
934 | static ssize_t tcm_qla2xxx_tpg_attrib_store_##name( \ | ||
935 | struct se_portal_group *se_tpg, \ | ||
936 | const char *page, \ | ||
937 | size_t count) \ | ||
938 | { \ | ||
939 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \ | ||
940 | struct tcm_qla2xxx_tpg, se_tpg); \ | ||
941 | unsigned long val; \ | ||
942 | int ret; \ | ||
943 | \ | ||
944 | ret = kstrtoul(page, 0, &val); \ | ||
945 | if (ret < 0) { \ | ||
946 | pr_err("kstrtoul() failed with" \ | ||
947 | " ret: %d\n", ret); \ | ||
948 | return -EINVAL; \ | ||
949 | } \ | ||
950 | ret = tcm_qla2xxx_set_attrib_##name(tpg, val); \ | ||
951 | \ | ||
952 | return (!ret) ? count : -EINVAL; \ | ||
953 | } | ||
954 | |||
955 | #define DEF_QLA_TPG_ATTR_BOOL(_name) \ | ||
956 | \ | ||
957 | static int tcm_qla2xxx_set_attrib_##_name( \ | ||
958 | struct tcm_qla2xxx_tpg *tpg, \ | ||
959 | unsigned long val) \ | ||
960 | { \ | ||
961 | struct tcm_qla2xxx_tpg_attrib *a = &tpg->tpg_attrib; \ | ||
962 | \ | ||
963 | if ((val != 0) && (val != 1)) { \ | ||
964 | pr_err("Illegal boolean value %lu\n", val); \ | ||
965 | return -EINVAL; \ | ||
966 | } \ | ||
967 | \ | ||
968 | a->_name = val; \ | ||
969 | return 0; \ | ||
970 | } | ||
971 | |||
972 | #define QLA_TPG_ATTR(_name, _mode) \ | ||
973 | TF_TPG_ATTRIB_ATTR(tcm_qla2xxx, _name, _mode); | ||
974 | |||
975 | /* | ||
976 | * Define tcm_qla2xxx_tpg_attrib_s_generate_node_acls | ||
977 | */ | ||
978 | DEF_QLA_TPG_ATTR_BOOL(generate_node_acls); | ||
979 | DEF_QLA_TPG_ATTRIB(generate_node_acls); | ||
980 | QLA_TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR); | ||
981 | |||
982 | /* | ||
983 | Define tcm_qla2xxx_attrib_s_cache_dynamic_acls | ||
984 | */ | ||
985 | DEF_QLA_TPG_ATTR_BOOL(cache_dynamic_acls); | ||
986 | DEF_QLA_TPG_ATTRIB(cache_dynamic_acls); | ||
987 | QLA_TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR); | ||
988 | |||
989 | /* | ||
990 | * Define tcm_qla2xxx_tpg_attrib_s_demo_mode_write_protect | ||
991 | */ | ||
992 | DEF_QLA_TPG_ATTR_BOOL(demo_mode_write_protect); | ||
993 | DEF_QLA_TPG_ATTRIB(demo_mode_write_protect); | ||
994 | QLA_TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR); | ||
995 | |||
996 | /* | ||
997 | * Define tcm_qla2xxx_tpg_attrib_s_prod_mode_write_protect | ||
998 | */ | ||
999 | DEF_QLA_TPG_ATTR_BOOL(prod_mode_write_protect); | ||
1000 | DEF_QLA_TPG_ATTRIB(prod_mode_write_protect); | ||
1001 | QLA_TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR); | ||
1002 | |||
1003 | static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = { | ||
1004 | &tcm_qla2xxx_tpg_attrib_generate_node_acls.attr, | ||
1005 | &tcm_qla2xxx_tpg_attrib_cache_dynamic_acls.attr, | ||
1006 | &tcm_qla2xxx_tpg_attrib_demo_mode_write_protect.attr, | ||
1007 | &tcm_qla2xxx_tpg_attrib_prod_mode_write_protect.attr, | ||
1008 | NULL, | ||
1009 | }; | ||
1010 | |||
1011 | /* End items for tcm_qla2xxx_tpg_attrib_cit */ | ||
1012 | |||
1013 | static ssize_t tcm_qla2xxx_tpg_show_enable( | ||
1014 | struct se_portal_group *se_tpg, | ||
1015 | char *page) | ||
1016 | { | ||
1017 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
1018 | struct tcm_qla2xxx_tpg, se_tpg); | ||
1019 | |||
1020 | return snprintf(page, PAGE_SIZE, "%d\n", | ||
1021 | atomic_read(&tpg->lport_tpg_enabled)); | ||
1022 | } | ||
1023 | |||
1024 | static ssize_t tcm_qla2xxx_tpg_store_enable( | ||
1025 | struct se_portal_group *se_tpg, | ||
1026 | const char *page, | ||
1027 | size_t count) | ||
1028 | { | ||
1029 | struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; | ||
1030 | struct tcm_qla2xxx_lport *lport = container_of(se_wwn, | ||
1031 | struct tcm_qla2xxx_lport, lport_wwn); | ||
1032 | struct scsi_qla_host *vha = lport->qla_vha; | ||
1033 | struct qla_hw_data *ha = vha->hw; | ||
1034 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
1035 | struct tcm_qla2xxx_tpg, se_tpg); | ||
1036 | unsigned long op; | ||
1037 | int rc; | ||
1038 | |||
1039 | rc = kstrtoul(page, 0, &op); | ||
1040 | if (rc < 0) { | ||
1041 | pr_err("kstrtoul() returned %d\n", rc); | ||
1042 | return -EINVAL; | ||
1043 | } | ||
1044 | if ((op != 1) && (op != 0)) { | ||
1045 | pr_err("Illegal value for tpg_enable: %lu\n", op); | ||
1046 | return -EINVAL; | ||
1047 | } | ||
1048 | |||
1049 | if (op) { | ||
1050 | atomic_set(&tpg->lport_tpg_enabled, 1); | ||
1051 | qlt_enable_vha(vha); | ||
1052 | } else { | ||
1053 | if (!ha->tgt.qla_tgt) { | ||
1054 | pr_err("truct qla_hw_data *ha->tgt.qla_tgt is NULL\n"); | ||
1055 | return -ENODEV; | ||
1056 | } | ||
1057 | atomic_set(&tpg->lport_tpg_enabled, 0); | ||
1058 | qlt_stop_phase1(ha->tgt.qla_tgt); | ||
1059 | } | ||
1060 | |||
1061 | return count; | ||
1062 | } | ||
1063 | |||
1064 | TF_TPG_BASE_ATTR(tcm_qla2xxx, enable, S_IRUGO | S_IWUSR); | ||
1065 | |||
1066 | static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = { | ||
1067 | &tcm_qla2xxx_tpg_enable.attr, | ||
1068 | NULL, | ||
1069 | }; | ||
1070 | |||
1071 | static struct se_portal_group *tcm_qla2xxx_make_tpg( | ||
1072 | struct se_wwn *wwn, | ||
1073 | struct config_group *group, | ||
1074 | const char *name) | ||
1075 | { | ||
1076 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | ||
1077 | struct tcm_qla2xxx_lport, lport_wwn); | ||
1078 | struct tcm_qla2xxx_tpg *tpg; | ||
1079 | unsigned long tpgt; | ||
1080 | int ret; | ||
1081 | |||
1082 | if (strstr(name, "tpgt_") != name) | ||
1083 | return ERR_PTR(-EINVAL); | ||
1084 | if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) | ||
1085 | return ERR_PTR(-EINVAL); | ||
1086 | |||
1087 | if (!lport->qla_npiv_vp && (tpgt != 1)) { | ||
1088 | pr_err("In non NPIV mode, a single TPG=1 is used for HW port mappings\n"); | ||
1089 | return ERR_PTR(-ENOSYS); | ||
1090 | } | ||
1091 | |||
1092 | tpg = kzalloc(sizeof(struct tcm_qla2xxx_tpg), GFP_KERNEL); | ||
1093 | if (!tpg) { | ||
1094 | pr_err("Unable to allocate struct tcm_qla2xxx_tpg\n"); | ||
1095 | return ERR_PTR(-ENOMEM); | ||
1096 | } | ||
1097 | tpg->lport = lport; | ||
1098 | tpg->lport_tpgt = tpgt; | ||
1099 | /* | ||
1100 | * By default allow READ-ONLY TPG demo-mode access w/ cached dynamic | ||
1101 | * NodeACLs | ||
1102 | */ | ||
1103 | QLA_TPG_ATTRIB(tpg)->generate_node_acls = 1; | ||
1104 | QLA_TPG_ATTRIB(tpg)->demo_mode_write_protect = 1; | ||
1105 | QLA_TPG_ATTRIB(tpg)->cache_dynamic_acls = 1; | ||
1106 | |||
1107 | ret = core_tpg_register(&tcm_qla2xxx_fabric_configfs->tf_ops, wwn, | ||
1108 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); | ||
1109 | if (ret < 0) { | ||
1110 | kfree(tpg); | ||
1111 | return NULL; | ||
1112 | } | ||
1113 | /* | ||
1114 | * Setup local TPG=1 pointer for non NPIV mode. | ||
1115 | */ | ||
1116 | if (lport->qla_npiv_vp == NULL) | ||
1117 | lport->tpg_1 = tpg; | ||
1118 | |||
1119 | return &tpg->se_tpg; | ||
1120 | } | ||
1121 | |||
1122 | static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg) | ||
1123 | { | ||
1124 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
1125 | struct tcm_qla2xxx_tpg, se_tpg); | ||
1126 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
1127 | struct scsi_qla_host *vha = lport->qla_vha; | ||
1128 | struct qla_hw_data *ha = vha->hw; | ||
1129 | /* | ||
1130 | * Call into qla2x_target.c LLD logic to shutdown the active | ||
1131 | * FC Nexuses and disable target mode operation for this qla_hw_data | ||
1132 | */ | ||
1133 | if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stop) | ||
1134 | qlt_stop_phase1(ha->tgt.qla_tgt); | ||
1135 | |||
1136 | core_tpg_deregister(se_tpg); | ||
1137 | /* | ||
1138 | * Clear local TPG=1 pointer for non NPIV mode. | ||
1139 | */ | ||
1140 | if (lport->qla_npiv_vp == NULL) | ||
1141 | lport->tpg_1 = NULL; | ||
1142 | |||
1143 | kfree(tpg); | ||
1144 | } | ||
1145 | |||
1146 | static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( | ||
1147 | struct se_wwn *wwn, | ||
1148 | struct config_group *group, | ||
1149 | const char *name) | ||
1150 | { | ||
1151 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | ||
1152 | struct tcm_qla2xxx_lport, lport_wwn); | ||
1153 | struct tcm_qla2xxx_tpg *tpg; | ||
1154 | unsigned long tpgt; | ||
1155 | int ret; | ||
1156 | |||
1157 | if (strstr(name, "tpgt_") != name) | ||
1158 | return ERR_PTR(-EINVAL); | ||
1159 | if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) | ||
1160 | return ERR_PTR(-EINVAL); | ||
1161 | |||
1162 | tpg = kzalloc(sizeof(struct tcm_qla2xxx_tpg), GFP_KERNEL); | ||
1163 | if (!tpg) { | ||
1164 | pr_err("Unable to allocate struct tcm_qla2xxx_tpg\n"); | ||
1165 | return ERR_PTR(-ENOMEM); | ||
1166 | } | ||
1167 | tpg->lport = lport; | ||
1168 | tpg->lport_tpgt = tpgt; | ||
1169 | |||
1170 | ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn, | ||
1171 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); | ||
1172 | if (ret < 0) { | ||
1173 | kfree(tpg); | ||
1174 | return NULL; | ||
1175 | } | ||
1176 | return &tpg->se_tpg; | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1180 | * Expected to be called with struct qla_hw_data->hardware_lock held | ||
1181 | */ | ||
1182 | static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( | ||
1183 | scsi_qla_host_t *vha, | ||
1184 | const uint8_t *s_id) | ||
1185 | { | ||
1186 | struct qla_hw_data *ha = vha->hw; | ||
1187 | struct tcm_qla2xxx_lport *lport; | ||
1188 | struct se_node_acl *se_nacl; | ||
1189 | struct tcm_qla2xxx_nacl *nacl; | ||
1190 | u32 key; | ||
1191 | |||
1192 | lport = ha->tgt.target_lport_ptr; | ||
1193 | if (!lport) { | ||
1194 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | ||
1195 | dump_stack(); | ||
1196 | return NULL; | ||
1197 | } | ||
1198 | |||
1199 | key = (((unsigned long)s_id[0] << 16) | | ||
1200 | ((unsigned long)s_id[1] << 8) | | ||
1201 | (unsigned long)s_id[2]); | ||
1202 | pr_debug("find_sess_by_s_id: 0x%06x\n", key); | ||
1203 | |||
1204 | se_nacl = btree_lookup32(&lport->lport_fcport_map, key); | ||
1205 | if (!se_nacl) { | ||
1206 | pr_debug("Unable to locate s_id: 0x%06x\n", key); | ||
1207 | return NULL; | ||
1208 | } | ||
1209 | pr_debug("find_sess_by_s_id: located se_nacl: %p, initiatorname: %s\n", | ||
1210 | se_nacl, se_nacl->initiatorname); | ||
1211 | |||
1212 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
1213 | if (!nacl->qla_tgt_sess) { | ||
1214 | pr_err("Unable to locate struct qla_tgt_sess\n"); | ||
1215 | return NULL; | ||
1216 | } | ||
1217 | |||
1218 | return nacl->qla_tgt_sess; | ||
1219 | } | ||
1220 | |||
1221 | /* | ||
1222 | * Expected to be called with struct qla_hw_data->hardware_lock held | ||
1223 | */ | ||
1224 | static void tcm_qla2xxx_set_sess_by_s_id( | ||
1225 | struct tcm_qla2xxx_lport *lport, | ||
1226 | struct se_node_acl *new_se_nacl, | ||
1227 | struct tcm_qla2xxx_nacl *nacl, | ||
1228 | struct se_session *se_sess, | ||
1229 | struct qla_tgt_sess *qla_tgt_sess, | ||
1230 | uint8_t *s_id) | ||
1231 | { | ||
1232 | u32 key; | ||
1233 | void *slot; | ||
1234 | int rc; | ||
1235 | |||
1236 | key = (((unsigned long)s_id[0] << 16) | | ||
1237 | ((unsigned long)s_id[1] << 8) | | ||
1238 | (unsigned long)s_id[2]); | ||
1239 | pr_debug("set_sess_by_s_id: %06x\n", key); | ||
1240 | |||
1241 | slot = btree_lookup32(&lport->lport_fcport_map, key); | ||
1242 | if (!slot) { | ||
1243 | if (new_se_nacl) { | ||
1244 | pr_debug("Setting up new fc_port entry to new_se_nacl\n"); | ||
1245 | nacl->nport_id = key; | ||
1246 | rc = btree_insert32(&lport->lport_fcport_map, key, | ||
1247 | new_se_nacl, GFP_ATOMIC); | ||
1248 | if (rc) | ||
1249 | printk(KERN_ERR "Unable to insert s_id into fcport_map: %06x\n", | ||
1250 | (int)key); | ||
1251 | } else { | ||
1252 | pr_debug("Wiping nonexisting fc_port entry\n"); | ||
1253 | } | ||
1254 | |||
1255 | qla_tgt_sess->se_sess = se_sess; | ||
1256 | nacl->qla_tgt_sess = qla_tgt_sess; | ||
1257 | return; | ||
1258 | } | ||
1259 | |||
1260 | if (nacl->qla_tgt_sess) { | ||
1261 | if (new_se_nacl == NULL) { | ||
1262 | pr_debug("Clearing existing nacl->qla_tgt_sess and fc_port entry\n"); | ||
1263 | btree_remove32(&lport->lport_fcport_map, key); | ||
1264 | nacl->qla_tgt_sess = NULL; | ||
1265 | return; | ||
1266 | } | ||
1267 | pr_debug("Replacing existing nacl->qla_tgt_sess and fc_port entry\n"); | ||
1268 | btree_update32(&lport->lport_fcport_map, key, new_se_nacl); | ||
1269 | qla_tgt_sess->se_sess = se_sess; | ||
1270 | nacl->qla_tgt_sess = qla_tgt_sess; | ||
1271 | return; | ||
1272 | } | ||
1273 | |||
1274 | if (new_se_nacl == NULL) { | ||
1275 | pr_debug("Clearing existing fc_port entry\n"); | ||
1276 | btree_remove32(&lport->lport_fcport_map, key); | ||
1277 | return; | ||
1278 | } | ||
1279 | |||
1280 | pr_debug("Replacing existing fc_port entry w/o active nacl->qla_tgt_sess\n"); | ||
1281 | btree_update32(&lport->lport_fcport_map, key, new_se_nacl); | ||
1282 | qla_tgt_sess->se_sess = se_sess; | ||
1283 | nacl->qla_tgt_sess = qla_tgt_sess; | ||
1284 | |||
1285 | pr_debug("Setup nacl->qla_tgt_sess %p by s_id for se_nacl: %p, initiatorname: %s\n", | ||
1286 | nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname); | ||
1287 | } | ||
1288 | |||
1289 | /* | ||
1290 | * Expected to be called with struct qla_hw_data->hardware_lock held | ||
1291 | */ | ||
1292 | static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( | ||
1293 | scsi_qla_host_t *vha, | ||
1294 | const uint16_t loop_id) | ||
1295 | { | ||
1296 | struct qla_hw_data *ha = vha->hw; | ||
1297 | struct tcm_qla2xxx_lport *lport; | ||
1298 | struct se_node_acl *se_nacl; | ||
1299 | struct tcm_qla2xxx_nacl *nacl; | ||
1300 | struct tcm_qla2xxx_fc_loopid *fc_loopid; | ||
1301 | |||
1302 | lport = ha->tgt.target_lport_ptr; | ||
1303 | if (!lport) { | ||
1304 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | ||
1305 | dump_stack(); | ||
1306 | return NULL; | ||
1307 | } | ||
1308 | |||
1309 | pr_debug("find_sess_by_loop_id: Using loop_id: 0x%04x\n", loop_id); | ||
1310 | |||
1311 | fc_loopid = lport->lport_loopid_map + loop_id; | ||
1312 | se_nacl = fc_loopid->se_nacl; | ||
1313 | if (!se_nacl) { | ||
1314 | pr_debug("Unable to locate se_nacl by loop_id: 0x%04x\n", | ||
1315 | loop_id); | ||
1316 | return NULL; | ||
1317 | } | ||
1318 | |||
1319 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
1320 | |||
1321 | if (!nacl->qla_tgt_sess) { | ||
1322 | pr_err("Unable to locate struct qla_tgt_sess\n"); | ||
1323 | return NULL; | ||
1324 | } | ||
1325 | |||
1326 | return nacl->qla_tgt_sess; | ||
1327 | } | ||
1328 | |||
1329 | /* | ||
1330 | * Expected to be called with struct qla_hw_data->hardware_lock held | ||
1331 | */ | ||
1332 | static void tcm_qla2xxx_set_sess_by_loop_id( | ||
1333 | struct tcm_qla2xxx_lport *lport, | ||
1334 | struct se_node_acl *new_se_nacl, | ||
1335 | struct tcm_qla2xxx_nacl *nacl, | ||
1336 | struct se_session *se_sess, | ||
1337 | struct qla_tgt_sess *qla_tgt_sess, | ||
1338 | uint16_t loop_id) | ||
1339 | { | ||
1340 | struct se_node_acl *saved_nacl; | ||
1341 | struct tcm_qla2xxx_fc_loopid *fc_loopid; | ||
1342 | |||
1343 | pr_debug("set_sess_by_loop_id: Using loop_id: 0x%04x\n", loop_id); | ||
1344 | |||
1345 | fc_loopid = &((struct tcm_qla2xxx_fc_loopid *) | ||
1346 | lport->lport_loopid_map)[loop_id]; | ||
1347 | |||
1348 | saved_nacl = fc_loopid->se_nacl; | ||
1349 | if (!saved_nacl) { | ||
1350 | pr_debug("Setting up new fc_loopid->se_nacl to new_se_nacl\n"); | ||
1351 | fc_loopid->se_nacl = new_se_nacl; | ||
1352 | if (qla_tgt_sess->se_sess != se_sess) | ||
1353 | qla_tgt_sess->se_sess = se_sess; | ||
1354 | if (nacl->qla_tgt_sess != qla_tgt_sess) | ||
1355 | nacl->qla_tgt_sess = qla_tgt_sess; | ||
1356 | return; | ||
1357 | } | ||
1358 | |||
1359 | if (nacl->qla_tgt_sess) { | ||
1360 | if (new_se_nacl == NULL) { | ||
1361 | pr_debug("Clearing nacl->qla_tgt_sess and fc_loopid->se_nacl\n"); | ||
1362 | fc_loopid->se_nacl = NULL; | ||
1363 | nacl->qla_tgt_sess = NULL; | ||
1364 | return; | ||
1365 | } | ||
1366 | |||
1367 | pr_debug("Replacing existing nacl->qla_tgt_sess and fc_loopid->se_nacl\n"); | ||
1368 | fc_loopid->se_nacl = new_se_nacl; | ||
1369 | if (qla_tgt_sess->se_sess != se_sess) | ||
1370 | qla_tgt_sess->se_sess = se_sess; | ||
1371 | if (nacl->qla_tgt_sess != qla_tgt_sess) | ||
1372 | nacl->qla_tgt_sess = qla_tgt_sess; | ||
1373 | return; | ||
1374 | } | ||
1375 | |||
1376 | if (new_se_nacl == NULL) { | ||
1377 | pr_debug("Clearing fc_loopid->se_nacl\n"); | ||
1378 | fc_loopid->se_nacl = NULL; | ||
1379 | return; | ||
1380 | } | ||
1381 | |||
1382 | pr_debug("Replacing existing fc_loopid->se_nacl w/o active nacl->qla_tgt_sess\n"); | ||
1383 | fc_loopid->se_nacl = new_se_nacl; | ||
1384 | if (qla_tgt_sess->se_sess != se_sess) | ||
1385 | qla_tgt_sess->se_sess = se_sess; | ||
1386 | if (nacl->qla_tgt_sess != qla_tgt_sess) | ||
1387 | nacl->qla_tgt_sess = qla_tgt_sess; | ||
1388 | |||
1389 | pr_debug("Setup nacl->qla_tgt_sess %p by loop_id for se_nacl: %p, initiatorname: %s\n", | ||
1390 | nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname); | ||
1391 | } | ||
1392 | |||
1393 | static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | ||
1394 | { | ||
1395 | struct qla_tgt *tgt = sess->tgt; | ||
1396 | struct qla_hw_data *ha = tgt->ha; | ||
1397 | struct se_session *se_sess; | ||
1398 | struct se_node_acl *se_nacl; | ||
1399 | struct tcm_qla2xxx_lport *lport; | ||
1400 | struct tcm_qla2xxx_nacl *nacl; | ||
1401 | unsigned char be_sid[3]; | ||
1402 | unsigned long flags; | ||
1403 | |||
1404 | BUG_ON(in_interrupt()); | ||
1405 | |||
1406 | se_sess = sess->se_sess; | ||
1407 | if (!se_sess) { | ||
1408 | pr_err("struct qla_tgt_sess->se_sess is NULL\n"); | ||
1409 | dump_stack(); | ||
1410 | return; | ||
1411 | } | ||
1412 | se_nacl = se_sess->se_node_acl; | ||
1413 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
1414 | |||
1415 | lport = ha->tgt.target_lport_ptr; | ||
1416 | if (!lport) { | ||
1417 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | ||
1418 | dump_stack(); | ||
1419 | return; | ||
1420 | } | ||
1421 | target_wait_for_sess_cmds(se_sess, 0); | ||
1422 | /* | ||
1423 | * And now clear the se_nacl and session pointers from our HW lport | ||
1424 | * mappings for fabric S_ID and LOOP_ID. | ||
1425 | */ | ||
1426 | memset(&be_sid, 0, 3); | ||
1427 | be_sid[0] = sess->s_id.b.domain; | ||
1428 | be_sid[1] = sess->s_id.b.area; | ||
1429 | be_sid[2] = sess->s_id.b.al_pa; | ||
1430 | |||
1431 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1432 | tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess, | ||
1433 | sess, be_sid); | ||
1434 | tcm_qla2xxx_set_sess_by_loop_id(lport, NULL, nacl, se_sess, | ||
1435 | sess, sess->loop_id); | ||
1436 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1437 | |||
1438 | transport_deregister_session_configfs(sess->se_sess); | ||
1439 | transport_deregister_session(sess->se_sess); | ||
1440 | } | ||
1441 | |||
1442 | /* | ||
1443 | * Called via qlt_create_sess():ha->qla2x_tmpl->check_initiator_node_acl() | ||
1444 | * to locate struct se_node_acl | ||
1445 | */ | ||
1446 | static int tcm_qla2xxx_check_initiator_node_acl( | ||
1447 | scsi_qla_host_t *vha, | ||
1448 | unsigned char *fc_wwpn, | ||
1449 | void *qla_tgt_sess, | ||
1450 | uint8_t *s_id, | ||
1451 | uint16_t loop_id) | ||
1452 | { | ||
1453 | struct qla_hw_data *ha = vha->hw; | ||
1454 | struct tcm_qla2xxx_lport *lport; | ||
1455 | struct tcm_qla2xxx_tpg *tpg; | ||
1456 | struct tcm_qla2xxx_nacl *nacl; | ||
1457 | struct se_portal_group *se_tpg; | ||
1458 | struct se_node_acl *se_nacl; | ||
1459 | struct se_session *se_sess; | ||
1460 | struct qla_tgt_sess *sess = qla_tgt_sess; | ||
1461 | unsigned char port_name[36]; | ||
1462 | unsigned long flags; | ||
1463 | |||
1464 | lport = ha->tgt.target_lport_ptr; | ||
1465 | if (!lport) { | ||
1466 | pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); | ||
1467 | dump_stack(); | ||
1468 | return -EINVAL; | ||
1469 | } | ||
1470 | /* | ||
1471 | * Locate the TPG=1 reference.. | ||
1472 | */ | ||
1473 | tpg = lport->tpg_1; | ||
1474 | if (!tpg) { | ||
1475 | pr_err("Unable to lcoate struct tcm_qla2xxx_lport->tpg_1\n"); | ||
1476 | return -EINVAL; | ||
1477 | } | ||
1478 | se_tpg = &tpg->se_tpg; | ||
1479 | |||
1480 | se_sess = transport_init_session(); | ||
1481 | if (IS_ERR(se_sess)) { | ||
1482 | pr_err("Unable to initialize struct se_session\n"); | ||
1483 | return PTR_ERR(se_sess); | ||
1484 | } | ||
1485 | /* | ||
1486 | * Format the FCP Initiator port_name into colon seperated values to | ||
1487 | * match the format by tcm_qla2xxx explict ConfigFS NodeACLs. | ||
1488 | */ | ||
1489 | memset(&port_name, 0, 36); | ||
1490 | snprintf(port_name, 36, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", | ||
1491 | fc_wwpn[0], fc_wwpn[1], fc_wwpn[2], fc_wwpn[3], fc_wwpn[4], | ||
1492 | fc_wwpn[5], fc_wwpn[6], fc_wwpn[7]); | ||
1493 | /* | ||
1494 | * Locate our struct se_node_acl either from an explict NodeACL created | ||
1495 | * via ConfigFS, or via running in TPG demo mode. | ||
1496 | */ | ||
1497 | se_sess->se_node_acl = core_tpg_check_initiator_node_acl(se_tpg, | ||
1498 | port_name); | ||
1499 | if (!se_sess->se_node_acl) { | ||
1500 | transport_free_session(se_sess); | ||
1501 | return -EINVAL; | ||
1502 | } | ||
1503 | se_nacl = se_sess->se_node_acl; | ||
1504 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
1505 | /* | ||
1506 | * And now setup the new se_nacl and session pointers into our HW lport | ||
1507 | * mappings for fabric S_ID and LOOP_ID. | ||
1508 | */ | ||
1509 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1510 | tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, | ||
1511 | qla_tgt_sess, s_id); | ||
1512 | tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess, | ||
1513 | qla_tgt_sess, loop_id); | ||
1514 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1515 | /* | ||
1516 | * Finally register the new FC Nexus with TCM | ||
1517 | */ | ||
1518 | __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); | ||
1519 | |||
1520 | return 0; | ||
1521 | } | ||
1522 | |||
1523 | /* | ||
1524 | * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. | ||
1525 | */ | ||
1526 | static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { | ||
1527 | .handle_cmd = tcm_qla2xxx_handle_cmd, | ||
1528 | .handle_data = tcm_qla2xxx_handle_data, | ||
1529 | .handle_tmr = tcm_qla2xxx_handle_tmr, | ||
1530 | .free_cmd = tcm_qla2xxx_free_cmd, | ||
1531 | .free_mcmd = tcm_qla2xxx_free_mcmd, | ||
1532 | .free_session = tcm_qla2xxx_free_session, | ||
1533 | .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, | ||
1534 | .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, | ||
1535 | .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, | ||
1536 | .clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map, | ||
1537 | .put_sess = tcm_qla2xxx_put_sess, | ||
1538 | .shutdown_sess = tcm_qla2xxx_shutdown_sess, | ||
1539 | }; | ||
1540 | |||
1541 | static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) | ||
1542 | { | ||
1543 | int rc; | ||
1544 | |||
1545 | rc = btree_init32(&lport->lport_fcport_map); | ||
1546 | if (rc) { | ||
1547 | pr_err("Unable to initialize lport->lport_fcport_map btree\n"); | ||
1548 | return rc; | ||
1549 | } | ||
1550 | |||
1551 | lport->lport_loopid_map = vmalloc(sizeof(struct tcm_qla2xxx_fc_loopid) * | ||
1552 | 65536); | ||
1553 | if (!lport->lport_loopid_map) { | ||
1554 | pr_err("Unable to allocate lport->lport_loopid_map of %zu bytes\n", | ||
1555 | sizeof(struct tcm_qla2xxx_fc_loopid) * 65536); | ||
1556 | btree_destroy32(&lport->lport_fcport_map); | ||
1557 | return -ENOMEM; | ||
1558 | } | ||
1559 | memset(lport->lport_loopid_map, 0, sizeof(struct tcm_qla2xxx_fc_loopid) | ||
1560 | * 65536); | ||
1561 | pr_debug("qla2xxx: Allocated lport_loopid_map of %zu bytes\n", | ||
1562 | sizeof(struct tcm_qla2xxx_fc_loopid) * 65536); | ||
1563 | return 0; | ||
1564 | } | ||
1565 | |||
1566 | static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) | ||
1567 | { | ||
1568 | struct qla_hw_data *ha = vha->hw; | ||
1569 | struct tcm_qla2xxx_lport *lport; | ||
1570 | /* | ||
1571 | * Setup local pointer to vha, NPIV VP pointer (if present) and | ||
1572 | * vha->tcm_lport pointer | ||
1573 | */ | ||
1574 | lport = (struct tcm_qla2xxx_lport *)ha->tgt.target_lport_ptr; | ||
1575 | lport->qla_vha = vha; | ||
1576 | |||
1577 | return 0; | ||
1578 | } | ||
1579 | |||
1580 | static struct se_wwn *tcm_qla2xxx_make_lport( | ||
1581 | struct target_fabric_configfs *tf, | ||
1582 | struct config_group *group, | ||
1583 | const char *name) | ||
1584 | { | ||
1585 | struct tcm_qla2xxx_lport *lport; | ||
1586 | u64 wwpn; | ||
1587 | int ret = -ENODEV; | ||
1588 | |||
1589 | if (tcm_qla2xxx_parse_wwn(name, &wwpn, 1) < 0) | ||
1590 | return ERR_PTR(-EINVAL); | ||
1591 | |||
1592 | lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); | ||
1593 | if (!lport) { | ||
1594 | pr_err("Unable to allocate struct tcm_qla2xxx_lport\n"); | ||
1595 | return ERR_PTR(-ENOMEM); | ||
1596 | } | ||
1597 | lport->lport_wwpn = wwpn; | ||
1598 | tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, | ||
1599 | wwpn); | ||
1600 | |||
1601 | ret = tcm_qla2xxx_init_lport(lport); | ||
1602 | if (ret != 0) | ||
1603 | goto out; | ||
1604 | |||
1605 | ret = qlt_lport_register(&tcm_qla2xxx_template, wwpn, | ||
1606 | tcm_qla2xxx_lport_register_cb, lport); | ||
1607 | if (ret != 0) | ||
1608 | goto out_lport; | ||
1609 | |||
1610 | return &lport->lport_wwn; | ||
1611 | out_lport: | ||
1612 | vfree(lport->lport_loopid_map); | ||
1613 | btree_destroy32(&lport->lport_fcport_map); | ||
1614 | out: | ||
1615 | kfree(lport); | ||
1616 | return ERR_PTR(ret); | ||
1617 | } | ||
1618 | |||
1619 | static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) | ||
1620 | { | ||
1621 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | ||
1622 | struct tcm_qla2xxx_lport, lport_wwn); | ||
1623 | struct scsi_qla_host *vha = lport->qla_vha; | ||
1624 | struct qla_hw_data *ha = vha->hw; | ||
1625 | struct se_node_acl *node; | ||
1626 | u32 key = 0; | ||
1627 | |||
1628 | /* | ||
1629 | * Call into qla2x_target.c LLD logic to complete the | ||
1630 | * shutdown of struct qla_tgt after the call to | ||
1631 | * qlt_stop_phase1() from tcm_qla2xxx_drop_tpg() above.. | ||
1632 | */ | ||
1633 | if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stopped) | ||
1634 | qlt_stop_phase2(ha->tgt.qla_tgt); | ||
1635 | |||
1636 | qlt_lport_deregister(vha); | ||
1637 | |||
1638 | vfree(lport->lport_loopid_map); | ||
1639 | btree_for_each_safe32(&lport->lport_fcport_map, key, node) | ||
1640 | btree_remove32(&lport->lport_fcport_map, key); | ||
1641 | btree_destroy32(&lport->lport_fcport_map); | ||
1642 | kfree(lport); | ||
1643 | } | ||
1644 | |||
1645 | static struct se_wwn *tcm_qla2xxx_npiv_make_lport( | ||
1646 | struct target_fabric_configfs *tf, | ||
1647 | struct config_group *group, | ||
1648 | const char *name) | ||
1649 | { | ||
1650 | struct tcm_qla2xxx_lport *lport; | ||
1651 | u64 npiv_wwpn, npiv_wwnn; | ||
1652 | int ret; | ||
1653 | |||
1654 | if (tcm_qla2xxx_npiv_parse_wwn(name, strlen(name)+1, | ||
1655 | &npiv_wwpn, &npiv_wwnn) < 0) | ||
1656 | return ERR_PTR(-EINVAL); | ||
1657 | |||
1658 | lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); | ||
1659 | if (!lport) { | ||
1660 | pr_err("Unable to allocate struct tcm_qla2xxx_lport for NPIV\n"); | ||
1661 | return ERR_PTR(-ENOMEM); | ||
1662 | } | ||
1663 | lport->lport_npiv_wwpn = npiv_wwpn; | ||
1664 | lport->lport_npiv_wwnn = npiv_wwnn; | ||
1665 | tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], | ||
1666 | TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); | ||
1667 | |||
1668 | /* FIXME: tcm_qla2xxx_npiv_make_lport */ | ||
1669 | ret = -ENOSYS; | ||
1670 | if (ret != 0) | ||
1671 | goto out; | ||
1672 | |||
1673 | return &lport->lport_wwn; | ||
1674 | out: | ||
1675 | kfree(lport); | ||
1676 | return ERR_PTR(ret); | ||
1677 | } | ||
1678 | |||
1679 | static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn) | ||
1680 | { | ||
1681 | struct tcm_qla2xxx_lport *lport = container_of(wwn, | ||
1682 | struct tcm_qla2xxx_lport, lport_wwn); | ||
1683 | struct scsi_qla_host *vha = lport->qla_vha; | ||
1684 | struct Scsi_Host *sh = vha->host; | ||
1685 | /* | ||
1686 | * Notify libfc that we want to release the lport->npiv_vport | ||
1687 | */ | ||
1688 | fc_vport_terminate(lport->npiv_vport); | ||
1689 | |||
1690 | scsi_host_put(sh); | ||
1691 | kfree(lport); | ||
1692 | } | ||
1693 | |||
1694 | |||
1695 | static ssize_t tcm_qla2xxx_wwn_show_attr_version( | ||
1696 | struct target_fabric_configfs *tf, | ||
1697 | char *page) | ||
1698 | { | ||
1699 | return sprintf(page, | ||
1700 | "TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on " | ||
1701 | UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname, | ||
1702 | utsname()->machine); | ||
1703 | } | ||
1704 | |||
1705 | TF_WWN_ATTR_RO(tcm_qla2xxx, version); | ||
1706 | |||
1707 | static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = { | ||
1708 | &tcm_qla2xxx_wwn_version.attr, | ||
1709 | NULL, | ||
1710 | }; | ||
1711 | |||
1712 | static struct target_core_fabric_ops tcm_qla2xxx_ops = { | ||
1713 | .get_fabric_name = tcm_qla2xxx_get_fabric_name, | ||
1714 | .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, | ||
1715 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, | ||
1716 | .tpg_get_tag = tcm_qla2xxx_get_tag, | ||
1717 | .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, | ||
1718 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, | ||
1719 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, | ||
1720 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, | ||
1721 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, | ||
1722 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, | ||
1723 | .tpg_check_demo_mode_write_protect = | ||
1724 | tcm_qla2xxx_check_demo_write_protect, | ||
1725 | .tpg_check_prod_mode_write_protect = | ||
1726 | tcm_qla2xxx_check_prod_write_protect, | ||
1727 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_true, | ||
1728 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, | ||
1729 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, | ||
1730 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, | ||
1731 | .new_cmd_map = NULL, | ||
1732 | .check_stop_free = tcm_qla2xxx_check_stop_free, | ||
1733 | .release_cmd = tcm_qla2xxx_release_cmd, | ||
1734 | .shutdown_session = tcm_qla2xxx_shutdown_session, | ||
1735 | .close_session = tcm_qla2xxx_close_session, | ||
1736 | .sess_get_index = tcm_qla2xxx_sess_get_index, | ||
1737 | .sess_get_initiator_sid = NULL, | ||
1738 | .write_pending = tcm_qla2xxx_write_pending, | ||
1739 | .write_pending_status = tcm_qla2xxx_write_pending_status, | ||
1740 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, | ||
1741 | .get_task_tag = tcm_qla2xxx_get_task_tag, | ||
1742 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, | ||
1743 | .queue_data_in = tcm_qla2xxx_queue_data_in, | ||
1744 | .queue_status = tcm_qla2xxx_queue_status, | ||
1745 | .queue_tm_rsp = tcm_qla2xxx_queue_tm_rsp, | ||
1746 | .get_fabric_sense_len = tcm_qla2xxx_get_fabric_sense_len, | ||
1747 | .set_fabric_sense_len = tcm_qla2xxx_set_fabric_sense_len, | ||
1748 | /* | ||
1749 | * Setup function pointers for generic logic in | ||
1750 | * target_core_fabric_configfs.c | ||
1751 | */ | ||
1752 | .fabric_make_wwn = tcm_qla2xxx_make_lport, | ||
1753 | .fabric_drop_wwn = tcm_qla2xxx_drop_lport, | ||
1754 | .fabric_make_tpg = tcm_qla2xxx_make_tpg, | ||
1755 | .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, | ||
1756 | .fabric_post_link = NULL, | ||
1757 | .fabric_pre_unlink = NULL, | ||
1758 | .fabric_make_np = NULL, | ||
1759 | .fabric_drop_np = NULL, | ||
1760 | .fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl, | ||
1761 | .fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl, | ||
1762 | }; | ||
1763 | |||
1764 | static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { | ||
1765 | .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, | ||
1766 | .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, | ||
1767 | .tpg_get_wwn = tcm_qla2xxx_npiv_get_fabric_wwn, | ||
1768 | .tpg_get_tag = tcm_qla2xxx_get_tag, | ||
1769 | .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, | ||
1770 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, | ||
1771 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, | ||
1772 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, | ||
1773 | .tpg_check_demo_mode = tcm_qla2xxx_check_false, | ||
1774 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_true, | ||
1775 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_true, | ||
1776 | .tpg_check_prod_mode_write_protect = tcm_qla2xxx_check_false, | ||
1777 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_true, | ||
1778 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, | ||
1779 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, | ||
1780 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, | ||
1781 | .release_cmd = tcm_qla2xxx_release_cmd, | ||
1782 | .shutdown_session = tcm_qla2xxx_shutdown_session, | ||
1783 | .close_session = tcm_qla2xxx_close_session, | ||
1784 | .sess_get_index = tcm_qla2xxx_sess_get_index, | ||
1785 | .sess_get_initiator_sid = NULL, | ||
1786 | .write_pending = tcm_qla2xxx_write_pending, | ||
1787 | .write_pending_status = tcm_qla2xxx_write_pending_status, | ||
1788 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, | ||
1789 | .get_task_tag = tcm_qla2xxx_get_task_tag, | ||
1790 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, | ||
1791 | .queue_data_in = tcm_qla2xxx_queue_data_in, | ||
1792 | .queue_status = tcm_qla2xxx_queue_status, | ||
1793 | .queue_tm_rsp = tcm_qla2xxx_queue_tm_rsp, | ||
1794 | .get_fabric_sense_len = tcm_qla2xxx_get_fabric_sense_len, | ||
1795 | .set_fabric_sense_len = tcm_qla2xxx_set_fabric_sense_len, | ||
1796 | /* | ||
1797 | * Setup function pointers for generic logic in | ||
1798 | * target_core_fabric_configfs.c | ||
1799 | */ | ||
1800 | .fabric_make_wwn = tcm_qla2xxx_npiv_make_lport, | ||
1801 | .fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport, | ||
1802 | .fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg, | ||
1803 | .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, | ||
1804 | .fabric_post_link = NULL, | ||
1805 | .fabric_pre_unlink = NULL, | ||
1806 | .fabric_make_np = NULL, | ||
1807 | .fabric_drop_np = NULL, | ||
1808 | .fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl, | ||
1809 | .fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl, | ||
1810 | }; | ||
1811 | |||
1812 | static int tcm_qla2xxx_register_configfs(void) | ||
1813 | { | ||
1814 | struct target_fabric_configfs *fabric, *npiv_fabric; | ||
1815 | int ret; | ||
1816 | |||
1817 | pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on " | ||
1818 | UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname, | ||
1819 | utsname()->machine); | ||
1820 | /* | ||
1821 | * Register the top level struct config_item_type with TCM core | ||
1822 | */ | ||
1823 | fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx"); | ||
1824 | if (IS_ERR(fabric)) { | ||
1825 | pr_err("target_fabric_configfs_init() failed\n"); | ||
1826 | return PTR_ERR(fabric); | ||
1827 | } | ||
1828 | /* | ||
1829 | * Setup fabric->tf_ops from our local tcm_qla2xxx_ops | ||
1830 | */ | ||
1831 | fabric->tf_ops = tcm_qla2xxx_ops; | ||
1832 | /* | ||
1833 | * Setup default attribute lists for various fabric->tf_cit_tmpl | ||
1834 | */ | ||
1835 | TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; | ||
1836 | TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_qla2xxx_tpg_attrs; | ||
1837 | TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = | ||
1838 | tcm_qla2xxx_tpg_attrib_attrs; | ||
1839 | TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL; | ||
1840 | TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; | ||
1841 | TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; | ||
1842 | TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; | ||
1843 | TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; | ||
1844 | TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; | ||
1845 | /* | ||
1846 | * Register the fabric for use within TCM | ||
1847 | */ | ||
1848 | ret = target_fabric_configfs_register(fabric); | ||
1849 | if (ret < 0) { | ||
1850 | pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n"); | ||
1851 | return ret; | ||
1852 | } | ||
1853 | /* | ||
1854 | * Setup our local pointer to *fabric | ||
1855 | */ | ||
1856 | tcm_qla2xxx_fabric_configfs = fabric; | ||
1857 | pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_fabric_configfs\n"); | ||
1858 | |||
1859 | /* | ||
1860 | * Register the top level struct config_item_type for NPIV with TCM core | ||
1861 | */ | ||
1862 | npiv_fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx_npiv"); | ||
1863 | if (IS_ERR(npiv_fabric)) { | ||
1864 | pr_err("target_fabric_configfs_init() failed\n"); | ||
1865 | ret = PTR_ERR(npiv_fabric); | ||
1866 | goto out_fabric; | ||
1867 | } | ||
1868 | /* | ||
1869 | * Setup fabric->tf_ops from our local tcm_qla2xxx_npiv_ops | ||
1870 | */ | ||
1871 | npiv_fabric->tf_ops = tcm_qla2xxx_npiv_ops; | ||
1872 | /* | ||
1873 | * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl | ||
1874 | */ | ||
1875 | TF_CIT_TMPL(npiv_fabric)->tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; | ||
1876 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_base_cit.ct_attrs = NULL; | ||
1877 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL; | ||
1878 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_param_cit.ct_attrs = NULL; | ||
1879 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; | ||
1880 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; | ||
1881 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; | ||
1882 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; | ||
1883 | TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; | ||
1884 | /* | ||
1885 | * Register the npiv_fabric for use within TCM | ||
1886 | */ | ||
1887 | ret = target_fabric_configfs_register(npiv_fabric); | ||
1888 | if (ret < 0) { | ||
1889 | pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n"); | ||
1890 | goto out_fabric; | ||
1891 | } | ||
1892 | /* | ||
1893 | * Setup our local pointer to *npiv_fabric | ||
1894 | */ | ||
1895 | tcm_qla2xxx_npiv_fabric_configfs = npiv_fabric; | ||
1896 | pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_npiv_fabric_configfs\n"); | ||
1897 | |||
1898 | tcm_qla2xxx_free_wq = alloc_workqueue("tcm_qla2xxx_free", | ||
1899 | WQ_MEM_RECLAIM, 0); | ||
1900 | if (!tcm_qla2xxx_free_wq) { | ||
1901 | ret = -ENOMEM; | ||
1902 | goto out_fabric_npiv; | ||
1903 | } | ||
1904 | |||
1905 | tcm_qla2xxx_cmd_wq = alloc_workqueue("tcm_qla2xxx_cmd", 0, 0); | ||
1906 | if (!tcm_qla2xxx_cmd_wq) { | ||
1907 | ret = -ENOMEM; | ||
1908 | goto out_free_wq; | ||
1909 | } | ||
1910 | |||
1911 | return 0; | ||
1912 | |||
1913 | out_free_wq: | ||
1914 | destroy_workqueue(tcm_qla2xxx_free_wq); | ||
1915 | out_fabric_npiv: | ||
1916 | target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs); | ||
1917 | out_fabric: | ||
1918 | target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs); | ||
1919 | return ret; | ||
1920 | } | ||
1921 | |||
1922 | static void tcm_qla2xxx_deregister_configfs(void) | ||
1923 | { | ||
1924 | destroy_workqueue(tcm_qla2xxx_cmd_wq); | ||
1925 | destroy_workqueue(tcm_qla2xxx_free_wq); | ||
1926 | |||
1927 | target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs); | ||
1928 | tcm_qla2xxx_fabric_configfs = NULL; | ||
1929 | pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_fabric_configfs\n"); | ||
1930 | |||
1931 | target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs); | ||
1932 | tcm_qla2xxx_npiv_fabric_configfs = NULL; | ||
1933 | pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_npiv_fabric_configfs\n"); | ||
1934 | } | ||
1935 | |||
1936 | static int __init tcm_qla2xxx_init(void) | ||
1937 | { | ||
1938 | int ret; | ||
1939 | |||
1940 | ret = tcm_qla2xxx_register_configfs(); | ||
1941 | if (ret < 0) | ||
1942 | return ret; | ||
1943 | |||
1944 | return 0; | ||
1945 | } | ||
1946 | |||
1947 | static void __exit tcm_qla2xxx_exit(void) | ||
1948 | { | ||
1949 | tcm_qla2xxx_deregister_configfs(); | ||
1950 | } | ||
1951 | |||
1952 | MODULE_DESCRIPTION("TCM QLA2XXX series NPIV enabled fabric driver"); | ||
1953 | MODULE_LICENSE("GPL"); | ||
1954 | module_init(tcm_qla2xxx_init); | ||
1955 | module_exit(tcm_qla2xxx_exit); | ||
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h new file mode 100644 index 000000000000..825498103352 --- /dev/null +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h | |||
@@ -0,0 +1,82 @@ | |||
1 | #include <target/target_core_base.h> | ||
2 | #include <linux/btree.h> | ||
3 | |||
4 | #define TCM_QLA2XXX_VERSION "v0.1" | ||
5 | /* length of ASCII WWPNs including pad */ | ||
6 | #define TCM_QLA2XXX_NAMELEN 32 | ||
7 | /* lenth of ASCII NPIV 'WWPN+WWNN' including pad */ | ||
8 | #define TCM_QLA2XXX_NPIV_NAMELEN 66 | ||
9 | |||
10 | #include "qla_target.h" | ||
11 | |||
12 | struct tcm_qla2xxx_nacl { | ||
13 | /* From libfc struct fc_rport->port_id */ | ||
14 | u32 nport_id; | ||
15 | /* Binary World Wide unique Node Name for remote FC Initiator Nport */ | ||
16 | u64 nport_wwnn; | ||
17 | /* ASCII formatted WWPN for FC Initiator Nport */ | ||
18 | char nport_name[TCM_QLA2XXX_NAMELEN]; | ||
19 | /* Pointer to qla_tgt_sess */ | ||
20 | struct qla_tgt_sess *qla_tgt_sess; | ||
21 | /* Pointer to TCM FC nexus */ | ||
22 | struct se_session *nport_nexus; | ||
23 | /* Returned by tcm_qla2xxx_make_nodeacl() */ | ||
24 | struct se_node_acl se_node_acl; | ||
25 | }; | ||
26 | |||
27 | struct tcm_qla2xxx_tpg_attrib { | ||
28 | int generate_node_acls; | ||
29 | int cache_dynamic_acls; | ||
30 | int demo_mode_write_protect; | ||
31 | int prod_mode_write_protect; | ||
32 | }; | ||
33 | |||
34 | struct tcm_qla2xxx_tpg { | ||
35 | /* FC lport target portal group tag for TCM */ | ||
36 | u16 lport_tpgt; | ||
37 | /* Atomic bit to determine TPG active status */ | ||
38 | atomic_t lport_tpg_enabled; | ||
39 | /* Pointer back to tcm_qla2xxx_lport */ | ||
40 | struct tcm_qla2xxx_lport *lport; | ||
41 | /* Used by tcm_qla2xxx_tpg_attrib_cit */ | ||
42 | struct tcm_qla2xxx_tpg_attrib tpg_attrib; | ||
43 | /* Returned by tcm_qla2xxx_make_tpg() */ | ||
44 | struct se_portal_group se_tpg; | ||
45 | }; | ||
46 | |||
47 | #define QLA_TPG_ATTRIB(tpg) (&(tpg)->tpg_attrib) | ||
48 | |||
49 | struct tcm_qla2xxx_fc_loopid { | ||
50 | struct se_node_acl *se_nacl; | ||
51 | }; | ||
52 | |||
53 | struct tcm_qla2xxx_lport { | ||
54 | /* SCSI protocol the lport is providing */ | ||
55 | u8 lport_proto_id; | ||
56 | /* Binary World Wide unique Port Name for FC Target Lport */ | ||
57 | u64 lport_wwpn; | ||
58 | /* Binary World Wide unique Port Name for FC NPIV Target Lport */ | ||
59 | u64 lport_npiv_wwpn; | ||
60 | /* Binary World Wide unique Node Name for FC NPIV Target Lport */ | ||
61 | u64 lport_npiv_wwnn; | ||
62 | /* ASCII formatted WWPN for FC Target Lport */ | ||
63 | char lport_name[TCM_QLA2XXX_NAMELEN]; | ||
64 | /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ | ||
65 | char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; | ||
66 | /* map for fc_port pointers in 24-bit FC Port ID space */ | ||
67 | struct btree_head32 lport_fcport_map; | ||
68 | /* vmalloc-ed memory for fc_port pointers for 16-bit FC loop ID */ | ||
69 | struct tcm_qla2xxx_fc_loopid *lport_loopid_map; | ||
70 | /* Pointer to struct scsi_qla_host from qla2xxx LLD */ | ||
71 | struct scsi_qla_host *qla_vha; | ||
72 | /* Pointer to struct scsi_qla_host for NPIV VP from qla2xxx LLD */ | ||
73 | struct scsi_qla_host *qla_npiv_vp; | ||
74 | /* Pointer to struct qla_tgt pointer */ | ||
75 | struct qla_tgt lport_qla_tgt; | ||
76 | /* Pointer to struct fc_vport for NPIV vport from libfc */ | ||
77 | struct fc_vport *npiv_vport; | ||
78 | /* Pointer to TPG=1 for non NPIV mode */ | ||
79 | struct tcm_qla2xxx_tpg *tpg_1; | ||
80 | /* Returned by tcm_qla2xxx_make_lport() */ | ||
81 | struct se_wwn lport_wwn; | ||
82 | }; | ||
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c index 0b0a7d42137d..c681b2a355e1 100644 --- a/drivers/scsi/qla4xxx/ql4_attr.c +++ b/drivers/scsi/qla4xxx/ql4_attr.c | |||
@@ -9,6 +9,140 @@ | |||
9 | #include "ql4_glbl.h" | 9 | #include "ql4_glbl.h" |
10 | #include "ql4_dbg.h" | 10 | #include "ql4_dbg.h" |
11 | 11 | ||
12 | static ssize_t | ||
13 | qla4_8xxx_sysfs_read_fw_dump(struct file *filep, struct kobject *kobj, | ||
14 | struct bin_attribute *ba, char *buf, loff_t off, | ||
15 | size_t count) | ||
16 | { | ||
17 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
18 | struct device, kobj))); | ||
19 | |||
20 | if (!is_qla8022(ha)) | ||
21 | return -EINVAL; | ||
22 | |||
23 | if (!test_bit(AF_82XX_DUMP_READING, &ha->flags)) | ||
24 | return 0; | ||
25 | |||
26 | return memory_read_from_buffer(buf, count, &off, ha->fw_dump, | ||
27 | ha->fw_dump_size); | ||
28 | } | ||
29 | |||
30 | static ssize_t | ||
31 | qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj, | ||
32 | struct bin_attribute *ba, char *buf, loff_t off, | ||
33 | size_t count) | ||
34 | { | ||
35 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
36 | struct device, kobj))); | ||
37 | uint32_t dev_state; | ||
38 | long reading; | ||
39 | int ret = 0; | ||
40 | |||
41 | if (!is_qla8022(ha)) | ||
42 | return -EINVAL; | ||
43 | |||
44 | if (off != 0) | ||
45 | return ret; | ||
46 | |||
47 | buf[1] = 0; | ||
48 | ret = kstrtol(buf, 10, &reading); | ||
49 | if (ret) { | ||
50 | ql4_printk(KERN_ERR, ha, "%s: Invalid input. Return err %d\n", | ||
51 | __func__, ret); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | switch (reading) { | ||
56 | case 0: | ||
57 | /* clear dump collection flags */ | ||
58 | if (test_and_clear_bit(AF_82XX_DUMP_READING, &ha->flags)) { | ||
59 | clear_bit(AF_82XX_FW_DUMPED, &ha->flags); | ||
60 | /* Reload minidump template */ | ||
61 | qla4xxx_alloc_fw_dump(ha); | ||
62 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
63 | "Firmware template reloaded\n")); | ||
64 | } | ||
65 | break; | ||
66 | case 1: | ||
67 | /* Set flag to read dump */ | ||
68 | if (test_bit(AF_82XX_FW_DUMPED, &ha->flags) && | ||
69 | !test_bit(AF_82XX_DUMP_READING, &ha->flags)) { | ||
70 | set_bit(AF_82XX_DUMP_READING, &ha->flags); | ||
71 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
72 | "Raw firmware dump ready for read on (%ld).\n", | ||
73 | ha->host_no)); | ||
74 | } | ||
75 | break; | ||
76 | case 2: | ||
77 | /* Reset HBA */ | ||
78 | qla4_8xxx_idc_lock(ha); | ||
79 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
80 | if (dev_state == QLA82XX_DEV_READY) { | ||
81 | ql4_printk(KERN_INFO, ha, | ||
82 | "%s: Setting Need reset, reset_owner is 0x%x.\n", | ||
83 | __func__, ha->func_num); | ||
84 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
85 | QLA82XX_DEV_NEED_RESET); | ||
86 | set_bit(AF_82XX_RST_OWNER, &ha->flags); | ||
87 | } else | ||
88 | ql4_printk(KERN_INFO, ha, | ||
89 | "%s: Reset not performed as device state is 0x%x\n", | ||
90 | __func__, dev_state); | ||
91 | |||
92 | qla4_8xxx_idc_unlock(ha); | ||
93 | break; | ||
94 | default: | ||
95 | /* do nothing */ | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | return count; | ||
100 | } | ||
101 | |||
102 | static struct bin_attribute sysfs_fw_dump_attr = { | ||
103 | .attr = { | ||
104 | .name = "fw_dump", | ||
105 | .mode = S_IRUSR | S_IWUSR, | ||
106 | }, | ||
107 | .size = 0, | ||
108 | .read = qla4_8xxx_sysfs_read_fw_dump, | ||
109 | .write = qla4_8xxx_sysfs_write_fw_dump, | ||
110 | }; | ||
111 | |||
112 | static struct sysfs_entry { | ||
113 | char *name; | ||
114 | struct bin_attribute *attr; | ||
115 | } bin_file_entries[] = { | ||
116 | { "fw_dump", &sysfs_fw_dump_attr }, | ||
117 | { NULL }, | ||
118 | }; | ||
119 | |||
120 | void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha) | ||
121 | { | ||
122 | struct Scsi_Host *host = ha->host; | ||
123 | struct sysfs_entry *iter; | ||
124 | int ret; | ||
125 | |||
126 | for (iter = bin_file_entries; iter->name; iter++) { | ||
127 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, | ||
128 | iter->attr); | ||
129 | if (ret) | ||
130 | ql4_printk(KERN_ERR, ha, | ||
131 | "Unable to create sysfs %s binary attribute (%d).\n", | ||
132 | iter->name, ret); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha) | ||
137 | { | ||
138 | struct Scsi_Host *host = ha->host; | ||
139 | struct sysfs_entry *iter; | ||
140 | |||
141 | for (iter = bin_file_entries; iter->name; iter++) | ||
142 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | ||
143 | iter->attr); | ||
144 | } | ||
145 | |||
12 | /* Scsi_Host attributes. */ | 146 | /* Scsi_Host attributes. */ |
13 | static ssize_t | 147 | static ssize_t |
14 | qla4xxx_fw_version_show(struct device *dev, | 148 | qla4xxx_fw_version_show(struct device *dev, |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 7f2492e88be7..96a5616a8fda 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -398,6 +398,16 @@ struct isp_operations { | |||
398 | int (*get_sys_info) (struct scsi_qla_host *); | 398 | int (*get_sys_info) (struct scsi_qla_host *); |
399 | }; | 399 | }; |
400 | 400 | ||
401 | struct ql4_mdump_size_table { | ||
402 | uint32_t size; | ||
403 | uint32_t size_cmask_02; | ||
404 | uint32_t size_cmask_04; | ||
405 | uint32_t size_cmask_08; | ||
406 | uint32_t size_cmask_10; | ||
407 | uint32_t size_cmask_FF; | ||
408 | uint32_t version; | ||
409 | }; | ||
410 | |||
401 | /*qla4xxx ipaddress configuration details */ | 411 | /*qla4xxx ipaddress configuration details */ |
402 | struct ipaddress_config { | 412 | struct ipaddress_config { |
403 | uint16_t ipv4_options; | 413 | uint16_t ipv4_options; |
@@ -485,6 +495,10 @@ struct scsi_qla_host { | |||
485 | #define AF_EEH_BUSY 20 /* 0x00100000 */ | 495 | #define AF_EEH_BUSY 20 /* 0x00100000 */ |
486 | #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ | 496 | #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ |
487 | #define AF_BUILD_DDB_LIST 22 /* 0x00400000 */ | 497 | #define AF_BUILD_DDB_LIST 22 /* 0x00400000 */ |
498 | #define AF_82XX_FW_DUMPED 24 /* 0x01000000 */ | ||
499 | #define AF_82XX_RST_OWNER 25 /* 0x02000000 */ | ||
500 | #define AF_82XX_DUMP_READING 26 /* 0x04000000 */ | ||
501 | |||
488 | unsigned long dpc_flags; | 502 | unsigned long dpc_flags; |
489 | 503 | ||
490 | #define DPC_RESET_HA 1 /* 0x00000002 */ | 504 | #define DPC_RESET_HA 1 /* 0x00000002 */ |
@@ -662,6 +676,11 @@ struct scsi_qla_host { | |||
662 | 676 | ||
663 | uint32_t nx_dev_init_timeout; | 677 | uint32_t nx_dev_init_timeout; |
664 | uint32_t nx_reset_timeout; | 678 | uint32_t nx_reset_timeout; |
679 | void *fw_dump; | ||
680 | uint32_t fw_dump_size; | ||
681 | uint32_t fw_dump_capture_mask; | ||
682 | void *fw_dump_tmplt_hdr; | ||
683 | uint32_t fw_dump_tmplt_size; | ||
665 | 684 | ||
666 | struct completion mbx_intr_comp; | 685 | struct completion mbx_intr_comp; |
667 | 686 | ||
@@ -936,4 +955,7 @@ static inline int ql4xxx_reset_active(struct scsi_qla_host *ha) | |||
936 | #define PROCESS_ALL_AENS 0 | 955 | #define PROCESS_ALL_AENS 0 |
937 | #define FLUSH_DDB_CHANGED_AENS 1 | 956 | #define FLUSH_DDB_CHANGED_AENS 1 |
938 | 957 | ||
958 | /* Defines for udev events */ | ||
959 | #define QL4_UEVENT_CODE_FW_DUMP 0 | ||
960 | |||
939 | #endif /*_QLA4XXX_H */ | 961 | #endif /*_QLA4XXX_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 210cd1d64475..7240948fb929 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -385,6 +385,11 @@ struct qla_flt_region { | |||
385 | #define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 | 385 | #define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 |
386 | #define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 | 386 | #define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 |
387 | #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 | 387 | #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 |
388 | #define MBOX_CMD_MINIDUMP 0x0129 | ||
389 | |||
390 | /* Minidump subcommand */ | ||
391 | #define MINIDUMP_GET_SIZE_SUBCOMMAND 0x00 | ||
392 | #define MINIDUMP_GET_TMPLT_SUBCOMMAND 0x01 | ||
388 | 393 | ||
389 | /* Mailbox 1 */ | 394 | /* Mailbox 1 */ |
390 | #define FW_STATE_READY 0x0000 | 395 | #define FW_STATE_READY 0x0000 |
@@ -1190,4 +1195,27 @@ struct ql_iscsi_stats { | |||
1190 | uint8_t reserved2[264]; /* 0x0308 - 0x040F */ | 1195 | uint8_t reserved2[264]; /* 0x0308 - 0x040F */ |
1191 | }; | 1196 | }; |
1192 | 1197 | ||
1198 | #define QLA82XX_DBG_STATE_ARRAY_LEN 16 | ||
1199 | #define QLA82XX_DBG_CAP_SIZE_ARRAY_LEN 8 | ||
1200 | #define QLA82XX_DBG_RSVD_ARRAY_LEN 8 | ||
1201 | |||
1202 | struct qla4_8xxx_minidump_template_hdr { | ||
1203 | uint32_t entry_type; | ||
1204 | uint32_t first_entry_offset; | ||
1205 | uint32_t size_of_template; | ||
1206 | uint32_t capture_debug_level; | ||
1207 | uint32_t num_of_entries; | ||
1208 | uint32_t version; | ||
1209 | uint32_t driver_timestamp; | ||
1210 | uint32_t checksum; | ||
1211 | |||
1212 | uint32_t driver_capture_mask; | ||
1213 | uint32_t driver_info_word2; | ||
1214 | uint32_t driver_info_word3; | ||
1215 | uint32_t driver_info_word4; | ||
1216 | |||
1217 | uint32_t saved_state_array[QLA82XX_DBG_STATE_ARRAY_LEN]; | ||
1218 | uint32_t capture_size_array[QLA82XX_DBG_CAP_SIZE_ARRAY_LEN]; | ||
1219 | }; | ||
1220 | |||
1193 | #endif /* _QLA4X_FW_H */ | 1221 | #endif /* _QLA4X_FW_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 910536667cf5..20b49d019043 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -196,10 +196,18 @@ int qla4xxx_bsg_request(struct bsg_job *bsg_job); | |||
196 | int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); | 196 | int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); |
197 | 197 | ||
198 | void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry); | 198 | void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry); |
199 | int qla4xxx_get_minidump_template(struct scsi_qla_host *ha, | ||
200 | dma_addr_t phys_addr); | ||
201 | int qla4xxx_req_template_size(struct scsi_qla_host *ha); | ||
202 | void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha); | ||
203 | void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha); | ||
204 | void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha); | ||
199 | 205 | ||
200 | extern int ql4xextended_error_logging; | 206 | extern int ql4xextended_error_logging; |
201 | extern int ql4xdontresethba; | 207 | extern int ql4xdontresethba; |
202 | extern int ql4xenablemsix; | 208 | extern int ql4xenablemsix; |
209 | extern int ql4xmdcapmask; | ||
210 | extern int ql4xenablemd; | ||
203 | 211 | ||
204 | extern struct device_attribute *qla4xxx_host_attrs[]; | 212 | extern struct device_attribute *qla4xxx_host_attrs[]; |
205 | #endif /* _QLA4x_GBL_H */ | 213 | #endif /* _QLA4x_GBL_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 90ee5d8fa731..bf36723b84e1 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -277,6 +277,94 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha) | |||
277 | return ipv4_wait|ipv6_wait; | 277 | return ipv4_wait|ipv6_wait; |
278 | } | 278 | } |
279 | 279 | ||
280 | /** | ||
281 | * qla4xxx_alloc_fw_dump - Allocate memory for minidump data. | ||
282 | * @ha: pointer to host adapter structure. | ||
283 | **/ | ||
284 | void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha) | ||
285 | { | ||
286 | int status; | ||
287 | uint32_t capture_debug_level; | ||
288 | int hdr_entry_bit, k; | ||
289 | void *md_tmp; | ||
290 | dma_addr_t md_tmp_dma; | ||
291 | struct qla4_8xxx_minidump_template_hdr *md_hdr; | ||
292 | |||
293 | if (ha->fw_dump) { | ||
294 | ql4_printk(KERN_WARNING, ha, | ||
295 | "Firmware dump previously allocated.\n"); | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | status = qla4xxx_req_template_size(ha); | ||
300 | if (status != QLA_SUCCESS) { | ||
301 | ql4_printk(KERN_INFO, ha, | ||
302 | "scsi%ld: Failed to get template size\n", | ||
303 | ha->host_no); | ||
304 | return; | ||
305 | } | ||
306 | |||
307 | clear_bit(AF_82XX_FW_DUMPED, &ha->flags); | ||
308 | |||
309 | /* Allocate memory for saving the template */ | ||
310 | md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, | ||
311 | &md_tmp_dma, GFP_KERNEL); | ||
312 | |||
313 | /* Request template */ | ||
314 | status = qla4xxx_get_minidump_template(ha, md_tmp_dma); | ||
315 | if (status != QLA_SUCCESS) { | ||
316 | ql4_printk(KERN_INFO, ha, | ||
317 | "scsi%ld: Failed to get minidump template\n", | ||
318 | ha->host_no); | ||
319 | goto alloc_cleanup; | ||
320 | } | ||
321 | |||
322 | md_hdr = (struct qla4_8xxx_minidump_template_hdr *)md_tmp; | ||
323 | |||
324 | capture_debug_level = md_hdr->capture_debug_level; | ||
325 | |||
326 | /* Get capture mask based on module loadtime setting. */ | ||
327 | if (ql4xmdcapmask >= 0x3 && ql4xmdcapmask <= 0x7F) | ||
328 | ha->fw_dump_capture_mask = ql4xmdcapmask; | ||
329 | else | ||
330 | ha->fw_dump_capture_mask = capture_debug_level; | ||
331 | |||
332 | md_hdr->driver_capture_mask = ha->fw_dump_capture_mask; | ||
333 | |||
334 | DEBUG2(ql4_printk(KERN_INFO, ha, "Minimum num of entries = %d\n", | ||
335 | md_hdr->num_of_entries)); | ||
336 | DEBUG2(ql4_printk(KERN_INFO, ha, "Dump template size = %d\n", | ||
337 | ha->fw_dump_tmplt_size)); | ||
338 | DEBUG2(ql4_printk(KERN_INFO, ha, "Selected Capture mask =0x%x\n", | ||
339 | ha->fw_dump_capture_mask)); | ||
340 | |||
341 | /* Calculate fw_dump_size */ | ||
342 | for (hdr_entry_bit = 0x2, k = 1; (hdr_entry_bit & 0xFF); | ||
343 | hdr_entry_bit <<= 1, k++) { | ||
344 | if (hdr_entry_bit & ha->fw_dump_capture_mask) | ||
345 | ha->fw_dump_size += md_hdr->capture_size_array[k]; | ||
346 | } | ||
347 | |||
348 | /* Total firmware dump size including command header */ | ||
349 | ha->fw_dump_size += ha->fw_dump_tmplt_size; | ||
350 | ha->fw_dump = vmalloc(ha->fw_dump_size); | ||
351 | if (!ha->fw_dump) | ||
352 | goto alloc_cleanup; | ||
353 | |||
354 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
355 | "Minidump Tempalate Size = 0x%x KB\n", | ||
356 | ha->fw_dump_tmplt_size)); | ||
357 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
358 | "Total Minidump size = 0x%x KB\n", ha->fw_dump_size)); | ||
359 | |||
360 | memcpy(ha->fw_dump, md_tmp, ha->fw_dump_tmplt_size); | ||
361 | ha->fw_dump_tmplt_hdr = ha->fw_dump; | ||
362 | |||
363 | alloc_cleanup: | ||
364 | dma_free_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, | ||
365 | md_tmp, md_tmp_dma); | ||
366 | } | ||
367 | |||
280 | static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | 368 | static int qla4xxx_fw_ready(struct scsi_qla_host *ha) |
281 | { | 369 | { |
282 | uint32_t timeout_count; | 370 | uint32_t timeout_count; |
@@ -445,9 +533,13 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) | |||
445 | "control block\n", ha->host_no, __func__)); | 533 | "control block\n", ha->host_no, __func__)); |
446 | return status; | 534 | return status; |
447 | } | 535 | } |
536 | |||
448 | if (!qla4xxx_fw_ready(ha)) | 537 | if (!qla4xxx_fw_ready(ha)) |
449 | return status; | 538 | return status; |
450 | 539 | ||
540 | if (is_qla8022(ha) && !test_bit(AF_INIT_DONE, &ha->flags)) | ||
541 | qla4xxx_alloc_fw_dump(ha); | ||
542 | |||
451 | return qla4xxx_get_firmware_status(ha); | 543 | return qla4xxx_get_firmware_status(ha); |
452 | } | 544 | } |
453 | 545 | ||
@@ -884,8 +976,8 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
884 | switch (state) { | 976 | switch (state) { |
885 | case DDB_DS_SESSION_ACTIVE: | 977 | case DDB_DS_SESSION_ACTIVE: |
886 | case DDB_DS_DISCOVERY: | 978 | case DDB_DS_DISCOVERY: |
887 | ddb_entry->unblock_sess(ddb_entry->sess); | ||
888 | qla4xxx_update_session_conn_param(ha, ddb_entry); | 979 | qla4xxx_update_session_conn_param(ha, ddb_entry); |
980 | ddb_entry->unblock_sess(ddb_entry->sess); | ||
889 | status = QLA_SUCCESS; | 981 | status = QLA_SUCCESS; |
890 | break; | 982 | break; |
891 | case DDB_DS_SESSION_FAILED: | 983 | case DDB_DS_SESSION_FAILED: |
@@ -897,6 +989,7 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
897 | } | 989 | } |
898 | break; | 990 | break; |
899 | case DDB_DS_SESSION_ACTIVE: | 991 | case DDB_DS_SESSION_ACTIVE: |
992 | case DDB_DS_DISCOVERY: | ||
900 | switch (state) { | 993 | switch (state) { |
901 | case DDB_DS_SESSION_FAILED: | 994 | case DDB_DS_SESSION_FAILED: |
902 | /* | 995 | /* |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 7ac21dabbf22..cab8f665a41f 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -51,25 +51,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
54 | if (is_qla8022(ha)) { | ||
55 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
56 | DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " | ||
57 | "prematurely completing mbx cmd as firmware " | ||
58 | "recovery detected\n", ha->host_no, __func__)); | ||
59 | return status; | ||
60 | } | ||
61 | /* Do not send any mbx cmd if h/w is in failed state*/ | ||
62 | qla4_8xxx_idc_lock(ha); | ||
63 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
64 | qla4_8xxx_idc_unlock(ha); | ||
65 | if (dev_state == QLA82XX_DEV_FAILED) { | ||
66 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in " | ||
67 | "failed state, do not send any mailbox commands\n", | ||
68 | ha->host_no, __func__); | ||
69 | return status; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | if ((is_aer_supported(ha)) && | 54 | if ((is_aer_supported(ha)) && |
74 | (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { | 55 | (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { |
75 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " | 56 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " |
@@ -96,6 +77,25 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
96 | msleep(10); | 77 | msleep(10); |
97 | } | 78 | } |
98 | 79 | ||
80 | if (is_qla8022(ha)) { | ||
81 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
82 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
83 | "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n", | ||
84 | ha->host_no, __func__)); | ||
85 | goto mbox_exit; | ||
86 | } | ||
87 | /* Do not send any mbx cmd if h/w is in failed state*/ | ||
88 | qla4_8xxx_idc_lock(ha); | ||
89 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
90 | qla4_8xxx_idc_unlock(ha); | ||
91 | if (dev_state == QLA82XX_DEV_FAILED) { | ||
92 | ql4_printk(KERN_WARNING, ha, | ||
93 | "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n", | ||
94 | ha->host_no, __func__); | ||
95 | goto mbox_exit; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | spin_lock_irqsave(&ha->hardware_lock, flags); | 99 | spin_lock_irqsave(&ha->hardware_lock, flags); |
100 | 100 | ||
101 | ha->mbox_status_count = outCount; | 101 | ha->mbox_status_count = outCount; |
@@ -270,6 +270,79 @@ mbox_exit: | |||
270 | return status; | 270 | return status; |
271 | } | 271 | } |
272 | 272 | ||
273 | /** | ||
274 | * qla4xxx_get_minidump_template - Get the firmware template | ||
275 | * @ha: Pointer to host adapter structure. | ||
276 | * @phys_addr: dma address for template | ||
277 | * | ||
278 | * Obtain the minidump template from firmware during initialization | ||
279 | * as it may not be available when minidump is desired. | ||
280 | **/ | ||
281 | int qla4xxx_get_minidump_template(struct scsi_qla_host *ha, | ||
282 | dma_addr_t phys_addr) | ||
283 | { | ||
284 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
285 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
286 | int status; | ||
287 | |||
288 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
289 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
290 | |||
291 | mbox_cmd[0] = MBOX_CMD_MINIDUMP; | ||
292 | mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND; | ||
293 | mbox_cmd[2] = LSDW(phys_addr); | ||
294 | mbox_cmd[3] = MSDW(phys_addr); | ||
295 | mbox_cmd[4] = ha->fw_dump_tmplt_size; | ||
296 | mbox_cmd[5] = 0; | ||
297 | |||
298 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], | ||
299 | &mbox_sts[0]); | ||
300 | if (status != QLA_SUCCESS) { | ||
301 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
302 | "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n", | ||
303 | ha->host_no, __func__, mbox_cmd[0], | ||
304 | mbox_sts[0], mbox_sts[1])); | ||
305 | } | ||
306 | return status; | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * qla4xxx_req_template_size - Get minidump template size from firmware. | ||
311 | * @ha: Pointer to host adapter structure. | ||
312 | **/ | ||
313 | int qla4xxx_req_template_size(struct scsi_qla_host *ha) | ||
314 | { | ||
315 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
316 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
317 | int status; | ||
318 | |||
319 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
320 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
321 | |||
322 | mbox_cmd[0] = MBOX_CMD_MINIDUMP; | ||
323 | mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND; | ||
324 | |||
325 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], | ||
326 | &mbox_sts[0]); | ||
327 | if (status == QLA_SUCCESS) { | ||
328 | ha->fw_dump_tmplt_size = mbox_sts[1]; | ||
329 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
330 | "%s: sts[0]=0x%04x, template size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n", | ||
331 | __func__, mbox_sts[0], mbox_sts[1], | ||
332 | mbox_sts[2], mbox_sts[3], mbox_sts[4], | ||
333 | mbox_sts[5], mbox_sts[6], mbox_sts[7])); | ||
334 | if (ha->fw_dump_tmplt_size == 0) | ||
335 | status = QLA_ERROR; | ||
336 | } else { | ||
337 | ql4_printk(KERN_WARNING, ha, | ||
338 | "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n", | ||
339 | __func__, mbox_sts[0], mbox_sts[1]); | ||
340 | status = QLA_ERROR; | ||
341 | } | ||
342 | |||
343 | return status; | ||
344 | } | ||
345 | |||
273 | void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) | 346 | void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) |
274 | { | 347 | { |
275 | set_bit(AF_FW_RECOVERY, &ha->flags); | 348 | set_bit(AF_FW_RECOVERY, &ha->flags); |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index e1e46b6dac75..228b67020d2c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
8 | #include <linux/io.h> | 8 | #include <linux/io.h> |
9 | #include <linux/pci.h> | 9 | #include <linux/pci.h> |
10 | #include <linux/ratelimit.h> | ||
10 | #include "ql4_def.h" | 11 | #include "ql4_def.h" |
11 | #include "ql4_glbl.h" | 12 | #include "ql4_glbl.h" |
12 | 13 | ||
@@ -420,6 +421,38 @@ qla4_8xxx_rd_32(struct scsi_qla_host *ha, ulong off) | |||
420 | return data; | 421 | return data; |
421 | } | 422 | } |
422 | 423 | ||
424 | /* Minidump related functions */ | ||
425 | static int qla4_8xxx_md_rw_32(struct scsi_qla_host *ha, uint32_t off, | ||
426 | u32 data, uint8_t flag) | ||
427 | { | ||
428 | uint32_t win_read, off_value, rval = QLA_SUCCESS; | ||
429 | |||
430 | off_value = off & 0xFFFF0000; | ||
431 | writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
432 | |||
433 | /* Read back value to make sure write has gone through before trying | ||
434 | * to use it. | ||
435 | */ | ||
436 | win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
437 | if (win_read != off_value) { | ||
438 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
439 | "%s: Written (0x%x) != Read (0x%x), off=0x%x\n", | ||
440 | __func__, off_value, win_read, off)); | ||
441 | return QLA_ERROR; | ||
442 | } | ||
443 | |||
444 | off_value = off & 0x0000FFFF; | ||
445 | |||
446 | if (flag) | ||
447 | writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M + | ||
448 | ha->nx_pcibase)); | ||
449 | else | ||
450 | rval = readl((void __iomem *)(off_value + CRB_INDIRECT_2M + | ||
451 | ha->nx_pcibase)); | ||
452 | |||
453 | return rval; | ||
454 | } | ||
455 | |||
423 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | 456 | #define CRB_WIN_LOCK_TIMEOUT 100000000 |
424 | 457 | ||
425 | int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) | 458 | int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) |
@@ -1252,9 +1285,9 @@ qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *ha, | |||
1252 | } | 1285 | } |
1253 | 1286 | ||
1254 | if (j >= MAX_CTL_CHECK) { | 1287 | if (j >= MAX_CTL_CHECK) { |
1255 | if (printk_ratelimit()) | 1288 | printk_ratelimited(KERN_ERR |
1256 | ql4_printk(KERN_ERR, ha, | 1289 | "%s: failed to read through agent\n", |
1257 | "failed to read through agent\n"); | 1290 | __func__); |
1258 | break; | 1291 | break; |
1259 | } | 1292 | } |
1260 | 1293 | ||
@@ -1390,7 +1423,8 @@ qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, | |||
1390 | if (j >= MAX_CTL_CHECK) { | 1423 | if (j >= MAX_CTL_CHECK) { |
1391 | if (printk_ratelimit()) | 1424 | if (printk_ratelimit()) |
1392 | ql4_printk(KERN_ERR, ha, | 1425 | ql4_printk(KERN_ERR, ha, |
1393 | "failed to write through agent\n"); | 1426 | "%s: failed to read through agent\n", |
1427 | __func__); | ||
1394 | ret = -1; | 1428 | ret = -1; |
1395 | break; | 1429 | break; |
1396 | } | 1430 | } |
@@ -1462,6 +1496,8 @@ qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) | |||
1462 | 1496 | ||
1463 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 1497 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
1464 | drv_active |= (1 << (ha->func_num * 4)); | 1498 | drv_active |= (1 << (ha->func_num * 4)); |
1499 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", | ||
1500 | __func__, ha->host_no, drv_active); | ||
1465 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | 1501 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); |
1466 | } | 1502 | } |
1467 | 1503 | ||
@@ -1472,6 +1508,8 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) | |||
1472 | 1508 | ||
1473 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 1509 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
1474 | drv_active &= ~(1 << (ha->func_num * 4)); | 1510 | drv_active &= ~(1 << (ha->func_num * 4)); |
1511 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", | ||
1512 | __func__, ha->host_no, drv_active); | ||
1475 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | 1513 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); |
1476 | } | 1514 | } |
1477 | 1515 | ||
@@ -1497,6 +1535,8 @@ qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) | |||
1497 | 1535 | ||
1498 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 1536 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
1499 | drv_state |= (1 << (ha->func_num * 4)); | 1537 | drv_state |= (1 << (ha->func_num * 4)); |
1538 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", | ||
1539 | __func__, ha->host_no, drv_state); | ||
1500 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | 1540 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); |
1501 | } | 1541 | } |
1502 | 1542 | ||
@@ -1507,6 +1547,8 @@ qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) | |||
1507 | 1547 | ||
1508 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 1548 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
1509 | drv_state &= ~(1 << (ha->func_num * 4)); | 1549 | drv_state &= ~(1 << (ha->func_num * 4)); |
1550 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", | ||
1551 | __func__, ha->host_no, drv_state); | ||
1510 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | 1552 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); |
1511 | } | 1553 | } |
1512 | 1554 | ||
@@ -1601,6 +1643,629 @@ static void qla4_8xxx_rom_lock_recovery(struct scsi_qla_host *ha) | |||
1601 | qla4_8xxx_rom_unlock(ha); | 1643 | qla4_8xxx_rom_unlock(ha); |
1602 | } | 1644 | } |
1603 | 1645 | ||
1646 | static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, | ||
1647 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1648 | uint32_t **d_ptr) | ||
1649 | { | ||
1650 | uint32_t r_addr, r_stride, loop_cnt, i, r_value; | ||
1651 | struct qla82xx_minidump_entry_crb *crb_hdr; | ||
1652 | uint32_t *data_ptr = *d_ptr; | ||
1653 | |||
1654 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1655 | crb_hdr = (struct qla82xx_minidump_entry_crb *)entry_hdr; | ||
1656 | r_addr = crb_hdr->addr; | ||
1657 | r_stride = crb_hdr->crb_strd.addr_stride; | ||
1658 | loop_cnt = crb_hdr->op_count; | ||
1659 | |||
1660 | for (i = 0; i < loop_cnt; i++) { | ||
1661 | r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); | ||
1662 | *data_ptr++ = cpu_to_le32(r_addr); | ||
1663 | *data_ptr++ = cpu_to_le32(r_value); | ||
1664 | r_addr += r_stride; | ||
1665 | } | ||
1666 | *d_ptr = data_ptr; | ||
1667 | } | ||
1668 | |||
1669 | static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, | ||
1670 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1671 | uint32_t **d_ptr) | ||
1672 | { | ||
1673 | uint32_t addr, r_addr, c_addr, t_r_addr; | ||
1674 | uint32_t i, k, loop_count, t_value, r_cnt, r_value; | ||
1675 | unsigned long p_wait, w_time, p_mask; | ||
1676 | uint32_t c_value_w, c_value_r; | ||
1677 | struct qla82xx_minidump_entry_cache *cache_hdr; | ||
1678 | int rval = QLA_ERROR; | ||
1679 | uint32_t *data_ptr = *d_ptr; | ||
1680 | |||
1681 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1682 | cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr; | ||
1683 | |||
1684 | loop_count = cache_hdr->op_count; | ||
1685 | r_addr = cache_hdr->read_addr; | ||
1686 | c_addr = cache_hdr->control_addr; | ||
1687 | c_value_w = cache_hdr->cache_ctrl.write_value; | ||
1688 | |||
1689 | t_r_addr = cache_hdr->tag_reg_addr; | ||
1690 | t_value = cache_hdr->addr_ctrl.init_tag_value; | ||
1691 | r_cnt = cache_hdr->read_ctrl.read_addr_cnt; | ||
1692 | p_wait = cache_hdr->cache_ctrl.poll_wait; | ||
1693 | p_mask = cache_hdr->cache_ctrl.poll_mask; | ||
1694 | |||
1695 | for (i = 0; i < loop_count; i++) { | ||
1696 | qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1); | ||
1697 | |||
1698 | if (c_value_w) | ||
1699 | qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1); | ||
1700 | |||
1701 | if (p_mask) { | ||
1702 | w_time = jiffies + p_wait; | ||
1703 | do { | ||
1704 | c_value_r = qla4_8xxx_md_rw_32(ha, c_addr, | ||
1705 | 0, 0); | ||
1706 | if ((c_value_r & p_mask) == 0) { | ||
1707 | break; | ||
1708 | } else if (time_after_eq(jiffies, w_time)) { | ||
1709 | /* capturing dump failed */ | ||
1710 | return rval; | ||
1711 | } | ||
1712 | } while (1); | ||
1713 | } | ||
1714 | |||
1715 | addr = r_addr; | ||
1716 | for (k = 0; k < r_cnt; k++) { | ||
1717 | r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); | ||
1718 | *data_ptr++ = cpu_to_le32(r_value); | ||
1719 | addr += cache_hdr->read_ctrl.read_addr_stride; | ||
1720 | } | ||
1721 | |||
1722 | t_value += cache_hdr->addr_ctrl.tag_value_stride; | ||
1723 | } | ||
1724 | *d_ptr = data_ptr; | ||
1725 | return QLA_SUCCESS; | ||
1726 | } | ||
1727 | |||
1728 | static int qla4_8xxx_minidump_process_control(struct scsi_qla_host *ha, | ||
1729 | struct qla82xx_minidump_entry_hdr *entry_hdr) | ||
1730 | { | ||
1731 | struct qla82xx_minidump_entry_crb *crb_entry; | ||
1732 | uint32_t read_value, opcode, poll_time, addr, index, rval = QLA_SUCCESS; | ||
1733 | uint32_t crb_addr; | ||
1734 | unsigned long wtime; | ||
1735 | struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; | ||
1736 | int i; | ||
1737 | |||
1738 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1739 | tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) | ||
1740 | ha->fw_dump_tmplt_hdr; | ||
1741 | crb_entry = (struct qla82xx_minidump_entry_crb *)entry_hdr; | ||
1742 | |||
1743 | crb_addr = crb_entry->addr; | ||
1744 | for (i = 0; i < crb_entry->op_count; i++) { | ||
1745 | opcode = crb_entry->crb_ctrl.opcode; | ||
1746 | if (opcode & QLA82XX_DBG_OPCODE_WR) { | ||
1747 | qla4_8xxx_md_rw_32(ha, crb_addr, | ||
1748 | crb_entry->value_1, 1); | ||
1749 | opcode &= ~QLA82XX_DBG_OPCODE_WR; | ||
1750 | } | ||
1751 | if (opcode & QLA82XX_DBG_OPCODE_RW) { | ||
1752 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1753 | qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); | ||
1754 | opcode &= ~QLA82XX_DBG_OPCODE_RW; | ||
1755 | } | ||
1756 | if (opcode & QLA82XX_DBG_OPCODE_AND) { | ||
1757 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1758 | read_value &= crb_entry->value_2; | ||
1759 | opcode &= ~QLA82XX_DBG_OPCODE_AND; | ||
1760 | if (opcode & QLA82XX_DBG_OPCODE_OR) { | ||
1761 | read_value |= crb_entry->value_3; | ||
1762 | opcode &= ~QLA82XX_DBG_OPCODE_OR; | ||
1763 | } | ||
1764 | qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); | ||
1765 | } | ||
1766 | if (opcode & QLA82XX_DBG_OPCODE_OR) { | ||
1767 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1768 | read_value |= crb_entry->value_3; | ||
1769 | qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); | ||
1770 | opcode &= ~QLA82XX_DBG_OPCODE_OR; | ||
1771 | } | ||
1772 | if (opcode & QLA82XX_DBG_OPCODE_POLL) { | ||
1773 | poll_time = crb_entry->crb_strd.poll_timeout; | ||
1774 | wtime = jiffies + poll_time; | ||
1775 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1776 | |||
1777 | do { | ||
1778 | if ((read_value & crb_entry->value_2) == | ||
1779 | crb_entry->value_1) | ||
1780 | break; | ||
1781 | else if (time_after_eq(jiffies, wtime)) { | ||
1782 | /* capturing dump failed */ | ||
1783 | rval = QLA_ERROR; | ||
1784 | break; | ||
1785 | } else | ||
1786 | read_value = qla4_8xxx_md_rw_32(ha, | ||
1787 | crb_addr, 0, 0); | ||
1788 | } while (1); | ||
1789 | opcode &= ~QLA82XX_DBG_OPCODE_POLL; | ||
1790 | } | ||
1791 | |||
1792 | if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) { | ||
1793 | if (crb_entry->crb_strd.state_index_a) { | ||
1794 | index = crb_entry->crb_strd.state_index_a; | ||
1795 | addr = tmplt_hdr->saved_state_array[index]; | ||
1796 | } else { | ||
1797 | addr = crb_addr; | ||
1798 | } | ||
1799 | |||
1800 | read_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); | ||
1801 | index = crb_entry->crb_ctrl.state_index_v; | ||
1802 | tmplt_hdr->saved_state_array[index] = read_value; | ||
1803 | opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE; | ||
1804 | } | ||
1805 | |||
1806 | if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) { | ||
1807 | if (crb_entry->crb_strd.state_index_a) { | ||
1808 | index = crb_entry->crb_strd.state_index_a; | ||
1809 | addr = tmplt_hdr->saved_state_array[index]; | ||
1810 | } else { | ||
1811 | addr = crb_addr; | ||
1812 | } | ||
1813 | |||
1814 | if (crb_entry->crb_ctrl.state_index_v) { | ||
1815 | index = crb_entry->crb_ctrl.state_index_v; | ||
1816 | read_value = | ||
1817 | tmplt_hdr->saved_state_array[index]; | ||
1818 | } else { | ||
1819 | read_value = crb_entry->value_1; | ||
1820 | } | ||
1821 | |||
1822 | qla4_8xxx_md_rw_32(ha, addr, read_value, 1); | ||
1823 | opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE; | ||
1824 | } | ||
1825 | |||
1826 | if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) { | ||
1827 | index = crb_entry->crb_ctrl.state_index_v; | ||
1828 | read_value = tmplt_hdr->saved_state_array[index]; | ||
1829 | read_value <<= crb_entry->crb_ctrl.shl; | ||
1830 | read_value >>= crb_entry->crb_ctrl.shr; | ||
1831 | if (crb_entry->value_2) | ||
1832 | read_value &= crb_entry->value_2; | ||
1833 | read_value |= crb_entry->value_3; | ||
1834 | read_value += crb_entry->value_1; | ||
1835 | tmplt_hdr->saved_state_array[index] = read_value; | ||
1836 | opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE; | ||
1837 | } | ||
1838 | crb_addr += crb_entry->crb_strd.addr_stride; | ||
1839 | } | ||
1840 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__)); | ||
1841 | return rval; | ||
1842 | } | ||
1843 | |||
1844 | static void qla4_8xxx_minidump_process_rdocm(struct scsi_qla_host *ha, | ||
1845 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1846 | uint32_t **d_ptr) | ||
1847 | { | ||
1848 | uint32_t r_addr, r_stride, loop_cnt, i, r_value; | ||
1849 | struct qla82xx_minidump_entry_rdocm *ocm_hdr; | ||
1850 | uint32_t *data_ptr = *d_ptr; | ||
1851 | |||
1852 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1853 | ocm_hdr = (struct qla82xx_minidump_entry_rdocm *)entry_hdr; | ||
1854 | r_addr = ocm_hdr->read_addr; | ||
1855 | r_stride = ocm_hdr->read_addr_stride; | ||
1856 | loop_cnt = ocm_hdr->op_count; | ||
1857 | |||
1858 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1859 | "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n", | ||
1860 | __func__, r_addr, r_stride, loop_cnt)); | ||
1861 | |||
1862 | for (i = 0; i < loop_cnt; i++) { | ||
1863 | r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase)); | ||
1864 | *data_ptr++ = cpu_to_le32(r_value); | ||
1865 | r_addr += r_stride; | ||
1866 | } | ||
1867 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%lx\n", | ||
1868 | __func__, (loop_cnt * sizeof(uint32_t)))); | ||
1869 | *d_ptr = data_ptr; | ||
1870 | } | ||
1871 | |||
1872 | static void qla4_8xxx_minidump_process_rdmux(struct scsi_qla_host *ha, | ||
1873 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1874 | uint32_t **d_ptr) | ||
1875 | { | ||
1876 | uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value; | ||
1877 | struct qla82xx_minidump_entry_mux *mux_hdr; | ||
1878 | uint32_t *data_ptr = *d_ptr; | ||
1879 | |||
1880 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1881 | mux_hdr = (struct qla82xx_minidump_entry_mux *)entry_hdr; | ||
1882 | r_addr = mux_hdr->read_addr; | ||
1883 | s_addr = mux_hdr->select_addr; | ||
1884 | s_stride = mux_hdr->select_value_stride; | ||
1885 | s_value = mux_hdr->select_value; | ||
1886 | loop_cnt = mux_hdr->op_count; | ||
1887 | |||
1888 | for (i = 0; i < loop_cnt; i++) { | ||
1889 | qla4_8xxx_md_rw_32(ha, s_addr, s_value, 1); | ||
1890 | r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); | ||
1891 | *data_ptr++ = cpu_to_le32(s_value); | ||
1892 | *data_ptr++ = cpu_to_le32(r_value); | ||
1893 | s_value += s_stride; | ||
1894 | } | ||
1895 | *d_ptr = data_ptr; | ||
1896 | } | ||
1897 | |||
1898 | static void qla4_8xxx_minidump_process_l1cache(struct scsi_qla_host *ha, | ||
1899 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1900 | uint32_t **d_ptr) | ||
1901 | { | ||
1902 | uint32_t addr, r_addr, c_addr, t_r_addr; | ||
1903 | uint32_t i, k, loop_count, t_value, r_cnt, r_value; | ||
1904 | uint32_t c_value_w; | ||
1905 | struct qla82xx_minidump_entry_cache *cache_hdr; | ||
1906 | uint32_t *data_ptr = *d_ptr; | ||
1907 | |||
1908 | cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr; | ||
1909 | loop_count = cache_hdr->op_count; | ||
1910 | r_addr = cache_hdr->read_addr; | ||
1911 | c_addr = cache_hdr->control_addr; | ||
1912 | c_value_w = cache_hdr->cache_ctrl.write_value; | ||
1913 | |||
1914 | t_r_addr = cache_hdr->tag_reg_addr; | ||
1915 | t_value = cache_hdr->addr_ctrl.init_tag_value; | ||
1916 | r_cnt = cache_hdr->read_ctrl.read_addr_cnt; | ||
1917 | |||
1918 | for (i = 0; i < loop_count; i++) { | ||
1919 | qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1); | ||
1920 | qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1); | ||
1921 | addr = r_addr; | ||
1922 | for (k = 0; k < r_cnt; k++) { | ||
1923 | r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); | ||
1924 | *data_ptr++ = cpu_to_le32(r_value); | ||
1925 | addr += cache_hdr->read_ctrl.read_addr_stride; | ||
1926 | } | ||
1927 | t_value += cache_hdr->addr_ctrl.tag_value_stride; | ||
1928 | } | ||
1929 | *d_ptr = data_ptr; | ||
1930 | } | ||
1931 | |||
1932 | static void qla4_8xxx_minidump_process_queue(struct scsi_qla_host *ha, | ||
1933 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1934 | uint32_t **d_ptr) | ||
1935 | { | ||
1936 | uint32_t s_addr, r_addr; | ||
1937 | uint32_t r_stride, r_value, r_cnt, qid = 0; | ||
1938 | uint32_t i, k, loop_cnt; | ||
1939 | struct qla82xx_minidump_entry_queue *q_hdr; | ||
1940 | uint32_t *data_ptr = *d_ptr; | ||
1941 | |||
1942 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1943 | q_hdr = (struct qla82xx_minidump_entry_queue *)entry_hdr; | ||
1944 | s_addr = q_hdr->select_addr; | ||
1945 | r_cnt = q_hdr->rd_strd.read_addr_cnt; | ||
1946 | r_stride = q_hdr->rd_strd.read_addr_stride; | ||
1947 | loop_cnt = q_hdr->op_count; | ||
1948 | |||
1949 | for (i = 0; i < loop_cnt; i++) { | ||
1950 | qla4_8xxx_md_rw_32(ha, s_addr, qid, 1); | ||
1951 | r_addr = q_hdr->read_addr; | ||
1952 | for (k = 0; k < r_cnt; k++) { | ||
1953 | r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); | ||
1954 | *data_ptr++ = cpu_to_le32(r_value); | ||
1955 | r_addr += r_stride; | ||
1956 | } | ||
1957 | qid += q_hdr->q_strd.queue_id_stride; | ||
1958 | } | ||
1959 | *d_ptr = data_ptr; | ||
1960 | } | ||
1961 | |||
1962 | #define MD_DIRECT_ROM_WINDOW 0x42110030 | ||
1963 | #define MD_DIRECT_ROM_READ_BASE 0x42150000 | ||
1964 | |||
1965 | static void qla4_8xxx_minidump_process_rdrom(struct scsi_qla_host *ha, | ||
1966 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1967 | uint32_t **d_ptr) | ||
1968 | { | ||
1969 | uint32_t r_addr, r_value; | ||
1970 | uint32_t i, loop_cnt; | ||
1971 | struct qla82xx_minidump_entry_rdrom *rom_hdr; | ||
1972 | uint32_t *data_ptr = *d_ptr; | ||
1973 | |||
1974 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1975 | rom_hdr = (struct qla82xx_minidump_entry_rdrom *)entry_hdr; | ||
1976 | r_addr = rom_hdr->read_addr; | ||
1977 | loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t); | ||
1978 | |||
1979 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1980 | "[%s]: flash_addr: 0x%x, read_data_size: 0x%x\n", | ||
1981 | __func__, r_addr, loop_cnt)); | ||
1982 | |||
1983 | for (i = 0; i < loop_cnt; i++) { | ||
1984 | qla4_8xxx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW, | ||
1985 | (r_addr & 0xFFFF0000), 1); | ||
1986 | r_value = qla4_8xxx_md_rw_32(ha, | ||
1987 | MD_DIRECT_ROM_READ_BASE + | ||
1988 | (r_addr & 0x0000FFFF), 0, 0); | ||
1989 | *data_ptr++ = cpu_to_le32(r_value); | ||
1990 | r_addr += sizeof(uint32_t); | ||
1991 | } | ||
1992 | *d_ptr = data_ptr; | ||
1993 | } | ||
1994 | |||
1995 | #define MD_MIU_TEST_AGT_CTRL 0x41000090 | ||
1996 | #define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 | ||
1997 | #define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 | ||
1998 | |||
1999 | static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, | ||
2000 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
2001 | uint32_t **d_ptr) | ||
2002 | { | ||
2003 | uint32_t r_addr, r_value, r_data; | ||
2004 | uint32_t i, j, loop_cnt; | ||
2005 | struct qla82xx_minidump_entry_rdmem *m_hdr; | ||
2006 | unsigned long flags; | ||
2007 | uint32_t *data_ptr = *d_ptr; | ||
2008 | |||
2009 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
2010 | m_hdr = (struct qla82xx_minidump_entry_rdmem *)entry_hdr; | ||
2011 | r_addr = m_hdr->read_addr; | ||
2012 | loop_cnt = m_hdr->read_data_size/16; | ||
2013 | |||
2014 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2015 | "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n", | ||
2016 | __func__, r_addr, m_hdr->read_data_size)); | ||
2017 | |||
2018 | if (r_addr & 0xf) { | ||
2019 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2020 | "[%s]: Read addr 0x%x not 16 bytes alligned\n", | ||
2021 | __func__, r_addr)); | ||
2022 | return QLA_ERROR; | ||
2023 | } | ||
2024 | |||
2025 | if (m_hdr->read_data_size % 16) { | ||
2026 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2027 | "[%s]: Read data[0x%x] not multiple of 16 bytes\n", | ||
2028 | __func__, m_hdr->read_data_size)); | ||
2029 | return QLA_ERROR; | ||
2030 | } | ||
2031 | |||
2032 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2033 | "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n", | ||
2034 | __func__, r_addr, m_hdr->read_data_size, loop_cnt)); | ||
2035 | |||
2036 | write_lock_irqsave(&ha->hw_lock, flags); | ||
2037 | for (i = 0; i < loop_cnt; i++) { | ||
2038 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1); | ||
2039 | r_value = 0; | ||
2040 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1); | ||
2041 | r_value = MIU_TA_CTL_ENABLE; | ||
2042 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1); | ||
2043 | r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; | ||
2044 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1); | ||
2045 | |||
2046 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
2047 | r_value = qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, | ||
2048 | 0, 0); | ||
2049 | if ((r_value & MIU_TA_CTL_BUSY) == 0) | ||
2050 | break; | ||
2051 | } | ||
2052 | |||
2053 | if (j >= MAX_CTL_CHECK) { | ||
2054 | printk_ratelimited(KERN_ERR | ||
2055 | "%s: failed to read through agent\n", | ||
2056 | __func__); | ||
2057 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
2058 | return QLA_SUCCESS; | ||
2059 | } | ||
2060 | |||
2061 | for (j = 0; j < 4; j++) { | ||
2062 | r_data = qla4_8xxx_md_rw_32(ha, | ||
2063 | MD_MIU_TEST_AGT_RDDATA[j], | ||
2064 | 0, 0); | ||
2065 | *data_ptr++ = cpu_to_le32(r_data); | ||
2066 | } | ||
2067 | |||
2068 | r_addr += 16; | ||
2069 | } | ||
2070 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
2071 | |||
2072 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%x\n", | ||
2073 | __func__, (loop_cnt * 16))); | ||
2074 | |||
2075 | *d_ptr = data_ptr; | ||
2076 | return QLA_SUCCESS; | ||
2077 | } | ||
2078 | |||
2079 | static void ql4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, | ||
2080 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
2081 | int index) | ||
2082 | { | ||
2083 | entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG; | ||
2084 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2085 | "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n", | ||
2086 | ha->host_no, index, entry_hdr->entry_type, | ||
2087 | entry_hdr->d_ctrl.entry_capture_mask)); | ||
2088 | } | ||
2089 | |||
2090 | /** | ||
2091 | * qla82xx_collect_md_data - Retrieve firmware minidump data. | ||
2092 | * @ha: pointer to adapter structure | ||
2093 | **/ | ||
2094 | static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | ||
2095 | { | ||
2096 | int num_entry_hdr = 0; | ||
2097 | struct qla82xx_minidump_entry_hdr *entry_hdr; | ||
2098 | struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; | ||
2099 | uint32_t *data_ptr; | ||
2100 | uint32_t data_collected = 0; | ||
2101 | int i, rval = QLA_ERROR; | ||
2102 | uint64_t now; | ||
2103 | uint32_t timestamp; | ||
2104 | |||
2105 | if (!ha->fw_dump) { | ||
2106 | ql4_printk(KERN_INFO, ha, "%s(%ld) No buffer to dump\n", | ||
2107 | __func__, ha->host_no); | ||
2108 | return rval; | ||
2109 | } | ||
2110 | |||
2111 | tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) | ||
2112 | ha->fw_dump_tmplt_hdr; | ||
2113 | data_ptr = (uint32_t *)((uint8_t *)ha->fw_dump + | ||
2114 | ha->fw_dump_tmplt_size); | ||
2115 | data_collected += ha->fw_dump_tmplt_size; | ||
2116 | |||
2117 | num_entry_hdr = tmplt_hdr->num_of_entries; | ||
2118 | ql4_printk(KERN_INFO, ha, "[%s]: starting data ptr: %p\n", | ||
2119 | __func__, data_ptr); | ||
2120 | ql4_printk(KERN_INFO, ha, | ||
2121 | "[%s]: no of entry headers in Template: 0x%x\n", | ||
2122 | __func__, num_entry_hdr); | ||
2123 | ql4_printk(KERN_INFO, ha, "[%s]: Capture Mask obtained: 0x%x\n", | ||
2124 | __func__, ha->fw_dump_capture_mask); | ||
2125 | ql4_printk(KERN_INFO, ha, "[%s]: Total_data_size 0x%x, %d obtained\n", | ||
2126 | __func__, ha->fw_dump_size, ha->fw_dump_size); | ||
2127 | |||
2128 | /* Update current timestamp before taking dump */ | ||
2129 | now = get_jiffies_64(); | ||
2130 | timestamp = (u32)(jiffies_to_msecs(now) / 1000); | ||
2131 | tmplt_hdr->driver_timestamp = timestamp; | ||
2132 | |||
2133 | entry_hdr = (struct qla82xx_minidump_entry_hdr *) | ||
2134 | (((uint8_t *)ha->fw_dump_tmplt_hdr) + | ||
2135 | tmplt_hdr->first_entry_offset); | ||
2136 | |||
2137 | /* Walk through the entry headers - validate/perform required action */ | ||
2138 | for (i = 0; i < num_entry_hdr; i++) { | ||
2139 | if (data_collected >= ha->fw_dump_size) { | ||
2140 | ql4_printk(KERN_INFO, ha, | ||
2141 | "Data collected: [0x%x], Total Dump size: [0x%x]\n", | ||
2142 | data_collected, ha->fw_dump_size); | ||
2143 | return rval; | ||
2144 | } | ||
2145 | |||
2146 | if (!(entry_hdr->d_ctrl.entry_capture_mask & | ||
2147 | ha->fw_dump_capture_mask)) { | ||
2148 | entry_hdr->d_ctrl.driver_flags |= | ||
2149 | QLA82XX_DBG_SKIPPED_FLAG; | ||
2150 | goto skip_nxt_entry; | ||
2151 | } | ||
2152 | |||
2153 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2154 | "Data collected: [0x%x], Dump size left:[0x%x]\n", | ||
2155 | data_collected, | ||
2156 | (ha->fw_dump_size - data_collected))); | ||
2157 | |||
2158 | /* Decode the entry type and take required action to capture | ||
2159 | * debug data | ||
2160 | */ | ||
2161 | switch (entry_hdr->entry_type) { | ||
2162 | case QLA82XX_RDEND: | ||
2163 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2164 | break; | ||
2165 | case QLA82XX_CNTRL: | ||
2166 | rval = qla4_8xxx_minidump_process_control(ha, | ||
2167 | entry_hdr); | ||
2168 | if (rval != QLA_SUCCESS) { | ||
2169 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2170 | goto md_failed; | ||
2171 | } | ||
2172 | break; | ||
2173 | case QLA82XX_RDCRB: | ||
2174 | qla4_8xxx_minidump_process_rdcrb(ha, entry_hdr, | ||
2175 | &data_ptr); | ||
2176 | break; | ||
2177 | case QLA82XX_RDMEM: | ||
2178 | rval = qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, | ||
2179 | &data_ptr); | ||
2180 | if (rval != QLA_SUCCESS) { | ||
2181 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2182 | goto md_failed; | ||
2183 | } | ||
2184 | break; | ||
2185 | case QLA82XX_BOARD: | ||
2186 | case QLA82XX_RDROM: | ||
2187 | qla4_8xxx_minidump_process_rdrom(ha, entry_hdr, | ||
2188 | &data_ptr); | ||
2189 | break; | ||
2190 | case QLA82XX_L2DTG: | ||
2191 | case QLA82XX_L2ITG: | ||
2192 | case QLA82XX_L2DAT: | ||
2193 | case QLA82XX_L2INS: | ||
2194 | rval = qla4_8xxx_minidump_process_l2tag(ha, entry_hdr, | ||
2195 | &data_ptr); | ||
2196 | if (rval != QLA_SUCCESS) { | ||
2197 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2198 | goto md_failed; | ||
2199 | } | ||
2200 | break; | ||
2201 | case QLA82XX_L1DAT: | ||
2202 | case QLA82XX_L1INS: | ||
2203 | qla4_8xxx_minidump_process_l1cache(ha, entry_hdr, | ||
2204 | &data_ptr); | ||
2205 | break; | ||
2206 | case QLA82XX_RDOCM: | ||
2207 | qla4_8xxx_minidump_process_rdocm(ha, entry_hdr, | ||
2208 | &data_ptr); | ||
2209 | break; | ||
2210 | case QLA82XX_RDMUX: | ||
2211 | qla4_8xxx_minidump_process_rdmux(ha, entry_hdr, | ||
2212 | &data_ptr); | ||
2213 | break; | ||
2214 | case QLA82XX_QUEUE: | ||
2215 | qla4_8xxx_minidump_process_queue(ha, entry_hdr, | ||
2216 | &data_ptr); | ||
2217 | break; | ||
2218 | case QLA82XX_RDNOP: | ||
2219 | default: | ||
2220 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2221 | break; | ||
2222 | } | ||
2223 | |||
2224 | data_collected = (uint8_t *)data_ptr - | ||
2225 | ((uint8_t *)((uint8_t *)ha->fw_dump + | ||
2226 | ha->fw_dump_tmplt_size)); | ||
2227 | skip_nxt_entry: | ||
2228 | /* next entry in the template */ | ||
2229 | entry_hdr = (struct qla82xx_minidump_entry_hdr *) | ||
2230 | (((uint8_t *)entry_hdr) + | ||
2231 | entry_hdr->entry_size); | ||
2232 | } | ||
2233 | |||
2234 | if ((data_collected + ha->fw_dump_tmplt_size) != ha->fw_dump_size) { | ||
2235 | ql4_printk(KERN_INFO, ha, | ||
2236 | "Dump data mismatch: Data collected: [0x%x], total_data_size:[0x%x]\n", | ||
2237 | data_collected, ha->fw_dump_size); | ||
2238 | goto md_failed; | ||
2239 | } | ||
2240 | |||
2241 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s Last entry: 0x%x\n", | ||
2242 | __func__, i)); | ||
2243 | md_failed: | ||
2244 | return rval; | ||
2245 | } | ||
2246 | |||
2247 | /** | ||
2248 | * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready. | ||
2249 | * @ha: pointer to adapter structure | ||
2250 | **/ | ||
2251 | static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code) | ||
2252 | { | ||
2253 | char event_string[40]; | ||
2254 | char *envp[] = { event_string, NULL }; | ||
2255 | |||
2256 | switch (code) { | ||
2257 | case QL4_UEVENT_CODE_FW_DUMP: | ||
2258 | snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", | ||
2259 | ha->host_no); | ||
2260 | break; | ||
2261 | default: | ||
2262 | /*do nothing*/ | ||
2263 | break; | ||
2264 | } | ||
2265 | |||
2266 | kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp); | ||
2267 | } | ||
2268 | |||
1604 | /** | 2269 | /** |
1605 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw | 2270 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw |
1606 | * @ha: pointer to adapter structure | 2271 | * @ha: pointer to adapter structure |
@@ -1659,6 +2324,15 @@ dev_initialize: | |||
1659 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); | 2324 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); |
1660 | 2325 | ||
1661 | qla4_8xxx_idc_unlock(ha); | 2326 | qla4_8xxx_idc_unlock(ha); |
2327 | if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) && | ||
2328 | !test_and_set_bit(AF_82XX_FW_DUMPED, &ha->flags)) { | ||
2329 | if (!qla4_8xxx_collect_md_data(ha)) { | ||
2330 | qla4_8xxx_uevent_emit(ha, QL4_UEVENT_CODE_FW_DUMP); | ||
2331 | } else { | ||
2332 | ql4_printk(KERN_INFO, ha, "Unable to collect minidump\n"); | ||
2333 | clear_bit(AF_82XX_FW_DUMPED, &ha->flags); | ||
2334 | } | ||
2335 | } | ||
1662 | rval = qla4_8xxx_try_start_fw(ha); | 2336 | rval = qla4_8xxx_try_start_fw(ha); |
1663 | qla4_8xxx_idc_lock(ha); | 2337 | qla4_8xxx_idc_lock(ha); |
1664 | 2338 | ||
@@ -1686,6 +2360,7 @@ static void | |||
1686 | qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | 2360 | qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) |
1687 | { | 2361 | { |
1688 | uint32_t dev_state, drv_state, drv_active; | 2362 | uint32_t dev_state, drv_state, drv_active; |
2363 | uint32_t active_mask = 0xFFFFFFFF; | ||
1689 | unsigned long reset_timeout; | 2364 | unsigned long reset_timeout; |
1690 | 2365 | ||
1691 | ql4_printk(KERN_INFO, ha, | 2366 | ql4_printk(KERN_INFO, ha, |
@@ -1697,7 +2372,14 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | |||
1697 | qla4_8xxx_idc_lock(ha); | 2372 | qla4_8xxx_idc_lock(ha); |
1698 | } | 2373 | } |
1699 | 2374 | ||
1700 | qla4_8xxx_set_rst_ready(ha); | 2375 | if (!test_bit(AF_82XX_RST_OWNER, &ha->flags)) { |
2376 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2377 | "%s(%ld): reset acknowledged\n", | ||
2378 | __func__, ha->host_no)); | ||
2379 | qla4_8xxx_set_rst_ready(ha); | ||
2380 | } else { | ||
2381 | active_mask = (~(1 << (ha->func_num * 4))); | ||
2382 | } | ||
1701 | 2383 | ||
1702 | /* wait for 10 seconds for reset ack from all functions */ | 2384 | /* wait for 10 seconds for reset ack from all functions */ |
1703 | reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); | 2385 | reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); |
@@ -1709,12 +2391,24 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | |||
1709 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", | 2391 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", |
1710 | __func__, ha->host_no, drv_state, drv_active); | 2392 | __func__, ha->host_no, drv_state, drv_active); |
1711 | 2393 | ||
1712 | while (drv_state != drv_active) { | 2394 | while (drv_state != (drv_active & active_mask)) { |
1713 | if (time_after_eq(jiffies, reset_timeout)) { | 2395 | if (time_after_eq(jiffies, reset_timeout)) { |
1714 | printk("%s: RESET TIMEOUT!\n", DRIVER_NAME); | 2396 | ql4_printk(KERN_INFO, ha, |
2397 | "%s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n", | ||
2398 | DRIVER_NAME, drv_state, drv_active); | ||
1715 | break; | 2399 | break; |
1716 | } | 2400 | } |
1717 | 2401 | ||
2402 | /* | ||
2403 | * When reset_owner times out, check which functions | ||
2404 | * acked/did not ack | ||
2405 | */ | ||
2406 | if (test_bit(AF_82XX_RST_OWNER, &ha->flags)) { | ||
2407 | ql4_printk(KERN_INFO, ha, | ||
2408 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", | ||
2409 | __func__, ha->host_no, drv_state, | ||
2410 | drv_active); | ||
2411 | } | ||
1718 | qla4_8xxx_idc_unlock(ha); | 2412 | qla4_8xxx_idc_unlock(ha); |
1719 | msleep(1000); | 2413 | msleep(1000); |
1720 | qla4_8xxx_idc_lock(ha); | 2414 | qla4_8xxx_idc_lock(ha); |
@@ -1723,14 +2417,18 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | |||
1723 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 2417 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
1724 | } | 2418 | } |
1725 | 2419 | ||
2420 | /* Clear RESET OWNER as we are not going to use it any further */ | ||
2421 | clear_bit(AF_82XX_RST_OWNER, &ha->flags); | ||
2422 | |||
1726 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2423 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1727 | ql4_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, | 2424 | ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", dev_state, |
1728 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | 2425 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); |
1729 | 2426 | ||
1730 | /* Force to DEV_COLD unless someone else is starting a reset */ | 2427 | /* Force to DEV_COLD unless someone else is starting a reset */ |
1731 | if (dev_state != QLA82XX_DEV_INITIALIZING) { | 2428 | if (dev_state != QLA82XX_DEV_INITIALIZING) { |
1732 | ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); | 2429 | ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); |
1733 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); | 2430 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); |
2431 | qla4_8xxx_set_rst_ready(ha); | ||
1734 | } | 2432 | } |
1735 | } | 2433 | } |
1736 | 2434 | ||
@@ -1765,8 +2463,9 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1765 | } | 2463 | } |
1766 | 2464 | ||
1767 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2465 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1768 | ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, | 2466 | DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", |
1769 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | 2467 | dev_state, dev_state < MAX_STATES ? |
2468 | qdev_state[dev_state] : "Unknown")); | ||
1770 | 2469 | ||
1771 | /* wait for 30 seconds for device to go ready */ | 2470 | /* wait for 30 seconds for device to go ready */ |
1772 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); | 2471 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); |
@@ -1775,15 +2474,19 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1775 | while (1) { | 2474 | while (1) { |
1776 | 2475 | ||
1777 | if (time_after_eq(jiffies, dev_init_timeout)) { | 2476 | if (time_after_eq(jiffies, dev_init_timeout)) { |
1778 | ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); | 2477 | ql4_printk(KERN_WARNING, ha, |
2478 | "%s: Device Init Failed 0x%x = %s\n", | ||
2479 | DRIVER_NAME, | ||
2480 | dev_state, dev_state < MAX_STATES ? | ||
2481 | qdev_state[dev_state] : "Unknown"); | ||
1779 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 2482 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
1780 | QLA82XX_DEV_FAILED); | 2483 | QLA82XX_DEV_FAILED); |
1781 | } | 2484 | } |
1782 | 2485 | ||
1783 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2486 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1784 | ql4_printk(KERN_INFO, ha, | 2487 | ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", |
1785 | "2:Device state is 0x%x = %s\n", dev_state, | 2488 | dev_state, dev_state < MAX_STATES ? |
1786 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | 2489 | qdev_state[dev_state] : "Unknown"); |
1787 | 2490 | ||
1788 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ | 2491 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ |
1789 | switch (dev_state) { | 2492 | switch (dev_state) { |
@@ -2184,6 +2887,7 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | |||
2184 | ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); | 2887 | ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); |
2185 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 2888 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
2186 | QLA82XX_DEV_NEED_RESET); | 2889 | QLA82XX_DEV_NEED_RESET); |
2890 | set_bit(AF_82XX_RST_OWNER, &ha->flags); | ||
2187 | } else | 2891 | } else |
2188 | ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); | 2892 | ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); |
2189 | 2893 | ||
@@ -2195,8 +2899,10 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | |||
2195 | qla4_8xxx_clear_rst_ready(ha); | 2899 | qla4_8xxx_clear_rst_ready(ha); |
2196 | qla4_8xxx_idc_unlock(ha); | 2900 | qla4_8xxx_idc_unlock(ha); |
2197 | 2901 | ||
2198 | if (rval == QLA_SUCCESS) | 2902 | if (rval == QLA_SUCCESS) { |
2903 | ql4_printk(KERN_INFO, ha, "Clearing AF_RECOVERY in qla4_8xxx_isp_reset\n"); | ||
2199 | clear_bit(AF_FW_RECOVERY, &ha->flags); | 2904 | clear_bit(AF_FW_RECOVERY, &ha->flags); |
2905 | } | ||
2200 | 2906 | ||
2201 | return rval; | 2907 | return rval; |
2202 | } | 2908 | } |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index dc7500e47b8b..30258479f100 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h | |||
@@ -792,4 +792,196 @@ struct crb_addr_pair { | |||
792 | #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) | 792 | #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) |
793 | #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) | 793 | #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) |
794 | 794 | ||
795 | /* Minidump related */ | ||
796 | |||
797 | /* Entry Type Defines */ | ||
798 | #define QLA82XX_RDNOP 0 | ||
799 | #define QLA82XX_RDCRB 1 | ||
800 | #define QLA82XX_RDMUX 2 | ||
801 | #define QLA82XX_QUEUE 3 | ||
802 | #define QLA82XX_BOARD 4 | ||
803 | #define QLA82XX_RDOCM 6 | ||
804 | #define QLA82XX_PREGS 7 | ||
805 | #define QLA82XX_L1DTG 8 | ||
806 | #define QLA82XX_L1ITG 9 | ||
807 | #define QLA82XX_L1DAT 11 | ||
808 | #define QLA82XX_L1INS 12 | ||
809 | #define QLA82XX_L2DTG 21 | ||
810 | #define QLA82XX_L2ITG 22 | ||
811 | #define QLA82XX_L2DAT 23 | ||
812 | #define QLA82XX_L2INS 24 | ||
813 | #define QLA82XX_RDROM 71 | ||
814 | #define QLA82XX_RDMEM 72 | ||
815 | #define QLA82XX_CNTRL 98 | ||
816 | #define QLA82XX_RDEND 255 | ||
817 | |||
818 | /* Opcodes for Control Entries. | ||
819 | * These Flags are bit fields. | ||
820 | */ | ||
821 | #define QLA82XX_DBG_OPCODE_WR 0x01 | ||
822 | #define QLA82XX_DBG_OPCODE_RW 0x02 | ||
823 | #define QLA82XX_DBG_OPCODE_AND 0x04 | ||
824 | #define QLA82XX_DBG_OPCODE_OR 0x08 | ||
825 | #define QLA82XX_DBG_OPCODE_POLL 0x10 | ||
826 | #define QLA82XX_DBG_OPCODE_RDSTATE 0x20 | ||
827 | #define QLA82XX_DBG_OPCODE_WRSTATE 0x40 | ||
828 | #define QLA82XX_DBG_OPCODE_MDSTATE 0x80 | ||
829 | |||
830 | /* Driver Flags */ | ||
831 | #define QLA82XX_DBG_SKIPPED_FLAG 0x80 /* driver skipped this entry */ | ||
832 | #define QLA82XX_DBG_SIZE_ERR_FLAG 0x40 /* Entry vs Capture size | ||
833 | * mismatch */ | ||
834 | |||
835 | /* Driver_code is for driver to write some info about the entry | ||
836 | * currently not used. | ||
837 | */ | ||
838 | struct qla82xx_minidump_entry_hdr { | ||
839 | uint32_t entry_type; | ||
840 | uint32_t entry_size; | ||
841 | uint32_t entry_capture_size; | ||
842 | struct { | ||
843 | uint8_t entry_capture_mask; | ||
844 | uint8_t entry_code; | ||
845 | uint8_t driver_code; | ||
846 | uint8_t driver_flags; | ||
847 | } d_ctrl; | ||
848 | }; | ||
849 | |||
850 | /* Read CRB entry header */ | ||
851 | struct qla82xx_minidump_entry_crb { | ||
852 | struct qla82xx_minidump_entry_hdr h; | ||
853 | uint32_t addr; | ||
854 | struct { | ||
855 | uint8_t addr_stride; | ||
856 | uint8_t state_index_a; | ||
857 | uint16_t poll_timeout; | ||
858 | } crb_strd; | ||
859 | uint32_t data_size; | ||
860 | uint32_t op_count; | ||
861 | |||
862 | struct { | ||
863 | uint8_t opcode; | ||
864 | uint8_t state_index_v; | ||
865 | uint8_t shl; | ||
866 | uint8_t shr; | ||
867 | } crb_ctrl; | ||
868 | |||
869 | uint32_t value_1; | ||
870 | uint32_t value_2; | ||
871 | uint32_t value_3; | ||
872 | }; | ||
873 | |||
874 | struct qla82xx_minidump_entry_cache { | ||
875 | struct qla82xx_minidump_entry_hdr h; | ||
876 | uint32_t tag_reg_addr; | ||
877 | struct { | ||
878 | uint16_t tag_value_stride; | ||
879 | uint16_t init_tag_value; | ||
880 | } addr_ctrl; | ||
881 | uint32_t data_size; | ||
882 | uint32_t op_count; | ||
883 | uint32_t control_addr; | ||
884 | struct { | ||
885 | uint16_t write_value; | ||
886 | uint8_t poll_mask; | ||
887 | uint8_t poll_wait; | ||
888 | } cache_ctrl; | ||
889 | uint32_t read_addr; | ||
890 | struct { | ||
891 | uint8_t read_addr_stride; | ||
892 | uint8_t read_addr_cnt; | ||
893 | uint16_t rsvd_1; | ||
894 | } read_ctrl; | ||
895 | }; | ||
896 | |||
897 | /* Read OCM */ | ||
898 | struct qla82xx_minidump_entry_rdocm { | ||
899 | struct qla82xx_minidump_entry_hdr h; | ||
900 | uint32_t rsvd_0; | ||
901 | uint32_t rsvd_1; | ||
902 | uint32_t data_size; | ||
903 | uint32_t op_count; | ||
904 | uint32_t rsvd_2; | ||
905 | uint32_t rsvd_3; | ||
906 | uint32_t read_addr; | ||
907 | uint32_t read_addr_stride; | ||
908 | }; | ||
909 | |||
910 | /* Read Memory */ | ||
911 | struct qla82xx_minidump_entry_rdmem { | ||
912 | struct qla82xx_minidump_entry_hdr h; | ||
913 | uint32_t rsvd[6]; | ||
914 | uint32_t read_addr; | ||
915 | uint32_t read_data_size; | ||
916 | }; | ||
917 | |||
918 | /* Read ROM */ | ||
919 | struct qla82xx_minidump_entry_rdrom { | ||
920 | struct qla82xx_minidump_entry_hdr h; | ||
921 | uint32_t rsvd[6]; | ||
922 | uint32_t read_addr; | ||
923 | uint32_t read_data_size; | ||
924 | }; | ||
925 | |||
926 | /* Mux entry */ | ||
927 | struct qla82xx_minidump_entry_mux { | ||
928 | struct qla82xx_minidump_entry_hdr h; | ||
929 | uint32_t select_addr; | ||
930 | uint32_t rsvd_0; | ||
931 | uint32_t data_size; | ||
932 | uint32_t op_count; | ||
933 | uint32_t select_value; | ||
934 | uint32_t select_value_stride; | ||
935 | uint32_t read_addr; | ||
936 | uint32_t rsvd_1; | ||
937 | }; | ||
938 | |||
939 | /* Queue entry */ | ||
940 | struct qla82xx_minidump_entry_queue { | ||
941 | struct qla82xx_minidump_entry_hdr h; | ||
942 | uint32_t select_addr; | ||
943 | struct { | ||
944 | uint16_t queue_id_stride; | ||
945 | uint16_t rsvd_0; | ||
946 | } q_strd; | ||
947 | uint32_t data_size; | ||
948 | uint32_t op_count; | ||
949 | uint32_t rsvd_1; | ||
950 | uint32_t rsvd_2; | ||
951 | uint32_t read_addr; | ||
952 | struct { | ||
953 | uint8_t read_addr_stride; | ||
954 | uint8_t read_addr_cnt; | ||
955 | uint16_t rsvd_3; | ||
956 | } rd_strd; | ||
957 | }; | ||
958 | |||
959 | #define QLA82XX_MINIDUMP_OCM0_SIZE (256 * 1024) | ||
960 | #define QLA82XX_MINIDUMP_L1C_SIZE (256 * 1024) | ||
961 | #define QLA82XX_MINIDUMP_L2C_SIZE 1572864 | ||
962 | #define QLA82XX_MINIDUMP_COMMON_STR_SIZE 0 | ||
963 | #define QLA82XX_MINIDUMP_FCOE_STR_SIZE 0 | ||
964 | #define QLA82XX_MINIDUMP_MEM_SIZE 0 | ||
965 | #define QLA82XX_MAX_ENTRY_HDR 4 | ||
966 | |||
967 | struct qla82xx_minidump { | ||
968 | uint32_t md_ocm0_data[QLA82XX_MINIDUMP_OCM0_SIZE]; | ||
969 | uint32_t md_l1c_data[QLA82XX_MINIDUMP_L1C_SIZE]; | ||
970 | uint32_t md_l2c_data[QLA82XX_MINIDUMP_L2C_SIZE]; | ||
971 | uint32_t md_cs_data[QLA82XX_MINIDUMP_COMMON_STR_SIZE]; | ||
972 | uint32_t md_fcoes_data[QLA82XX_MINIDUMP_FCOE_STR_SIZE]; | ||
973 | uint32_t md_mem_data[QLA82XX_MINIDUMP_MEM_SIZE]; | ||
974 | }; | ||
975 | |||
976 | #define MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE 0x129 | ||
977 | #define RQST_TMPLT_SIZE 0x0 | ||
978 | #define RQST_TMPLT 0x1 | ||
979 | #define MD_DIRECT_ROM_WINDOW 0x42110030 | ||
980 | #define MD_DIRECT_ROM_READ_BASE 0x42150000 | ||
981 | #define MD_MIU_TEST_AGT_CTRL 0x41000090 | ||
982 | #define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 | ||
983 | #define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 | ||
984 | |||
985 | static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, | ||
986 | 0x410000AC, 0x410000B8, 0x410000BC }; | ||
795 | #endif | 987 | #endif |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ee47820c30a6..cd15678f9ada 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -68,12 +68,34 @@ MODULE_PARM_DESC(ql4xmaxqdepth, | |||
68 | " Maximum queue depth to report for target devices.\n" | 68 | " Maximum queue depth to report for target devices.\n" |
69 | "\t\t Default: 32."); | 69 | "\t\t Default: 32."); |
70 | 70 | ||
71 | static int ql4xqfulltracking = 1; | ||
72 | module_param(ql4xqfulltracking, int, S_IRUGO | S_IWUSR); | ||
73 | MODULE_PARM_DESC(ql4xqfulltracking, | ||
74 | " Enable or disable dynamic tracking and adjustment of\n" | ||
75 | "\t\t scsi device queue depth.\n" | ||
76 | "\t\t 0 - Disable.\n" | ||
77 | "\t\t 1 - Enable. (Default)"); | ||
78 | |||
71 | static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; | 79 | static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; |
72 | module_param(ql4xsess_recovery_tmo, int, S_IRUGO); | 80 | module_param(ql4xsess_recovery_tmo, int, S_IRUGO); |
73 | MODULE_PARM_DESC(ql4xsess_recovery_tmo, | 81 | MODULE_PARM_DESC(ql4xsess_recovery_tmo, |
74 | " Target Session Recovery Timeout.\n" | 82 | " Target Session Recovery Timeout.\n" |
75 | "\t\t Default: 120 sec."); | 83 | "\t\t Default: 120 sec."); |
76 | 84 | ||
85 | int ql4xmdcapmask = 0x1F; | ||
86 | module_param(ql4xmdcapmask, int, S_IRUGO); | ||
87 | MODULE_PARM_DESC(ql4xmdcapmask, | ||
88 | " Set the Minidump driver capture mask level.\n" | ||
89 | "\t\t Default is 0x1F.\n" | ||
90 | "\t\t Can be set to 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F"); | ||
91 | |||
92 | int ql4xenablemd = 1; | ||
93 | module_param(ql4xenablemd, int, S_IRUGO | S_IWUSR); | ||
94 | MODULE_PARM_DESC(ql4xenablemd, | ||
95 | " Set to enable minidump.\n" | ||
96 | "\t\t 0 - disable minidump\n" | ||
97 | "\t\t 1 - enable minidump (Default)"); | ||
98 | |||
77 | static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); | 99 | static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); |
78 | /* | 100 | /* |
79 | * SCSI host template entry points | 101 | * SCSI host template entry points |
@@ -140,6 +162,8 @@ static int qla4xxx_slave_configure(struct scsi_device *device); | |||
140 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); | 162 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); |
141 | static umode_t ql4_attr_is_visible(int param_type, int param); | 163 | static umode_t ql4_attr_is_visible(int param_type, int param); |
142 | static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); | 164 | static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); |
165 | static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, | ||
166 | int reason); | ||
143 | 167 | ||
144 | static struct qla4_8xxx_legacy_intr_set legacy_intr[] = | 168 | static struct qla4_8xxx_legacy_intr_set legacy_intr[] = |
145 | QLA82XX_LEGACY_INTR_CONFIG; | 169 | QLA82XX_LEGACY_INTR_CONFIG; |
@@ -159,6 +183,7 @@ static struct scsi_host_template qla4xxx_driver_template = { | |||
159 | .slave_configure = qla4xxx_slave_configure, | 183 | .slave_configure = qla4xxx_slave_configure, |
160 | .slave_alloc = qla4xxx_slave_alloc, | 184 | .slave_alloc = qla4xxx_slave_alloc, |
161 | .slave_destroy = qla4xxx_slave_destroy, | 185 | .slave_destroy = qla4xxx_slave_destroy, |
186 | .change_queue_depth = qla4xxx_change_queue_depth, | ||
162 | 187 | ||
163 | .this_id = -1, | 188 | .this_id = -1, |
164 | .cmd_per_lun = 3, | 189 | .cmd_per_lun = 3, |
@@ -1555,19 +1580,53 @@ static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess) | |||
1555 | struct iscsi_session *sess; | 1580 | struct iscsi_session *sess; |
1556 | struct ddb_entry *ddb_entry; | 1581 | struct ddb_entry *ddb_entry; |
1557 | struct scsi_qla_host *ha; | 1582 | struct scsi_qla_host *ha; |
1558 | unsigned long flags; | 1583 | unsigned long flags, wtime; |
1584 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
1585 | dma_addr_t fw_ddb_entry_dma; | ||
1586 | uint32_t ddb_state; | ||
1587 | int ret; | ||
1559 | 1588 | ||
1560 | DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); | 1589 | DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); |
1561 | sess = cls_sess->dd_data; | 1590 | sess = cls_sess->dd_data; |
1562 | ddb_entry = sess->dd_data; | 1591 | ddb_entry = sess->dd_data; |
1563 | ha = ddb_entry->ha; | 1592 | ha = ddb_entry->ha; |
1564 | 1593 | ||
1594 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
1595 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
1596 | if (!fw_ddb_entry) { | ||
1597 | ql4_printk(KERN_ERR, ha, | ||
1598 | "%s: Unable to allocate dma buffer\n", __func__); | ||
1599 | goto destroy_session; | ||
1600 | } | ||
1601 | |||
1602 | wtime = jiffies + (HZ * LOGOUT_TOV); | ||
1603 | do { | ||
1604 | ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, | ||
1605 | fw_ddb_entry, fw_ddb_entry_dma, | ||
1606 | NULL, NULL, &ddb_state, NULL, | ||
1607 | NULL, NULL); | ||
1608 | if (ret == QLA_ERROR) | ||
1609 | goto destroy_session; | ||
1610 | |||
1611 | if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || | ||
1612 | (ddb_state == DDB_DS_SESSION_FAILED)) | ||
1613 | goto destroy_session; | ||
1614 | |||
1615 | schedule_timeout_uninterruptible(HZ); | ||
1616 | } while ((time_after(wtime, jiffies))); | ||
1617 | |||
1618 | destroy_session: | ||
1565 | qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); | 1619 | qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); |
1566 | 1620 | ||
1567 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1621 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1568 | qla4xxx_free_ddb(ha, ddb_entry); | 1622 | qla4xxx_free_ddb(ha, ddb_entry); |
1569 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1623 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1624 | |||
1570 | iscsi_session_teardown(cls_sess); | 1625 | iscsi_session_teardown(cls_sess); |
1626 | |||
1627 | if (fw_ddb_entry) | ||
1628 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
1629 | fw_ddb_entry, fw_ddb_entry_dma); | ||
1571 | } | 1630 | } |
1572 | 1631 | ||
1573 | static struct iscsi_cls_conn * | 1632 | static struct iscsi_cls_conn * |
@@ -2220,6 +2279,9 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) | |||
2220 | dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues, | 2279 | dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues, |
2221 | ha->queues_dma); | 2280 | ha->queues_dma); |
2222 | 2281 | ||
2282 | if (ha->fw_dump) | ||
2283 | vfree(ha->fw_dump); | ||
2284 | |||
2223 | ha->queues_len = 0; | 2285 | ha->queues_len = 0; |
2224 | ha->queues = NULL; | 2286 | ha->queues = NULL; |
2225 | ha->queues_dma = 0; | 2287 | ha->queues_dma = 0; |
@@ -2229,6 +2291,8 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) | |||
2229 | ha->response_dma = 0; | 2291 | ha->response_dma = 0; |
2230 | ha->shadow_regs = NULL; | 2292 | ha->shadow_regs = NULL; |
2231 | ha->shadow_regs_dma = 0; | 2293 | ha->shadow_regs_dma = 0; |
2294 | ha->fw_dump = NULL; | ||
2295 | ha->fw_dump_size = 0; | ||
2232 | 2296 | ||
2233 | /* Free srb pool. */ | 2297 | /* Free srb pool. */ |
2234 | if (ha->srb_mempool) | 2298 | if (ha->srb_mempool) |
@@ -5023,6 +5087,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
5023 | 5087 | ||
5024 | set_bit(AF_INIT_DONE, &ha->flags); | 5088 | set_bit(AF_INIT_DONE, &ha->flags); |
5025 | 5089 | ||
5090 | qla4_8xxx_alloc_sysfs_attr(ha); | ||
5091 | |||
5026 | printk(KERN_INFO | 5092 | printk(KERN_INFO |
5027 | " QLogic iSCSI HBA Driver version: %s\n" | 5093 | " QLogic iSCSI HBA Driver version: %s\n" |
5028 | " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", | 5094 | " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", |
@@ -5149,6 +5215,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
5149 | iscsi_boot_destroy_kset(ha->boot_kset); | 5215 | iscsi_boot_destroy_kset(ha->boot_kset); |
5150 | 5216 | ||
5151 | qla4xxx_destroy_fw_ddb_session(ha); | 5217 | qla4xxx_destroy_fw_ddb_session(ha); |
5218 | qla4_8xxx_free_sysfs_attr(ha); | ||
5152 | 5219 | ||
5153 | scsi_remove_host(ha->host); | 5220 | scsi_remove_host(ha->host); |
5154 | 5221 | ||
@@ -5217,6 +5284,15 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) | |||
5217 | scsi_deactivate_tcq(sdev, 1); | 5284 | scsi_deactivate_tcq(sdev, 1); |
5218 | } | 5285 | } |
5219 | 5286 | ||
5287 | static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, | ||
5288 | int reason) | ||
5289 | { | ||
5290 | if (!ql4xqfulltracking) | ||
5291 | return -EOPNOTSUPP; | ||
5292 | |||
5293 | return iscsi_change_queue_depth(sdev, qdepth, reason); | ||
5294 | } | ||
5295 | |||
5220 | /** | 5296 | /** |
5221 | * qla4xxx_del_from_active_array - returns an active srb | 5297 | * qla4xxx_del_from_active_array - returns an active srb |
5222 | * @ha: Pointer to host adapter structure. | 5298 | * @ha: Pointer to host adapter structure. |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 97b30c108e36..cc1cc3518b87 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,4 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k16" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k17" |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 62ddfd31d4ce..6dfb9785d345 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1378,16 +1378,19 @@ static int scsi_lld_busy(struct request_queue *q) | |||
1378 | { | 1378 | { |
1379 | struct scsi_device *sdev = q->queuedata; | 1379 | struct scsi_device *sdev = q->queuedata; |
1380 | struct Scsi_Host *shost; | 1380 | struct Scsi_Host *shost; |
1381 | struct scsi_target *starget; | ||
1382 | 1381 | ||
1383 | if (!sdev) | 1382 | if (!sdev) |
1384 | return 0; | 1383 | return 0; |
1385 | 1384 | ||
1386 | shost = sdev->host; | 1385 | shost = sdev->host; |
1387 | starget = scsi_target(sdev); | ||
1388 | 1386 | ||
1389 | if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) || | 1387 | /* |
1390 | scsi_target_is_busy(starget) || scsi_device_is_busy(sdev)) | 1388 | * Ignore host/starget busy state. |
1389 | * Since block layer does not have a concept of fairness across | ||
1390 | * multiple queues, congestion of host/starget needs to be handled | ||
1391 | * in SCSI layer. | ||
1392 | */ | ||
1393 | if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev)) | ||
1391 | return 1; | 1394 | return 1; |
1392 | 1395 | ||
1393 | return 0; | 1396 | return 0; |
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index f661a41fa4c6..d4201ded3b22 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c | |||
@@ -24,8 +24,11 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) | |||
24 | err = scsi_device_quiesce(to_scsi_device(dev)); | 24 | err = scsi_device_quiesce(to_scsi_device(dev)); |
25 | if (err == 0) { | 25 | if (err == 0) { |
26 | drv = dev->driver; | 26 | drv = dev->driver; |
27 | if (drv && drv->suspend) | 27 | if (drv && drv->suspend) { |
28 | err = drv->suspend(dev, msg); | 28 | err = drv->suspend(dev, msg); |
29 | if (err) | ||
30 | scsi_device_resume(to_scsi_device(dev)); | ||
31 | } | ||
29 | } | 32 | } |
30 | dev_dbg(dev, "scsi suspend: %d\n", err); | 33 | dev_dbg(dev, "scsi suspend: %d\n", err); |
31 | return err; | 34 | return err; |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 01b03744f1f9..2e5fe584aad3 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -147,7 +147,7 @@ int scsi_complete_async_scans(void) | |||
147 | 147 | ||
148 | do { | 148 | do { |
149 | if (list_empty(&scanning_hosts)) | 149 | if (list_empty(&scanning_hosts)) |
150 | return 0; | 150 | goto out; |
151 | /* If we can't get memory immediately, that's OK. Just | 151 | /* If we can't get memory immediately, that's OK. Just |
152 | * sleep a little. Even if we never get memory, the async | 152 | * sleep a little. Even if we never get memory, the async |
153 | * scans will finish eventually. | 153 | * scans will finish eventually. |
@@ -179,8 +179,11 @@ int scsi_complete_async_scans(void) | |||
179 | } | 179 | } |
180 | done: | 180 | done: |
181 | spin_unlock(&async_scan_lock); | 181 | spin_unlock(&async_scan_lock); |
182 | |||
183 | kfree(data); | 182 | kfree(data); |
183 | |||
184 | out: | ||
185 | async_synchronize_full_domain(&scsi_sd_probe_domain); | ||
186 | |||
184 | return 0; | 187 | return 0; |
185 | } | 188 | } |
186 | 189 | ||
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c index 74708fcaf82f..ae7814874618 100644 --- a/drivers/scsi/scsi_wait_scan.c +++ b/drivers/scsi/scsi_wait_scan.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <scsi/scsi_scan.h> | 15 | #include "scsi_priv.h" |
16 | 16 | ||
17 | static int __init wait_scan_init(void) | 17 | static int __init wait_scan_init(void) |
18 | { | 18 | { |
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4e010b727818..6a4fd00117ca 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -1836,7 +1836,7 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1836 | err = pci_request_regions(pdev, UFSHCD); | 1836 | err = pci_request_regions(pdev, UFSHCD); |
1837 | if (err < 0) { | 1837 | if (err < 0) { |
1838 | dev_err(&pdev->dev, "request regions failed\n"); | 1838 | dev_err(&pdev->dev, "request regions failed\n"); |
1839 | goto out_disable; | 1839 | goto out_host_put; |
1840 | } | 1840 | } |
1841 | 1841 | ||
1842 | hba->mmio_base = pci_ioremap_bar(pdev, 0); | 1842 | hba->mmio_base = pci_ioremap_bar(pdev, 0); |
@@ -1925,8 +1925,9 @@ out_iounmap: | |||
1925 | iounmap(hba->mmio_base); | 1925 | iounmap(hba->mmio_base); |
1926 | out_release_regions: | 1926 | out_release_regions: |
1927 | pci_release_regions(pdev); | 1927 | pci_release_regions(pdev); |
1928 | out_disable: | 1928 | out_host_put: |
1929 | scsi_host_put(host); | 1929 | scsi_host_put(host); |
1930 | out_disable: | ||
1930 | pci_clear_master(pdev); | 1931 | pci_clear_master(pdev); |
1931 | pci_disable_device(pdev); | 1932 | pci_disable_device(pdev); |
1932 | out_error: | 1933 | out_error: |