aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-03-20 13:53:24 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-04-23 07:08:56 -0400
commit9487669fc225092cf315e1291ece28e23e6754f3 (patch)
treeb07d2c3250f44e3262d9580295ef4ecd501ba371 /drivers/scsi
parentec236e526777ea8825e6e0c3673a40389692eabf (diff)
[SCSI] libsas: unify domain_device sas_rphy lifetimes
Since the domain_device can out live the scsi_target we need the rphy to follow suit otherwise we run into issues like: BUG: unable to handle kernel NULL pointer dereference at 0000000000000050 IP: [<ffffffffa011561b>] sas_ata_printk+0x43/0x6f [libsas] PGD 0 Oops: 0000 [#1] SMP CPU 1 Modules linked in: ses enclosure isci libsas scsi_transport_sas fuse sunrpc cpufreq_ondemand acpi_cpufreq freq_table mperf microcode pcspkr igb joydev iTCO_wdt ioatdma iTCO_vendor_support i2c_i801 i2c_core dca wmi hed ipv6 pata_acpi ata_generic [last unloaded: scsi_wait_scan] Pid: 129, comm: kworker/u:3 Not tainted 3.3.0-rc5-isci+ #1 Intel Corporation SandyBridge Platform/To be filled by O.E.M. RIP: 0010:[<ffffffffa011561b>] [<ffffffffa011561b>] sas_ata_printk+0x43/0x6f [libsas] RSP: 0018:ffff88042232dd70 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffff8804283165b8 RCX: ffff88042232dda0 RDX: ffff88042232dd78 RSI: ffff8804283165b8 RDI: ffffffffa01188d7 RBP: ffff88042232ddd0 R08: ffff880388454000 R09: ffff8803edfde1f8 R10: ffff8803edfde1f8 R11: ffff8803edfde1f8 R12: ffff880428316750 R13: ffff880388454000 R14: ffff8803f88b31d0 R15: ffff8803f8b21d50 FS: 0000000000000000(0000) GS:ffff88042ee20000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000050 CR3: 0000000001a05000 CR4: 00000000000406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kworker/u:3 (pid: 129, threadinfo ffff88042232c000, task ffff88042230c920) Stack: 0000000000000000 ffff880400000018 ffff88042232dde0 ffff88042232dda0 ffffffffa01188c4 ffff88042ee93af0 ffff88042232ddb0 ffffffff8100e047 ffff88042232de10 ffff880420e5a2c8 ffff8803f8b21d50 ffff8803edfde1f8 Call Trace: [<ffffffff8100e047>] ? load_TLS+0xb/0xf [<ffffffffa01156ad>] async_sas_ata_eh+0x66/0x95 [libsas] [<ffffffff810655e1>] async_run_entry_fn+0x9e/0x131 Reported-by: Tom Jackson <thomas.p.jackson@intel.com> Tested-by: Tom Jackson <thomas.p.jackson@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libsas/sas_discover.c11
-rw-r--r--drivers/scsi/libsas/sas_expander.c6
2 files changed, 10 insertions, 7 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 658f16cc2f03..13b5891f9961 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -151,6 +151,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
151 sas_device_set_phy(dev, port->port); 151 sas_device_set_phy(dev, port->port);
152 152
153 dev->rphy = rphy; 153 dev->rphy = rphy;
154 get_device(&dev->rphy->dev);
154 155
155 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV) 156 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
156 list_add_tail(&dev->disco_list_node, &port->disco_list); 157 list_add_tail(&dev->disco_list_node, &port->disco_list);
@@ -255,6 +256,9 @@ void sas_free_device(struct kref *kref)
255{ 256{
256 struct domain_device *dev = container_of(kref, typeof(*dev), kref); 257 struct domain_device *dev = container_of(kref, typeof(*dev), kref);
257 258
259 put_device(&dev->rphy->dev);
260 dev->rphy = NULL;
261
258 if (dev->parent) 262 if (dev->parent)
259 sas_put_device(dev->parent); 263 sas_put_device(dev->parent);
260 264
@@ -301,7 +305,6 @@ static void sas_destruct_devices(struct work_struct *work)
301 305
302 sas_remove_children(&dev->rphy->dev); 306 sas_remove_children(&dev->rphy->dev);
303 sas_rphy_delete(dev->rphy); 307 sas_rphy_delete(dev->rphy);
304 dev->rphy = NULL;
305 sas_unregister_common_dev(port, dev); 308 sas_unregister_common_dev(port, dev);
306 } 309 }
307} 310}
@@ -313,11 +316,11 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
313 /* this rphy never saw sas_rphy_add */ 316 /* this rphy never saw sas_rphy_add */
314 list_del_init(&dev->disco_list_node); 317 list_del_init(&dev->disco_list_node);
315 sas_rphy_free(dev->rphy); 318 sas_rphy_free(dev->rphy);
316 dev->rphy = NULL;
317 sas_unregister_common_dev(port, dev); 319 sas_unregister_common_dev(port, dev);
320 return;
318 } 321 }
319 322
320 if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { 323 if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
321 sas_rphy_unlink(dev->rphy); 324 sas_rphy_unlink(dev->rphy);
322 list_move_tail(&dev->disco_list_node, &port->destroy_list); 325 list_move_tail(&dev->disco_list_node, &port->destroy_list);
323 sas_discover_event(dev->port, DISCE_DESTRUCT); 326 sas_discover_event(dev->port, DISCE_DESTRUCT);
@@ -417,8 +420,6 @@ static void sas_discover_domain(struct work_struct *work)
417 420
418 if (error) { 421 if (error) {
419 sas_rphy_free(dev->rphy); 422 sas_rphy_free(dev->rphy);
420 dev->rphy = NULL;
421
422 list_del_init(&dev->disco_list_node); 423 list_del_init(&dev->disco_list_node);
423 spin_lock_irq(&port->dev_list_lock); 424 spin_lock_irq(&port->dev_list_lock);
424 list_del_init(&dev->dev_list_node); 425 list_del_init(&dev->dev_list_node);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 833bea067a77..37c3c3f5f35d 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -783,6 +783,7 @@ static struct domain_device *sas_ex_discover_end_dev(
783 sas_init_dev(child); 783 sas_init_dev(child);
784 784
785 child->rphy = rphy; 785 child->rphy = rphy;
786 get_device(&rphy->dev);
786 787
787 list_add_tail(&child->disco_list_node, &parent->port->disco_list); 788 list_add_tail(&child->disco_list_node, &parent->port->disco_list);
788 789
@@ -806,6 +807,7 @@ static struct domain_device *sas_ex_discover_end_dev(
806 sas_init_dev(child); 807 sas_init_dev(child);
807 808
808 child->rphy = rphy; 809 child->rphy = rphy;
810 get_device(&rphy->dev);
809 sas_fill_in_rphy(child, rphy); 811 sas_fill_in_rphy(child, rphy);
810 812
811 list_add_tail(&child->disco_list_node, &parent->port->disco_list); 813 list_add_tail(&child->disco_list_node, &parent->port->disco_list);
@@ -830,8 +832,6 @@ static struct domain_device *sas_ex_discover_end_dev(
830 832
831 out_list_del: 833 out_list_del:
832 sas_rphy_free(child->rphy); 834 sas_rphy_free(child->rphy);
833 child->rphy = NULL;
834
835 list_del(&child->disco_list_node); 835 list_del(&child->disco_list_node);
836 spin_lock_irq(&parent->port->dev_list_lock); 836 spin_lock_irq(&parent->port->dev_list_lock);
837 list_del(&child->dev_list_node); 837 list_del(&child->dev_list_node);
@@ -911,6 +911,7 @@ static struct domain_device *sas_ex_discover_expander(
911 } 911 }
912 port = parent->port; 912 port = parent->port;
913 child->rphy = rphy; 913 child->rphy = rphy;
914 get_device(&rphy->dev);
914 edev = rphy_to_expander_device(rphy); 915 edev = rphy_to_expander_device(rphy);
915 child->dev_type = phy->attached_dev_type; 916 child->dev_type = phy->attached_dev_type;
916 kref_get(&parent->kref); 917 kref_get(&parent->kref);
@@ -934,6 +935,7 @@ static struct domain_device *sas_ex_discover_expander(
934 935
935 res = sas_discover_expander(child); 936 res = sas_discover_expander(child);
936 if (res) { 937 if (res) {
938 sas_rphy_delete(rphy);
937 spin_lock_irq(&parent->port->dev_list_lock); 939 spin_lock_irq(&parent->port->dev_list_lock);
938 list_del(&child->dev_list_node); 940 list_del(&child->dev_list_node);
939 spin_unlock_irq(&parent->port->dev_list_lock); 941 spin_unlock_irq(&parent->port->dev_list_lock);