aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_rport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libfc/fc_rport.c')
-rw-r--r--drivers/scsi/libfc/fc_rport.c191
1 files changed, 155 insertions, 36 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a7175adab32..49e1ccca09d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -58,7 +58,7 @@
58 58
59#include "fc_libfc.h" 59#include "fc_libfc.h"
60 60
61struct workqueue_struct *rport_event_queue; 61static struct workqueue_struct *rport_event_queue;
62 62
63static void fc_rport_enter_flogi(struct fc_rport_priv *); 63static void fc_rport_enter_flogi(struct fc_rport_priv *);
64static void fc_rport_enter_plogi(struct fc_rport_priv *); 64static void fc_rport_enter_plogi(struct fc_rport_priv *);
@@ -145,8 +145,10 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
145 rdata->maxframe_size = FC_MIN_MAX_PAYLOAD; 145 rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
146 INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout); 146 INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
147 INIT_WORK(&rdata->event_work, fc_rport_work); 147 INIT_WORK(&rdata->event_work, fc_rport_work);
148 if (port_id != FC_FID_DIR_SERV) 148 if (port_id != FC_FID_DIR_SERV) {
149 rdata->lld_event_callback = lport->tt.rport_event_callback;
149 list_add_rcu(&rdata->peers, &lport->disc.rports); 150 list_add_rcu(&rdata->peers, &lport->disc.rports);
151 }
150 return rdata; 152 return rdata;
151} 153}
152 154
@@ -257,6 +259,8 @@ static void fc_rport_work(struct work_struct *work)
257 struct fc_rport_operations *rport_ops; 259 struct fc_rport_operations *rport_ops;
258 struct fc_rport_identifiers ids; 260 struct fc_rport_identifiers ids;
259 struct fc_rport *rport; 261 struct fc_rport *rport;
262 struct fc4_prov *prov;
263 u8 type;
260 264
261 mutex_lock(&rdata->rp_mutex); 265 mutex_lock(&rdata->rp_mutex);
262 event = rdata->event; 266 event = rdata->event;
@@ -300,12 +304,25 @@ static void fc_rport_work(struct work_struct *work)
300 FC_RPORT_DBG(rdata, "callback ev %d\n", event); 304 FC_RPORT_DBG(rdata, "callback ev %d\n", event);
301 rport_ops->event_callback(lport, rdata, event); 305 rport_ops->event_callback(lport, rdata, event);
302 } 306 }
307 if (rdata->lld_event_callback) {
308 FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
309 rdata->lld_event_callback(lport, rdata, event);
310 }
303 kref_put(&rdata->kref, lport->tt.rport_destroy); 311 kref_put(&rdata->kref, lport->tt.rport_destroy);
304 break; 312 break;
305 313
306 case RPORT_EV_FAILED: 314 case RPORT_EV_FAILED:
307 case RPORT_EV_LOGO: 315 case RPORT_EV_LOGO:
308 case RPORT_EV_STOP: 316 case RPORT_EV_STOP:
317 if (rdata->prli_count) {
318 mutex_lock(&fc_prov_mutex);
319 for (type = 1; type < FC_FC4_PROV_SIZE; type++) {
320 prov = fc_passive_prov[type];
321 if (prov && prov->prlo)
322 prov->prlo(rdata);
323 }
324 mutex_unlock(&fc_prov_mutex);
325 }
309 port_id = rdata->ids.port_id; 326 port_id = rdata->ids.port_id;
310 mutex_unlock(&rdata->rp_mutex); 327 mutex_unlock(&rdata->rp_mutex);
311 328
@@ -313,6 +330,10 @@ static void fc_rport_work(struct work_struct *work)
313 FC_RPORT_DBG(rdata, "callback ev %d\n", event); 330 FC_RPORT_DBG(rdata, "callback ev %d\n", event);
314 rport_ops->event_callback(lport, rdata, event); 331 rport_ops->event_callback(lport, rdata, event);
315 } 332 }
333 if (rdata->lld_event_callback) {
334 FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
335 rdata->lld_event_callback(lport, rdata, event);
336 }
316 cancel_delayed_work_sync(&rdata->retry_work); 337 cancel_delayed_work_sync(&rdata->retry_work);
317 338
318 /* 339 /*
@@ -336,6 +357,7 @@ static void fc_rport_work(struct work_struct *work)
336 if (port_id == FC_FID_DIR_SERV) { 357 if (port_id == FC_FID_DIR_SERV) {
337 rdata->event = RPORT_EV_NONE; 358 rdata->event = RPORT_EV_NONE;
338 mutex_unlock(&rdata->rp_mutex); 359 mutex_unlock(&rdata->rp_mutex);
360 kref_put(&rdata->kref, lport->tt.rport_destroy);
339 } else if ((rdata->flags & FC_RP_STARTED) && 361 } else if ((rdata->flags & FC_RP_STARTED) &&
340 rdata->major_retries < 362 rdata->major_retries <
341 lport->max_rport_retry_count) { 363 lport->max_rport_retry_count) {
@@ -575,7 +597,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
575 597
576 /* make sure this isn't an FC_EX_CLOSED error, never retry those */ 598 /* make sure this isn't an FC_EX_CLOSED error, never retry those */
577 if (PTR_ERR(fp) == -FC_EX_CLOSED) 599 if (PTR_ERR(fp) == -FC_EX_CLOSED)
578 return fc_rport_error(rdata, fp); 600 goto out;
579 601
580 if (rdata->retries < rdata->local_port->max_rport_retry_count) { 602 if (rdata->retries < rdata->local_port->max_rport_retry_count) {
581 FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n", 603 FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
@@ -588,7 +610,8 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
588 return; 610 return;
589 } 611 }
590 612
591 return fc_rport_error(rdata, fp); 613out:
614 fc_rport_error(rdata, fp);
592} 615}
593 616
594/** 617/**
@@ -878,6 +901,9 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
878 rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn); 901 rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
879 rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn); 902 rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
880 903
904 /* save plogi response sp_features for further reference */
905 rdata->sp_features = ntohs(plp->fl_csp.sp_features);
906
881 if (lport->point_to_multipoint) 907 if (lport->point_to_multipoint)
882 fc_rport_login_complete(rdata, fp); 908 fc_rport_login_complete(rdata, fp);
883 csp_seq = ntohs(plp->fl_csp.sp_tot_seq); 909 csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
@@ -949,6 +975,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
949 struct fc_els_prli prli; 975 struct fc_els_prli prli;
950 struct fc_els_spp spp; 976 struct fc_els_spp spp;
951 } *pp; 977 } *pp;
978 struct fc_els_spp temp_spp;
979 struct fc4_prov *prov;
952 u32 roles = FC_RPORT_ROLE_UNKNOWN; 980 u32 roles = FC_RPORT_ROLE_UNKNOWN;
953 u32 fcp_parm = 0; 981 u32 fcp_parm = 0;
954 u8 op; 982 u8 op;
@@ -983,6 +1011,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
983 resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK); 1011 resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
984 FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n", 1012 FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
985 pp->spp.spp_flags); 1013 pp->spp.spp_flags);
1014 rdata->spp_type = pp->spp.spp_type;
986 if (resp_code != FC_SPP_RESP_ACK) { 1015 if (resp_code != FC_SPP_RESP_ACK) {
987 if (resp_code == FC_SPP_RESP_CONF) 1016 if (resp_code == FC_SPP_RESP_CONF)
988 fc_rport_error(rdata, fp); 1017 fc_rport_error(rdata, fp);
@@ -996,6 +1025,15 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
996 fcp_parm = ntohl(pp->spp.spp_params); 1025 fcp_parm = ntohl(pp->spp.spp_params);
997 if (fcp_parm & FCP_SPPF_RETRY) 1026 if (fcp_parm & FCP_SPPF_RETRY)
998 rdata->flags |= FC_RP_FLAGS_RETRY; 1027 rdata->flags |= FC_RP_FLAGS_RETRY;
1028 if (fcp_parm & FCP_SPPF_CONF_COMPL)
1029 rdata->flags |= FC_RP_FLAGS_CONF_REQ;
1030
1031 prov = fc_passive_prov[FC_TYPE_FCP];
1032 if (prov) {
1033 memset(&temp_spp, 0, sizeof(temp_spp));
1034 prov->prli(rdata, pp->prli.prli_spp_len,
1035 &pp->spp, &temp_spp);
1036 }
999 1037
1000 rdata->supported_classes = FC_COS_CLASS3; 1038 rdata->supported_classes = FC_COS_CLASS3;
1001 if (fcp_parm & FCP_SPPF_INIT_FCN) 1039 if (fcp_parm & FCP_SPPF_INIT_FCN)
@@ -1033,6 +1071,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
1033 struct fc_els_spp spp; 1071 struct fc_els_spp spp;
1034 } *pp; 1072 } *pp;
1035 struct fc_frame *fp; 1073 struct fc_frame *fp;
1074 struct fc4_prov *prov;
1036 1075
1037 /* 1076 /*
1038 * If the rport is one of the well known addresses 1077 * If the rport is one of the well known addresses
@@ -1054,9 +1093,20 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
1054 return; 1093 return;
1055 } 1094 }
1056 1095
1057 if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, 1096 fc_prli_fill(lport, fp);
1058 fc_rport_prli_resp, rdata, 1097
1059 2 * lport->r_a_tov)) 1098 prov = fc_passive_prov[FC_TYPE_FCP];
1099 if (prov) {
1100 pp = fc_frame_payload_get(fp, sizeof(*pp));
1101 prov->prli(rdata, sizeof(pp->spp), NULL, &pp->spp);
1102 }
1103
1104 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rdata->ids.port_id,
1105 fc_host_port_id(lport->host), FC_TYPE_ELS,
1106 FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
1107
1108 if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
1109 NULL, rdata, 2 * lport->r_a_tov))
1060 fc_rport_error_retry(rdata, NULL); 1110 fc_rport_error_retry(rdata, NULL);
1061 else 1111 else
1062 kref_get(&rdata->kref); 1112 kref_get(&rdata->kref);
@@ -1642,9 +1692,9 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
1642 unsigned int len; 1692 unsigned int len;
1643 unsigned int plen; 1693 unsigned int plen;
1644 enum fc_els_spp_resp resp; 1694 enum fc_els_spp_resp resp;
1695 enum fc_els_spp_resp passive;
1645 struct fc_seq_els_data rjt_data; 1696 struct fc_seq_els_data rjt_data;
1646 u32 fcp_parm; 1697 struct fc4_prov *prov;
1647 u32 roles = FC_RPORT_ROLE_UNKNOWN;
1648 1698
1649 FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", 1699 FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
1650 fc_rport_state(rdata)); 1700 fc_rport_state(rdata));
@@ -1678,46 +1728,42 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
1678 pp->prli.prli_len = htons(len); 1728 pp->prli.prli_len = htons(len);
1679 len -= sizeof(struct fc_els_prli); 1729 len -= sizeof(struct fc_els_prli);
1680 1730
1681 /* reinitialize remote port roles */
1682 rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
1683
1684 /* 1731 /*
1685 * Go through all the service parameter pages and build 1732 * Go through all the service parameter pages and build
1686 * response. If plen indicates longer SPP than standard, 1733 * response. If plen indicates longer SPP than standard,
1687 * use that. The entire response has been pre-cleared above. 1734 * use that. The entire response has been pre-cleared above.
1688 */ 1735 */
1689 spp = &pp->spp; 1736 spp = &pp->spp;
1737 mutex_lock(&fc_prov_mutex);
1690 while (len >= plen) { 1738 while (len >= plen) {
1739 rdata->spp_type = rspp->spp_type;
1691 spp->spp_type = rspp->spp_type; 1740 spp->spp_type = rspp->spp_type;
1692 spp->spp_type_ext = rspp->spp_type_ext; 1741 spp->spp_type_ext = rspp->spp_type_ext;
1693 spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; 1742 resp = 0;
1694 resp = FC_SPP_RESP_ACK; 1743
1695 1744 if (rspp->spp_type < FC_FC4_PROV_SIZE) {
1696 switch (rspp->spp_type) { 1745 prov = fc_active_prov[rspp->spp_type];
1697 case 0: /* common to all FC-4 types */ 1746 if (prov)
1698 break; 1747 resp = prov->prli(rdata, plen, rspp, spp);
1699 case FC_TYPE_FCP: 1748 prov = fc_passive_prov[rspp->spp_type];
1700 fcp_parm = ntohl(rspp->spp_params); 1749 if (prov) {
1701 if (fcp_parm & FCP_SPPF_RETRY) 1750 passive = prov->prli(rdata, plen, rspp, spp);
1702 rdata->flags |= FC_RP_FLAGS_RETRY; 1751 if (!resp || passive == FC_SPP_RESP_ACK)
1703 rdata->supported_classes = FC_COS_CLASS3; 1752 resp = passive;
1704 if (fcp_parm & FCP_SPPF_INIT_FCN) 1753 }
1705 roles |= FC_RPORT_ROLE_FCP_INITIATOR; 1754 }
1706 if (fcp_parm & FCP_SPPF_TARG_FCN) 1755 if (!resp) {
1707 roles |= FC_RPORT_ROLE_FCP_TARGET; 1756 if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)
1708 rdata->ids.roles = roles; 1757 resp |= FC_SPP_RESP_CONF;
1709 1758 else
1710 spp->spp_params = htonl(lport->service_params); 1759 resp |= FC_SPP_RESP_INVL;
1711 break;
1712 default:
1713 resp = FC_SPP_RESP_INVL;
1714 break;
1715 } 1760 }
1716 spp->spp_flags |= resp; 1761 spp->spp_flags |= resp;
1717 len -= plen; 1762 len -= plen;
1718 rspp = (struct fc_els_spp *)((char *)rspp + plen); 1763 rspp = (struct fc_els_spp *)((char *)rspp + plen);
1719 spp = (struct fc_els_spp *)((char *)spp + plen); 1764 spp = (struct fc_els_spp *)((char *)spp + plen);
1720 } 1765 }
1766 mutex_unlock(&fc_prov_mutex);
1721 1767
1722 /* 1768 /*
1723 * Send LS_ACC. If this fails, the originator should retry. 1769 * Send LS_ACC. If this fails, the originator should retry.
@@ -1887,9 +1933,82 @@ int fc_rport_init(struct fc_lport *lport)
1887EXPORT_SYMBOL(fc_rport_init); 1933EXPORT_SYMBOL(fc_rport_init);
1888 1934
1889/** 1935/**
1936 * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator.
1937 * @rdata: remote port private
1938 * @spp_len: service parameter page length
1939 * @rspp: received service parameter page
1940 * @spp: response service parameter page
1941 *
1942 * Returns the value for the response code to be placed in spp_flags;
1943 * Returns 0 if not an initiator.
1944 */
1945static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len,
1946 const struct fc_els_spp *rspp,
1947 struct fc_els_spp *spp)
1948{
1949 struct fc_lport *lport = rdata->local_port;
1950 u32 fcp_parm;
1951
1952 fcp_parm = ntohl(rspp->spp_params);
1953 rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
1954 if (fcp_parm & FCP_SPPF_INIT_FCN)
1955 rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
1956 if (fcp_parm & FCP_SPPF_TARG_FCN)
1957 rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
1958 if (fcp_parm & FCP_SPPF_RETRY)
1959 rdata->flags |= FC_RP_FLAGS_RETRY;
1960 rdata->supported_classes = FC_COS_CLASS3;
1961
1962 if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR))
1963 return 0;
1964
1965 spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
1966
1967 /*
1968 * OR in our service parameters with other providers (target), if any.
1969 */
1970 fcp_parm = ntohl(spp->spp_params);
1971 spp->spp_params = htonl(fcp_parm | lport->service_params);
1972 return FC_SPP_RESP_ACK;
1973}
1974
1975/*
1976 * FC-4 provider ops for FCP initiator.
1977 */
1978struct fc4_prov fc_rport_fcp_init = {
1979 .prli = fc_rport_fcp_prli,
1980};
1981
1982/**
1983 * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0
1984 * @rdata: remote port private
1985 * @spp_len: service parameter page length
1986 * @rspp: received service parameter page
1987 * @spp: response service parameter page
1988 */
1989static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len,
1990 const struct fc_els_spp *rspp,
1991 struct fc_els_spp *spp)
1992{
1993 if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR)
1994 return FC_SPP_RESP_INVL;
1995 return FC_SPP_RESP_ACK;
1996}
1997
1998/*
1999 * FC-4 provider ops for type 0 service parameters.
2000 *
2001 * This handles the special case of type 0 which is always successful
2002 * but doesn't do anything otherwise.
2003 */
2004struct fc4_prov fc_rport_t0_prov = {
2005 .prli = fc_rport_t0_prli,
2006};
2007
2008/**
1890 * fc_setup_rport() - Initialize the rport_event_queue 2009 * fc_setup_rport() - Initialize the rport_event_queue
1891 */ 2010 */
1892int fc_setup_rport() 2011int fc_setup_rport(void)
1893{ 2012{
1894 rport_event_queue = create_singlethread_workqueue("fc_rport_eq"); 2013 rport_event_queue = create_singlethread_workqueue("fc_rport_eq");
1895 if (!rport_event_queue) 2014 if (!rport_event_queue)
@@ -1900,7 +2019,7 @@ int fc_setup_rport()
1900/** 2019/**
1901 * fc_destroy_rport() - Destroy the rport_event_queue 2020 * fc_destroy_rport() - Destroy the rport_event_queue
1902 */ 2021 */
1903void fc_destroy_rport() 2022void fc_destroy_rport(void)
1904{ 2023{
1905 destroy_workqueue(rport_event_queue); 2024 destroy_workqueue(rport_event_queue);
1906} 2025}