aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorYi Zou <yi.zou@intel.com>2009-11-20 17:55:24 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:01:59 -0500
commit63e27fb80c2010678681cef7b528ab8af3624fe9 (patch)
tree2ce41c886c976ead202044eb32d3e9aacc97e023 /drivers/scsi
parentb84056bf68404a5fe06b452ea9790b9927e793a6 (diff)
[SCSI] libfc: add support of receiving ELS_RLS
Upon receiving ELS_RLS, send the Link Error Status Block (LESB) back. Signed-off-by: Yi Zou <yi.zou@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libfc/fc_rport.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 91e2ba27f7bd..35ca0e72df46 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1098,6 +1098,78 @@ drop:
1098} 1098}
1099 1099
1100/** 1100/**
1101 * fc_rport_recv_rls_req() - Handle received Read Link Status request
1102 * @rdata: The remote port that sent the RLS request
1103 * @sp: The sequence that the RLS was on
1104 * @rx_fp: The PRLI request frame
1105 *
1106 * Locking Note: The rport lock is expected to be held before calling
1107 * this function.
1108 */
1109static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
1110 struct fc_seq *sp, struct fc_frame *rx_fp)
1111
1112{
1113 struct fc_lport *lport = rdata->local_port;
1114 struct fc_frame *fp;
1115 struct fc_exch *ep = fc_seq_exch(sp);
1116 struct fc_els_rls *rls;
1117 struct fc_els_rls_resp *rsp;
1118 struct fc_els_lesb *lesb;
1119 struct fc_seq_els_data rjt_data;
1120 struct fc_host_statistics *hst;
1121 u32 f_ctl;
1122
1123 FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n",
1124 fc_rport_state(rdata));
1125
1126 rls = fc_frame_payload_get(rx_fp, sizeof(*rls));
1127 if (!rls) {
1128 rjt_data.reason = ELS_RJT_PROT;
1129 rjt_data.explan = ELS_EXPL_INV_LEN;
1130 goto out_rjt;
1131 }
1132
1133 fp = fc_frame_alloc(lport, sizeof(*rsp));
1134 if (!fp) {
1135 rjt_data.reason = ELS_RJT_UNAB;
1136 rjt_data.explan = ELS_EXPL_INSUF_RES;
1137 goto out_rjt;
1138 }
1139
1140 rsp = fc_frame_payload_get(fp, sizeof(*rsp));
1141 memset(rsp, 0, sizeof(*rsp));
1142 rsp->rls_cmd = ELS_LS_ACC;
1143 lesb = &rsp->rls_lesb;
1144 if (lport->tt.get_lesb) {
1145 /* get LESB from LLD if it supports it */
1146 lport->tt.get_lesb(lport, lesb);
1147 } else {
1148 fc_get_host_stats(lport->host);
1149 hst = &lport->host_stats;
1150 lesb->lesb_link_fail = htonl(hst->link_failure_count);
1151 lesb->lesb_sync_loss = htonl(hst->loss_of_sync_count);
1152 lesb->lesb_sig_loss = htonl(hst->loss_of_signal_count);
1153 lesb->lesb_prim_err = htonl(hst->prim_seq_protocol_err_count);
1154 lesb->lesb_inv_word = htonl(hst->invalid_tx_word_count);
1155 lesb->lesb_inv_crc = htonl(hst->invalid_crc_count);
1156 }
1157
1158 sp = lport->tt.seq_start_next(sp);
1159 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
1160 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
1161 FC_TYPE_ELS, f_ctl, 0);
1162 lport->tt.seq_send(lport, sp, fp);
1163 goto out;
1164
1165out_rjt:
1166 rjt_data.fp = NULL;
1167 lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
1168out:
1169 fc_frame_free(rx_fp);
1170}
1171
1172/**
1101 * fc_rport_recv_els_req() - Handler for validated ELS requests 1173 * fc_rport_recv_els_req() - Handler for validated ELS requests
1102 * @lport: The local port that received the ELS request 1174 * @lport: The local port that received the ELS request
1103 * @sp: The sequence that the ELS request was on 1175 * @sp: The sequence that the ELS request was on
@@ -1159,6 +1231,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
1159 els_data.fp = fp; 1231 els_data.fp = fp;
1160 lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); 1232 lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data);
1161 break; 1233 break;
1234 case ELS_RLS:
1235 fc_rport_recv_rls_req(rdata, sp, fp);
1236 break;
1162 default: 1237 default:
1163 fc_frame_free(fp); /* can't happen */ 1238 fc_frame_free(fp); /* can't happen */
1164 break; 1239 break;
@@ -1203,6 +1278,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
1203 case ELS_ADISC: 1278 case ELS_ADISC:
1204 case ELS_RRQ: 1279 case ELS_RRQ:
1205 case ELS_REC: 1280 case ELS_REC:
1281 case ELS_RLS:
1206 fc_rport_recv_els_req(lport, sp, fp); 1282 fc_rport_recv_els_req(lport, sp, fp);
1207 break; 1283 break;
1208 default: 1284 default: