aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_elsct.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libfc/fc_elsct.c')
-rw-r--r--drivers/scsi/libfc/fc_elsct.c79
1 files changed, 60 insertions, 19 deletions
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index 5cfa68732e9d..53748724f2c5 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -28,17 +28,22 @@
28#include <scsi/libfc.h> 28#include <scsi/libfc.h>
29#include <scsi/fc_encode.h> 29#include <scsi/fc_encode.h>
30 30
31/* 31/**
32 * fc_elsct_send - sends ELS/CT frame 32 * fc_elsct_send() - Send an ELS or CT frame
33 * @lport: The local port to send the frame on
34 * @did: The destination ID for the frame
35 * @fp: The frame to be sent
36 * @op: The operational code
37 * @resp: The callback routine when the response is received
38 * @arg: The argument to pass to the response callback routine
39 * @timer_msec: The timeout period for the frame (in msecs)
33 */ 40 */
34static struct fc_seq *fc_elsct_send(struct fc_lport *lport, 41struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did,
35 u32 did, 42 struct fc_frame *fp, unsigned int op,
36 struct fc_frame *fp, 43 void (*resp)(struct fc_seq *,
37 unsigned int op, 44 struct fc_frame *,
38 void (*resp)(struct fc_seq *, 45 void *),
39 struct fc_frame *fp, 46 void *arg, u32 timer_msec)
40 void *arg),
41 void *arg, u32 timer_msec)
42{ 47{
43 enum fc_rctl r_ctl; 48 enum fc_rctl r_ctl;
44 enum fc_fh_type fh_type; 49 enum fc_fh_type fh_type;
@@ -53,15 +58,22 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport,
53 did = FC_FID_DIR_SERV; 58 did = FC_FID_DIR_SERV;
54 } 59 }
55 60
56 if (rc) 61 if (rc) {
62 fc_frame_free(fp);
57 return NULL; 63 return NULL;
64 }
58 65
59 fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type, 66 fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type,
60 FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); 67 FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
61 68
62 return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); 69 return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec);
63} 70}
71EXPORT_SYMBOL(fc_elsct_send);
64 72
73/**
74 * fc_elsct_init() - Initialize the ELS/CT layer
75 * @lport: The local port to initialize the ELS/CT layer for
76 */
65int fc_elsct_init(struct fc_lport *lport) 77int fc_elsct_init(struct fc_lport *lport)
66{ 78{
67 if (!lport->tt.elsct_send) 79 if (!lport->tt.elsct_send)
@@ -72,12 +84,15 @@ int fc_elsct_init(struct fc_lport *lport)
72EXPORT_SYMBOL(fc_elsct_init); 84EXPORT_SYMBOL(fc_elsct_init);
73 85
74/** 86/**
75 * fc_els_resp_type() - return string describing ELS response for debug. 87 * fc_els_resp_type() - Return a string describing the ELS response
76 * @fp: frame pointer with possible error code. 88 * @fp: The frame pointer or possible error code
77 */ 89 */
78const char *fc_els_resp_type(struct fc_frame *fp) 90const char *fc_els_resp_type(struct fc_frame *fp)
79{ 91{
80 const char *msg; 92 const char *msg;
93 struct fc_frame_header *fh;
94 struct fc_ct_hdr *ct;
95
81 if (IS_ERR(fp)) { 96 if (IS_ERR(fp)) {
82 switch (-PTR_ERR(fp)) { 97 switch (-PTR_ERR(fp)) {
83 case FC_NO_ERR: 98 case FC_NO_ERR:
@@ -94,15 +109,41 @@ const char *fc_els_resp_type(struct fc_frame *fp)
94 break; 109 break;
95 } 110 }
96 } else { 111 } else {
97 switch (fc_frame_payload_op(fp)) { 112 fh = fc_frame_header_get(fp);
98 case ELS_LS_ACC: 113 switch (fh->fh_type) {
99 msg = "accept"; 114 case FC_TYPE_ELS:
115 switch (fc_frame_payload_op(fp)) {
116 case ELS_LS_ACC:
117 msg = "accept";
118 break;
119 case ELS_LS_RJT:
120 msg = "reject";
121 break;
122 default:
123 msg = "response unknown ELS";
124 break;
125 }
100 break; 126 break;
101 case ELS_LS_RJT: 127 case FC_TYPE_CT:
102 msg = "reject"; 128 ct = fc_frame_payload_get(fp, sizeof(*ct));
129 if (ct) {
130 switch (ntohs(ct->ct_cmd)) {
131 case FC_FS_ACC:
132 msg = "CT accept";
133 break;
134 case FC_FS_RJT:
135 msg = "CT reject";
136 break;
137 default:
138 msg = "response unknown CT";
139 break;
140 }
141 } else {
142 msg = "short CT response";
143 }
103 break; 144 break;
104 default: 145 default:
105 msg = "response unknown ELS"; 146 msg = "response not ELS or CT";
106 break; 147 break;
107 } 148 }
108 } 149 }