diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_elsct.c')
-rw-r--r-- | drivers/scsi/libfc/fc_elsct.c | 79 |
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 | */ |
34 | static struct fc_seq *fc_elsct_send(struct fc_lport *lport, | 41 | struct 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 | } |
71 | EXPORT_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 | */ | ||
65 | int fc_elsct_init(struct fc_lport *lport) | 77 | int 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) | |||
72 | EXPORT_SYMBOL(fc_elsct_init); | 84 | EXPORT_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 | */ |
78 | const char *fc_els_resp_type(struct fc_frame *fp) | 90 | const 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 | } |