aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 15:55:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 15:55:29 -0400
commit424a6f6ef990b7e9f56f6627bfc6c46b493faeb4 (patch)
tree0028356ed8003495fbbe1f716f359e3c8ebc35b6 /drivers/scsi/libfc
parent1ab142d499294b844ecc81e8004db4ce029b0b61 (diff)
parentcd8df932d894f3128c884e3ae1b2b484540513db (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
SCSI updates from James Bottomley: "The update includes the usual assortment of driver updates (lpfc, qla2xxx, qla4xxx, bfa, bnx2fc, bnx2i, isci, fcoe, hpsa) plus a huge amount of infrastructure work in the SAS library and transport class as well as an iSCSI update. There's also a new SCSI based virtio driver." * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (177 commits) [SCSI] qla4xxx: Update driver version to 5.02.00-k15 [SCSI] qla4xxx: trivial cleanup [SCSI] qla4xxx: Fix sparse warning [SCSI] qla4xxx: Add support for multiple session per host. [SCSI] qla4xxx: Export CHAP index as sysfs attribute [SCSI] scsi_transport: Export CHAP index as sysfs attribute [SCSI] qla4xxx: Add support to display CHAP list and delete CHAP entry [SCSI] iscsi_transport: Add support to display CHAP list and delete CHAP entry [SCSI] pm8001: fix endian issue with code optimization. [SCSI] pm8001: Fix possible racing condition. [SCSI] pm8001: Fix bogus interrupt state flag issue. [SCSI] ipr: update PCI ID definitions for new adapters [SCSI] qla2xxx: handle default case in qla2x00_request_firmware() [SCSI] isci: improvements in driver unloading routine [SCSI] isci: improve phy event warnings [SCSI] isci: debug, provide state-enum-to-string conversions [SCSI] scsi_transport_sas: 'enable' phys on reset [SCSI] libsas: don't recover end devices attached to disabled phys [SCSI] libsas: fixup target_port_protocols for expanders that don't report sata [SCSI] libsas: set attached device type and target protocols for local phys ...
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r--drivers/scsi/libfc/fc_disc.c7
-rw-r--r--drivers/scsi/libfc/fc_elsct.c3
-rw-r--r--drivers/scsi/libfc/fc_exch.c7
-rw-r--r--drivers/scsi/libfc/fc_lport.c227
4 files changed, 236 insertions, 8 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 1d1b0c9da29b..8e561e6a557c 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -337,6 +337,13 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
337 schedule_delayed_work(&disc->disc_work, delay); 337 schedule_delayed_work(&disc->disc_work, delay);
338 } else 338 } else
339 fc_disc_done(disc, DISC_EV_FAILED); 339 fc_disc_done(disc, DISC_EV_FAILED);
340 } else if (PTR_ERR(fp) == -FC_EX_CLOSED) {
341 /*
342 * if discovery fails due to lport reset, clear
343 * pending flag so that subsequent discovery can
344 * continue
345 */
346 disc->pending = 0;
340 } 347 }
341} 348}
342 349
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index e17a28d324d0..c2384d501470 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -56,8 +56,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did,
56 rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type); 56 rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type);
57 else { 57 else {
58 /* CT requests */ 58 /* CT requests */
59 rc = fc_ct_fill(lport, did, fp, op, &r_ctl, &fh_type); 59 rc = fc_ct_fill(lport, did, fp, op, &r_ctl, &fh_type, &did);
60 did = FC_FID_DIR_SERV;
61 } 60 }
62 61
63 if (rc) { 62 if (rc) {
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 4d70d96fa5dc..630291f01826 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1642,9 +1642,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
1642 case FC_RCTL_ACK_0: 1642 case FC_RCTL_ACK_0:
1643 break; 1643 break;
1644 default: 1644 default:
1645 FC_EXCH_DBG(ep, "BLS rctl %x - %s received", 1645 if (ep)
1646 fh->fh_r_ctl, 1646 FC_EXCH_DBG(ep, "BLS rctl %x - %s received",
1647 fc_exch_rctl_name(fh->fh_r_ctl)); 1647 fh->fh_r_ctl,
1648 fc_exch_rctl_name(fh->fh_r_ctl));
1648 break; 1649 break;
1649 } 1650 }
1650 fc_frame_free(fp); 1651 fc_frame_free(fp);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index c1a808cc5920..bd5d31d022d9 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -116,6 +116,8 @@ static void fc_lport_enter_ns(struct fc_lport *, enum fc_lport_state);
116static void fc_lport_enter_scr(struct fc_lport *); 116static void fc_lport_enter_scr(struct fc_lport *);
117static void fc_lport_enter_ready(struct fc_lport *); 117static void fc_lport_enter_ready(struct fc_lport *);
118static void fc_lport_enter_logo(struct fc_lport *); 118static void fc_lport_enter_logo(struct fc_lport *);
119static void fc_lport_enter_fdmi(struct fc_lport *lport);
120static void fc_lport_enter_ms(struct fc_lport *, enum fc_lport_state);
119 121
120static const char *fc_lport_state_names[] = { 122static const char *fc_lport_state_names[] = {
121 [LPORT_ST_DISABLED] = "disabled", 123 [LPORT_ST_DISABLED] = "disabled",
@@ -126,6 +128,11 @@ static const char *fc_lport_state_names[] = {
126 [LPORT_ST_RSPN_ID] = "RSPN_ID", 128 [LPORT_ST_RSPN_ID] = "RSPN_ID",
127 [LPORT_ST_RFT_ID] = "RFT_ID", 129 [LPORT_ST_RFT_ID] = "RFT_ID",
128 [LPORT_ST_RFF_ID] = "RFF_ID", 130 [LPORT_ST_RFF_ID] = "RFF_ID",
131 [LPORT_ST_FDMI] = "FDMI",
132 [LPORT_ST_RHBA] = "RHBA",
133 [LPORT_ST_RPA] = "RPA",
134 [LPORT_ST_DHBA] = "DHBA",
135 [LPORT_ST_DPRT] = "DPRT",
129 [LPORT_ST_SCR] = "SCR", 136 [LPORT_ST_SCR] = "SCR",
130 [LPORT_ST_READY] = "Ready", 137 [LPORT_ST_READY] = "Ready",
131 [LPORT_ST_LOGO] = "LOGO", 138 [LPORT_ST_LOGO] = "LOGO",
@@ -183,11 +190,14 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
183 if (lport->state == LPORT_ST_DNS) { 190 if (lport->state == LPORT_ST_DNS) {
184 lport->dns_rdata = rdata; 191 lport->dns_rdata = rdata;
185 fc_lport_enter_ns(lport, LPORT_ST_RNN_ID); 192 fc_lport_enter_ns(lport, LPORT_ST_RNN_ID);
193 } else if (lport->state == LPORT_ST_FDMI) {
194 lport->ms_rdata = rdata;
195 fc_lport_enter_ms(lport, LPORT_ST_DHBA);
186 } else { 196 } else {
187 FC_LPORT_DBG(lport, "Received an READY event " 197 FC_LPORT_DBG(lport, "Received an READY event "
188 "on port (%6.6x) for the directory " 198 "on port (%6.6x) for the directory "
189 "server, but the lport is not " 199 "server, but the lport is not "
190 "in the DNS state, it's in the " 200 "in the DNS or FDMI state, it's in the "
191 "%d state", rdata->ids.port_id, 201 "%d state", rdata->ids.port_id,
192 lport->state); 202 lport->state);
193 lport->tt.rport_logoff(rdata); 203 lport->tt.rport_logoff(rdata);
@@ -196,7 +206,10 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
196 case RPORT_EV_LOGO: 206 case RPORT_EV_LOGO:
197 case RPORT_EV_FAILED: 207 case RPORT_EV_FAILED:
198 case RPORT_EV_STOP: 208 case RPORT_EV_STOP:
199 lport->dns_rdata = NULL; 209 if (rdata->ids.port_id == FC_FID_DIR_SERV)
210 lport->dns_rdata = NULL;
211 else if (rdata->ids.port_id == FC_FID_MGMT_SERV)
212 lport->ms_rdata = NULL;
200 break; 213 break;
201 case RPORT_EV_NONE: 214 case RPORT_EV_NONE:
202 break; 215 break;
@@ -1148,7 +1161,10 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
1148 fc_lport_enter_ns(lport, LPORT_ST_RFF_ID); 1161 fc_lport_enter_ns(lport, LPORT_ST_RFF_ID);
1149 break; 1162 break;
1150 case LPORT_ST_RFF_ID: 1163 case LPORT_ST_RFF_ID:
1151 fc_lport_enter_scr(lport); 1164 if (lport->fdmi_enabled)
1165 fc_lport_enter_fdmi(lport);
1166 else
1167 fc_lport_enter_scr(lport);
1152 break; 1168 break;
1153 default: 1169 default:
1154 /* should have already been caught by state checks */ 1170 /* should have already been caught by state checks */
@@ -1163,6 +1179,85 @@ err:
1163} 1179}
1164 1180
1165/** 1181/**
1182 * fc_lport_ms_resp() - Handle response to a management server
1183 * exchange
1184 * @sp: current sequence in exchange
1185 * @fp: response frame
1186 * @lp_arg: Fibre Channel host port instance
1187 *
1188 * Locking Note: This function will be called without the lport lock
1189 * held, but it will lock, call an _enter_* function or fc_lport_error()
1190 * and then unlock the lport.
1191 */
1192static void fc_lport_ms_resp(struct fc_seq *sp, struct fc_frame *fp,
1193 void *lp_arg)
1194{
1195 struct fc_lport *lport = lp_arg;
1196 struct fc_frame_header *fh;
1197 struct fc_ct_hdr *ct;
1198
1199 FC_LPORT_DBG(lport, "Received a ms %s\n", fc_els_resp_type(fp));
1200
1201 if (fp == ERR_PTR(-FC_EX_CLOSED))
1202 return;
1203
1204 mutex_lock(&lport->lp_mutex);
1205
1206 if (lport->state < LPORT_ST_RHBA || lport->state > LPORT_ST_DPRT) {
1207 FC_LPORT_DBG(lport, "Received a management server response, "
1208 "but in state %s\n", fc_lport_state(lport));
1209 if (IS_ERR(fp))
1210 goto err;
1211 goto out;
1212 }
1213
1214 if (IS_ERR(fp)) {
1215 fc_lport_error(lport, fp);
1216 goto err;
1217 }
1218
1219 fh = fc_frame_header_get(fp);
1220 ct = fc_frame_payload_get(fp, sizeof(*ct));
1221
1222 if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1223 ct->ct_fs_type == FC_FST_MGMT &&
1224 ct->ct_fs_subtype == FC_FDMI_SUBTYPE) {
1225 FC_LPORT_DBG(lport, "Received a management server response, "
1226 "reason=%d explain=%d\n",
1227 ct->ct_reason,
1228 ct->ct_explan);
1229
1230 switch (lport->state) {
1231 case LPORT_ST_RHBA:
1232 if (ntohs(ct->ct_cmd) == FC_FS_ACC)
1233 fc_lport_enter_ms(lport, LPORT_ST_RPA);
1234 else /* Error Skip RPA */
1235 fc_lport_enter_scr(lport);
1236 break;
1237 case LPORT_ST_RPA:
1238 fc_lport_enter_scr(lport);
1239 break;
1240 case LPORT_ST_DPRT:
1241 fc_lport_enter_ms(lport, LPORT_ST_RHBA);
1242 break;
1243 case LPORT_ST_DHBA:
1244 fc_lport_enter_ms(lport, LPORT_ST_DPRT);
1245 break;
1246 default:
1247 /* should have already been caught by state checks */
1248 break;
1249 }
1250 } else {
1251 /* Invalid Frame? */
1252 fc_lport_error(lport, fp);
1253 }
1254out:
1255 fc_frame_free(fp);
1256err:
1257 mutex_unlock(&lport->lp_mutex);
1258}
1259
1260/**
1166 * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request 1261 * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request
1167 * @sp: current sequence in SCR exchange 1262 * @sp: current sequence in SCR exchange
1168 * @fp: response frame 1263 * @fp: response frame
@@ -1339,6 +1434,123 @@ err:
1339} 1434}
1340 1435
1341/** 1436/**
1437 * fc_lport_enter_ms() - management server commands
1438 * @lport: Fibre Channel local port to register
1439 *
1440 * Locking Note: The lport lock is expected to be held before calling
1441 * this routine.
1442 */
1443static void fc_lport_enter_ms(struct fc_lport *lport, enum fc_lport_state state)
1444{
1445 struct fc_frame *fp;
1446 enum fc_fdmi_req cmd;
1447 int size = sizeof(struct fc_ct_hdr);
1448 size_t len;
1449 int numattrs;
1450
1451 FC_LPORT_DBG(lport, "Entered %s state from %s state\n",
1452 fc_lport_state_names[state],
1453 fc_lport_state(lport));
1454
1455 fc_lport_state_enter(lport, state);
1456
1457 switch (state) {
1458 case LPORT_ST_RHBA:
1459 cmd = FC_FDMI_RHBA;
1460 /* Number of HBA Attributes */
1461 numattrs = 10;
1462 len = sizeof(struct fc_fdmi_rhba);
1463 len -= sizeof(struct fc_fdmi_attr_entry);
1464 len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
1465 len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
1466 len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN;
1467 len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN;
1468 len += FC_FDMI_HBA_ATTR_MODEL_LEN;
1469 len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN;
1470 len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN;
1471 len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN;
1472 len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN;
1473 len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN;
1474 len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN;
1475
1476 size += len;
1477 break;
1478 case LPORT_ST_RPA:
1479 cmd = FC_FDMI_RPA;
1480 /* Number of Port Attributes */
1481 numattrs = 6;
1482 len = sizeof(struct fc_fdmi_rpa);
1483 len -= sizeof(struct fc_fdmi_attr_entry);
1484 len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN);
1485 len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
1486 len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN;
1487 len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN;
1488 len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN;
1489 len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN;
1490 len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN;
1491
1492 size += len;
1493 break;
1494 case LPORT_ST_DPRT:
1495 cmd = FC_FDMI_DPRT;
1496 len = sizeof(struct fc_fdmi_dprt);
1497 size += len;
1498 break;
1499 case LPORT_ST_DHBA:
1500 cmd = FC_FDMI_DHBA;
1501 len = sizeof(struct fc_fdmi_dhba);
1502 size += len;
1503 break;
1504 default:
1505 fc_lport_error(lport, NULL);
1506 return;
1507 }
1508
1509 FC_LPORT_DBG(lport, "Cmd=0x%x Len %d size %d\n",
1510 cmd, (int)len, size);
1511 fp = fc_frame_alloc(lport, size);
1512 if (!fp) {
1513 fc_lport_error(lport, fp);
1514 return;
1515 }
1516
1517 if (!lport->tt.elsct_send(lport, FC_FID_MGMT_SERV, fp, cmd,
1518 fc_lport_ms_resp,
1519 lport, 3 * lport->r_a_tov))
1520 fc_lport_error(lport, fp);
1521}
1522
1523/**
1524 * fc_rport_enter_fdmi() - Create a fc_rport for the management server
1525 * @lport: The local port requesting a remote port for the management server
1526 *
1527 * Locking Note: The lport lock is expected to be held before calling
1528 * this routine.
1529 */
1530static void fc_lport_enter_fdmi(struct fc_lport *lport)
1531{
1532 struct fc_rport_priv *rdata;
1533
1534 FC_LPORT_DBG(lport, "Entered FDMI state from %s state\n",
1535 fc_lport_state(lport));
1536
1537 fc_lport_state_enter(lport, LPORT_ST_FDMI);
1538
1539 mutex_lock(&lport->disc.disc_mutex);
1540 rdata = lport->tt.rport_create(lport, FC_FID_MGMT_SERV);
1541 mutex_unlock(&lport->disc.disc_mutex);
1542 if (!rdata)
1543 goto err;
1544
1545 rdata->ops = &fc_lport_rport_ops;
1546 lport->tt.rport_login(rdata);
1547 return;
1548
1549err:
1550 fc_lport_error(lport, NULL);
1551}
1552
1553/**
1342 * fc_lport_timeout() - Handler for the retry_work timer 1554 * fc_lport_timeout() - Handler for the retry_work timer
1343 * @work: The work struct of the local port 1555 * @work: The work struct of the local port
1344 */ 1556 */
@@ -1371,6 +1583,15 @@ static void fc_lport_timeout(struct work_struct *work)
1371 case LPORT_ST_RFF_ID: 1583 case LPORT_ST_RFF_ID:
1372 fc_lport_enter_ns(lport, lport->state); 1584 fc_lport_enter_ns(lport, lport->state);
1373 break; 1585 break;
1586 case LPORT_ST_FDMI:
1587 fc_lport_enter_fdmi(lport);
1588 break;
1589 case LPORT_ST_RHBA:
1590 case LPORT_ST_RPA:
1591 case LPORT_ST_DHBA:
1592 case LPORT_ST_DPRT:
1593 fc_lport_enter_ms(lport, lport->state);
1594 break;
1374 case LPORT_ST_SCR: 1595 case LPORT_ST_SCR:
1375 fc_lport_enter_scr(lport); 1596 fc_lport_enter_scr(lport);
1376 break; 1597 break;