aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-01-04 02:26:08 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 16:05:05 -0500
commitc132f692085ac624d7c8123df781846c8dcb3166 (patch)
treec9009fcb9112812544f54efc6c134021dffb6545
parentcb48d672bfeb4147f3e20d5b16fa2eb6377231e2 (diff)
[SCSI] isci: kill iphy->isci_port lookups
This field is a holdover from the OS abstraction conversion. The stable phy to port lookups are done via iphy->ownining_port under scic_lock. After this conversion to use port->lldd_port the only volatile lookup is the initial lookup in isci_port_formed(). After that point any lookup via a successfully notified domain_device is guaranteed to be valid until the domain_device is destroyed. Delete ->start_complete as it is only set once and is set as a consequence of the port going link up, by definition of getting a port formed event the port is "ready". While we are correcting port lookups also move the asd_sas_port table out from under the isci_port. This is to preclude any temptation to use container_of() to convert an asd_sas_port to an isci_port, the association is dynamic and under libsas control. Tested-by: Maciej Trela <maciej.trela@intel.com> [dmilburn@redhat.com: fix i686 compile error] Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/isci/host.h19
-rw-r--r--drivers/scsi/isci/init.c7
-rw-r--r--drivers/scsi/isci/phy.c18
-rw-r--r--drivers/scsi/isci/phy.h1
-rw-r--r--drivers/scsi/isci/port.c84
-rw-r--r--drivers/scsi/isci/port.h2
-rw-r--r--drivers/scsi/isci/remote_device.c29
7 files changed, 83 insertions, 77 deletions
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 5477f0fa8233..adbad69d1069 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -187,6 +187,7 @@ struct isci_host {
187 int id; /* unique within a given pci device */ 187 int id; /* unique within a given pci device */
188 struct isci_phy phys[SCI_MAX_PHYS]; 188 struct isci_phy phys[SCI_MAX_PHYS];
189 struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ 189 struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */
190 struct asd_sas_port sas_ports[SCI_MAX_PORTS];
190 struct sas_ha_struct sas_ha; 191 struct sas_ha_struct sas_ha;
191 192
192 spinlock_t state_lock; 193 spinlock_t state_lock;
@@ -393,24 +394,6 @@ static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
393#define sci_controller_clear_invalid_phy(controller, phy) \ 394#define sci_controller_clear_invalid_phy(controller, phy) \
394 ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) 395 ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
395 396
396static inline struct device *sciphy_to_dev(struct isci_phy *iphy)
397{
398
399 if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)
400 return NULL;
401
402 return &iphy->isci_port->isci_host->pdev->dev;
403}
404
405static inline struct device *sciport_to_dev(struct isci_port *iport)
406{
407
408 if (!iport || !iport->isci_host)
409 return NULL;
410
411 return &iport->isci_host->pdev->dev;
412}
413
414static inline struct device *scirdev_to_dev(struct isci_remote_device *idev) 397static inline struct device *scirdev_to_dev(struct isci_remote_device *idev)
415{ 398{
416 if (!idev || !idev->isci_port || !idev->isci_port->isci_host) 399 if (!idev || !idev->isci_port || !idev->isci_port->isci_host)
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 7ba236e9fab2..c20fda090423 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -241,18 +241,13 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
241 if (!sas_ports) 241 if (!sas_ports)
242 return -ENOMEM; 242 return -ENOMEM;
243 243
244 /*----------------- Libsas Initialization Stuff----------------------
245 * Set various fields in the sas_ha struct:
246 */
247
248 sas_ha->sas_ha_name = DRV_NAME; 244 sas_ha->sas_ha_name = DRV_NAME;
249 sas_ha->lldd_module = THIS_MODULE; 245 sas_ha->lldd_module = THIS_MODULE;
250 sas_ha->sas_addr = &isci_host->phys[0].sas_addr[0]; 246 sas_ha->sas_addr = &isci_host->phys[0].sas_addr[0];
251 247
252 /* set the array of phy and port structs. */
253 for (i = 0; i < SCI_MAX_PHYS; i++) { 248 for (i = 0; i < SCI_MAX_PHYS; i++) {
254 sas_phys[i] = &isci_host->phys[i].sas_phy; 249 sas_phys[i] = &isci_host->phys[i].sas_phy;
255 sas_ports[i] = &isci_host->ports[i].sas_port; 250 sas_ports[i] = &isci_host->sas_ports[i];
256 } 251 }
257 252
258 sas_ha->sas_phy = sas_phys; 253 sas_ha->sas_phy = sas_phys;
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index fe18acfd6eb3..8d412ca689ad 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -67,6 +67,14 @@ enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy)
67 return iphy->max_negotiated_speed; 67 return iphy->max_negotiated_speed;
68} 68}
69 69
70static struct device *sciphy_to_dev(struct isci_phy *iphy)
71{
72 struct isci_phy *table = iphy - iphy->phy_index;
73 struct isci_host *ihost = container_of(table, typeof(*ihost), phys[0]);
74
75 return &ihost->pdev->dev;
76}
77
70static enum sci_status 78static enum sci_status
71sci_phy_transport_layer_initialization(struct isci_phy *iphy, 79sci_phy_transport_layer_initialization(struct isci_phy *iphy,
72 struct scu_transport_layer_registers __iomem *reg) 80 struct scu_transport_layer_registers __iomem *reg)
@@ -1299,7 +1307,6 @@ void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index)
1299 sas_addr = cpu_to_be64(sci_sas_addr); 1307 sas_addr = cpu_to_be64(sci_sas_addr);
1300 memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr)); 1308 memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr));
1301 1309
1302 iphy->isci_port = NULL;
1303 iphy->sas_phy.enabled = 0; 1310 iphy->sas_phy.enabled = 0;
1304 iphy->sas_phy.id = index; 1311 iphy->sas_phy.id = index;
1305 iphy->sas_phy.sas_addr = &iphy->sas_addr[0]; 1312 iphy->sas_phy.sas_addr = &iphy->sas_addr[0];
@@ -1333,13 +1340,13 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
1333{ 1340{
1334 int ret = 0; 1341 int ret = 0;
1335 struct isci_phy *iphy = sas_phy->lldd_phy; 1342 struct isci_phy *iphy = sas_phy->lldd_phy;
1336 struct isci_port *iport = iphy->isci_port; 1343 struct asd_sas_port *port = sas_phy->port;
1337 struct isci_host *ihost = sas_phy->ha->lldd_ha; 1344 struct isci_host *ihost = sas_phy->ha->lldd_ha;
1338 unsigned long flags; 1345 unsigned long flags;
1339 1346
1340 dev_dbg(&ihost->pdev->dev, 1347 dev_dbg(&ihost->pdev->dev,
1341 "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n", 1348 "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
1342 __func__, sas_phy, func, buf, iphy, iport); 1349 __func__, sas_phy, func, buf, iphy, port);
1343 1350
1344 switch (func) { 1351 switch (func) {
1345 case PHY_FUNC_DISABLE: 1352 case PHY_FUNC_DISABLE:
@@ -1356,11 +1363,10 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
1356 break; 1363 break;
1357 1364
1358 case PHY_FUNC_HARD_RESET: 1365 case PHY_FUNC_HARD_RESET:
1359 if (!iport) 1366 if (!port)
1360 return -ENODEV; 1367 return -ENODEV;
1361 1368
1362 /* Perform the port reset. */ 1369 ret = isci_port_perform_hard_reset(ihost, port->lldd_port, iphy);
1363 ret = isci_port_perform_hard_reset(ihost, iport, iphy);
1364 1370
1365 break; 1371 break;
1366 case PHY_FUNC_GET_EVENTS: { 1372 case PHY_FUNC_GET_EVENTS: {
diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h
index 67699c8e321c..a5e1a9e577b0 100644
--- a/drivers/scsi/isci/phy.h
+++ b/drivers/scsi/isci/phy.h
@@ -103,7 +103,6 @@ struct isci_phy {
103 struct scu_transport_layer_registers __iomem *transport_layer_registers; 103 struct scu_transport_layer_registers __iomem *transport_layer_registers;
104 struct scu_link_layer_registers __iomem *link_layer_registers; 104 struct scu_link_layer_registers __iomem *link_layer_registers;
105 struct asd_sas_phy sas_phy; 105 struct asd_sas_phy sas_phy;
106 struct isci_port *isci_port;
107 u8 sas_addr[SAS_ADDR_SIZE]; 106 u8 sas_addr[SAS_ADDR_SIZE];
108 union { 107 union {
109 struct sas_identify_frame iaf; 108 struct sas_identify_frame iaf;
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 7c6ac58a5c4c..a28c9e6e2806 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -60,6 +60,21 @@
60#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) 60#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000)
61#define SCU_DUMMY_INDEX (0xFFFF) 61#define SCU_DUMMY_INDEX (0xFFFF)
62 62
63static struct device *sciport_to_dev(struct isci_port *iport)
64{
65 int i = iport->physical_port_index;
66 struct isci_port *table;
67 struct isci_host *ihost;
68
69 if (i == SCIC_SDS_DUMMY_PORT)
70 i = SCI_MAX_PORTS+1;
71
72 table = iport - i;
73 ihost = container_of(table, typeof(*ihost), ports[0]);
74
75 return &ihost->pdev->dev;
76}
77
63static void isci_port_change_state(struct isci_port *iport, enum isci_status status) 78static void isci_port_change_state(struct isci_port *iport, enum isci_status status)
64{ 79{
65 unsigned long flags; 80 unsigned long flags;
@@ -165,17 +180,13 @@ static void isci_port_link_up(struct isci_host *isci_host,
165 struct sci_port_properties properties; 180 struct sci_port_properties properties;
166 unsigned long success = true; 181 unsigned long success = true;
167 182
168 BUG_ON(iphy->isci_port != NULL);
169
170 iphy->isci_port = iport;
171
172 dev_dbg(&isci_host->pdev->dev, 183 dev_dbg(&isci_host->pdev->dev,
173 "%s: isci_port = %p\n", 184 "%s: isci_port = %p\n",
174 __func__, iport); 185 __func__, iport);
175 186
176 spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); 187 spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags);
177 188
178 isci_port_change_state(iphy->isci_port, isci_starting); 189 isci_port_change_state(iport, isci_starting);
179 190
180 sci_port_get_properties(iport, &properties); 191 sci_port_get_properties(iport, &properties);
181 192
@@ -269,8 +280,6 @@ static void isci_port_link_down(struct isci_host *isci_host,
269 isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy, 280 isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy,
270 PHYE_LOSS_OF_SIGNAL); 281 PHYE_LOSS_OF_SIGNAL);
271 282
272 isci_phy->isci_port = NULL;
273
274 dev_dbg(&isci_host->pdev->dev, 283 dev_dbg(&isci_host->pdev->dev,
275 "%s: isci_port = %p - Done\n", __func__, isci_port); 284 "%s: isci_port = %p - Done\n", __func__, isci_port);
276} 285}
@@ -288,7 +297,6 @@ static void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_
288 dev_dbg(&isci_host->pdev->dev, 297 dev_dbg(&isci_host->pdev->dev,
289 "%s: isci_port = %p\n", __func__, isci_port); 298 "%s: isci_port = %p\n", __func__, isci_port);
290 299
291 complete_all(&isci_port->start_complete);
292 isci_port_change_state(isci_port, isci_ready); 300 isci_port_change_state(isci_port, isci_ready);
293 return; 301 return;
294} 302}
@@ -1645,7 +1653,6 @@ void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index)
1645 INIT_LIST_HEAD(&iport->remote_dev_list); 1653 INIT_LIST_HEAD(&iport->remote_dev_list);
1646 INIT_LIST_HEAD(&iport->domain_dev_list); 1654 INIT_LIST_HEAD(&iport->domain_dev_list);
1647 spin_lock_init(&iport->state_lock); 1655 spin_lock_init(&iport->state_lock);
1648 init_completion(&iport->start_complete);
1649 iport->isci_host = ihost; 1656 iport->isci_host = ihost;
1650 isci_port_change_state(iport, isci_freed); 1657 isci_port_change_state(iport, isci_freed);
1651} 1658}
@@ -1726,24 +1733,55 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1726 return ret; 1733 return ret;
1727} 1734}
1728 1735
1729/**
1730 * isci_port_deformed() - This function is called by libsas when a port becomes
1731 * inactive.
1732 * @phy: This parameter specifies the libsas phy with the inactive port.
1733 *
1734 */
1735void isci_port_deformed(struct asd_sas_phy *phy) 1736void isci_port_deformed(struct asd_sas_phy *phy)
1736{ 1737{
1737 pr_debug("%s: sas_phy = %p\n", __func__, phy); 1738 struct isci_host *ihost = phy->ha->lldd_ha;
1739 struct isci_port *iport = phy->port->lldd_port;
1740 unsigned long flags;
1741 int i;
1742
1743 /* we got a port notification on a port that was subsequently
1744 * torn down and libsas is just now catching up
1745 */
1746 if (!iport)
1747 return;
1748
1749 spin_lock_irqsave(&ihost->scic_lock, flags);
1750 for (i = 0; i < SCI_MAX_PHYS; i++) {
1751 if (iport->active_phy_mask & 1 << i)
1752 break;
1753 }
1754 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1755
1756 if (i >= SCI_MAX_PHYS)
1757 dev_dbg(&ihost->pdev->dev, "%s: port: %ld\n",
1758 __func__, (long) (iport - &ihost->ports[0]));
1738} 1759}
1739 1760
1740/**
1741 * isci_port_formed() - This function is called by libsas when a port becomes
1742 * active.
1743 * @phy: This parameter specifies the libsas phy with the active port.
1744 *
1745 */
1746void isci_port_formed(struct asd_sas_phy *phy) 1761void isci_port_formed(struct asd_sas_phy *phy)
1747{ 1762{
1748 pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port); 1763 struct isci_host *ihost = phy->ha->lldd_ha;
1764 struct isci_phy *iphy = to_iphy(phy);
1765 struct asd_sas_port *port = phy->port;
1766 struct isci_port *iport;
1767 unsigned long flags;
1768 int i;
1769
1770 /* initial ports are formed as the driver is still initializing,
1771 * wait for that process to complete
1772 */
1773 wait_for_start(ihost);
1774
1775 spin_lock_irqsave(&ihost->scic_lock, flags);
1776 for (i = 0; i < SCI_MAX_PORTS; i++) {
1777 iport = &ihost->ports[i];
1778 if (iport->active_phy_mask & 1 << iphy->phy_index)
1779 break;
1780 }
1781 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1782
1783 if (i >= SCI_MAX_PORTS)
1784 iport = NULL;
1785
1786 port->lldd_port = iport;
1749} 1787}
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index 08116090eb70..6b42e84b6955 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -97,11 +97,9 @@ enum isci_status {
97struct isci_port { 97struct isci_port {
98 enum isci_status status; 98 enum isci_status status;
99 struct isci_host *isci_host; 99 struct isci_host *isci_host;
100 struct asd_sas_port sas_port;
101 struct list_head remote_dev_list; 100 struct list_head remote_dev_list;
102 spinlock_t state_lock; 101 spinlock_t state_lock;
103 struct list_head domain_dev_list; 102 struct list_head domain_dev_list;
104 struct completion start_complete;
105 struct completion hard_reset_complete; 103 struct completion hard_reset_complete;
106 enum sci_status hard_reset_status; 104 enum sci_status hard_reset_status;
107 struct sci_base_state_machine sm; 105 struct sci_base_state_machine sm;
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index dd74b6ceeb82..cff684fc1efc 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -1381,31 +1381,18 @@ void isci_remote_device_gone(struct domain_device *dev)
1381 * 1381 *
1382 * status, zero indicates success. 1382 * status, zero indicates success.
1383 */ 1383 */
1384int isci_remote_device_found(struct domain_device *domain_dev) 1384int isci_remote_device_found(struct domain_device *dev)
1385{ 1385{
1386 struct isci_host *isci_host = dev_to_ihost(domain_dev); 1386 struct isci_host *isci_host = dev_to_ihost(dev);
1387 struct isci_port *isci_port; 1387 struct isci_port *isci_port = dev->port->lldd_port;
1388 struct isci_phy *isci_phy;
1389 struct asd_sas_port *sas_port;
1390 struct asd_sas_phy *sas_phy;
1391 struct isci_remote_device *isci_device; 1388 struct isci_remote_device *isci_device;
1392 enum sci_status status; 1389 enum sci_status status;
1393 1390
1394 dev_dbg(&isci_host->pdev->dev, 1391 dev_dbg(&isci_host->pdev->dev,
1395 "%s: domain_device = %p\n", __func__, domain_dev); 1392 "%s: domain_device = %p\n", __func__, dev);
1396 1393
1397 wait_for_start(isci_host); 1394 if (!isci_port)
1398 1395 return -ENODEV;
1399 sas_port = domain_dev->port;
1400 sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy,
1401 port_phy_el);
1402 isci_phy = to_iphy(sas_phy);
1403 isci_port = isci_phy->isci_port;
1404
1405 /* we are being called for a device on this port,
1406 * so it has to come up eventually
1407 */
1408 wait_for_completion(&isci_port->start_complete);
1409 1396
1410 if ((isci_stopping == isci_port_get_state(isci_port)) || 1397 if ((isci_stopping == isci_port_get_state(isci_port)) ||
1411 (isci_stopped == isci_port_get_state(isci_port))) 1398 (isci_stopped == isci_port_get_state(isci_port)))
@@ -1419,7 +1406,7 @@ int isci_remote_device_found(struct domain_device *domain_dev)
1419 INIT_LIST_HEAD(&isci_device->node); 1406 INIT_LIST_HEAD(&isci_device->node);
1420 1407
1421 spin_lock_irq(&isci_host->scic_lock); 1408 spin_lock_irq(&isci_host->scic_lock);
1422 isci_device->domain_dev = domain_dev; 1409 isci_device->domain_dev = dev;
1423 isci_device->isci_port = isci_port; 1410 isci_device->isci_port = isci_port;
1424 list_add_tail(&isci_device->node, &isci_port->remote_dev_list); 1411 list_add_tail(&isci_device->node, &isci_port->remote_dev_list);
1425 1412
@@ -1432,7 +1419,7 @@ int isci_remote_device_found(struct domain_device *domain_dev)
1432 1419
1433 if (status == SCI_SUCCESS) { 1420 if (status == SCI_SUCCESS) {
1434 /* device came up, advertise it to the world */ 1421 /* device came up, advertise it to the world */
1435 domain_dev->lldd_dev = isci_device; 1422 dev->lldd_dev = isci_device;
1436 } else 1423 } else
1437 isci_put_device(isci_device); 1424 isci_put_device(isci_device);
1438 spin_unlock_irq(&isci_host->scic_lock); 1425 spin_unlock_irq(&isci_host->scic_lock);