aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/isci/host.c21
-rw-r--r--drivers/scsi/isci/host.h17
-rw-r--r--drivers/scsi/isci/init.c27
-rw-r--r--drivers/scsi/isci/isci.h1
-rw-r--r--drivers/scsi/isci/remote_device.c73
-rw-r--r--drivers/scsi/isci/remote_device.h2
6 files changed, 68 insertions, 73 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 8d255666a657..ae5d46022073 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -378,8 +378,7 @@ static void __iomem *smu_base(struct isci_host *isci_host)
378 378
379int isci_host_init(struct isci_host *isci_host) 379int isci_host_init(struct isci_host *isci_host)
380{ 380{
381 int err = 0; 381 int err = 0, i;
382 int index = 0;
383 enum sci_status status; 382 enum sci_status status;
384 struct scic_sds_controller *controller; 383 struct scic_sds_controller *controller;
385 union scic_oem_parameters scic_oem_params; 384 union scic_oem_parameters scic_oem_params;
@@ -509,13 +508,19 @@ int isci_host_init(struct isci_host *isci_host)
509 if (!isci_host->dma_pool) 508 if (!isci_host->dma_pool)
510 return -ENOMEM; 509 return -ENOMEM;
511 510
512 for (index = 0; index < SCI_MAX_PORTS; index++) 511 for (i = 0; i < SCI_MAX_PORTS; i++)
513 isci_port_init(&isci_host->isci_ports[index], 512 isci_port_init(&isci_host->isci_ports[i], isci_host, i);
514 isci_host,
515 index);
516 513
517 for (index = 0; index < SCI_MAX_PHYS; index++) 514 for (i = 0; i < SCI_MAX_PHYS; i++)
518 isci_phy_init(&isci_host->phys[index], isci_host, index); 515 isci_phy_init(&isci_host->phys[i], isci_host, i);
516
517 for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
518 struct isci_remote_device *idev = idev_by_id(isci_host, i);
519
520 INIT_LIST_HEAD(&idev->reqs_in_process);
521 INIT_LIST_HEAD(&idev->node);
522 spin_lock_init(&idev->state_lock);
523 }
519 524
520 return 0; 525 return 0;
521} 526}
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 6a6304c06976..3c69f1ffb1c3 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -61,6 +61,7 @@
61/*#include "task.h"*/ 61/*#include "task.h"*/
62#include "timers.h" 62#include "timers.h"
63#include "remote_device.h" 63#include "remote_device.h"
64#include "scic_remote_device.h"
64 65
65#define DRV_NAME "isci" 66#define DRV_NAME "isci"
66#define SCI_PCI_BAR_COUNT 2 67#define SCI_PCI_BAR_COUNT 2
@@ -117,8 +118,18 @@ struct isci_host {
117 struct list_head requests_to_complete; 118 struct list_head requests_to_complete;
118 struct list_head requests_to_abort; 119 struct list_head requests_to_abort;
119 spinlock_t scic_lock; 120 spinlock_t scic_lock;
121
122 /* careful only access this via idev_by_id */
123 struct isci_remote_device devices[0];
120}; 124};
121 125
126static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int i)
127{
128 void *p = ihost->devices;
129
130 return p + i * (sizeof(struct isci_remote_device) +
131 scic_remote_device_get_object_size());
132}
122 133
123/** 134/**
124 * struct isci_pci_info - This class represents the pci function containing the 135 * struct isci_pci_info - This class represents the pci function containing the
@@ -219,11 +230,7 @@ static inline void wait_for_device_start(struct isci_host *ihost, struct isci_re
219 230
220static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) 231static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
221{ 232{
222 /* todo switch to: 233 wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
223 * wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
224 * once devices are statically allocated
225 */
226 wait_for_completion(idev->cmp);
227} 234}
228 235
229/** 236/**
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index f1b8a51dd49f..2838beff43b8 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -64,7 +64,6 @@
64#include "sci_environment.h" 64#include "sci_environment.h"
65 65
66static struct scsi_transport_template *isci_transport_template; 66static struct scsi_transport_template *isci_transport_template;
67struct kmem_cache *isci_kmem_cache;
68 67
69static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { 68static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
70 { PCI_VDEVICE(INTEL, 0x1D61),}, 69 { PCI_VDEVICE(INTEL, 0x1D61),},
@@ -443,7 +442,10 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
443 struct Scsi_Host *shost; 442 struct Scsi_Host *shost;
444 int err; 443 int err;
445 444
446 isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); 445 isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host) +
446 SCI_MAX_REMOTE_DEVICES *
447 (sizeof(struct isci_remote_device) +
448 scic_remote_device_get_object_size()), GFP_KERNEL);
447 if (!isci_host) 449 if (!isci_host)
448 return NULL; 450 return NULL;
449 451
@@ -656,31 +658,17 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev)
656 658
657static __init int isci_init(void) 659static __init int isci_init(void)
658{ 660{
659 int err = -ENOMEM; 661 int err;
660 662
661 pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); 663 pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
662 664
663 isci_kmem_cache = kmem_cache_create(DRV_NAME,
664 sizeof(struct isci_remote_device) +
665 scic_remote_device_get_object_size(),
666 0, 0, NULL);
667 if (!isci_kmem_cache)
668 return err;
669
670 isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); 665 isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
671 if (!isci_transport_template) 666 if (!isci_transport_template)
672 goto err_kmem; 667 return -ENOMEM;
673 668
674 err = pci_register_driver(&isci_pci_driver); 669 err = pci_register_driver(&isci_pci_driver);
675 if (err) 670 if (err)
676 goto err_sas; 671 sas_release_transport(isci_transport_template);
677
678 return 0;
679
680 err_sas:
681 sas_release_transport(isci_transport_template);
682 err_kmem:
683 kmem_cache_destroy(isci_kmem_cache);
684 672
685 return err; 673 return err;
686} 674}
@@ -689,7 +677,6 @@ static __exit void isci_exit(void)
689{ 677{
690 pci_unregister_driver(&isci_pci_driver); 678 pci_unregister_driver(&isci_pci_driver);
691 sas_release_transport(isci_transport_template); 679 sas_release_transport(isci_transport_template);
692 kmem_cache_destroy(isci_kmem_cache);
693} 680}
694 681
695MODULE_LICENSE("Dual BSD/GPL"); 682MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index 9b9aa50954ce..24c67b039d4a 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -89,7 +89,6 @@
89#include "task.h" 89#include "task.h"
90#include "sata.h" 90#include "sata.h"
91 91
92extern struct kmem_cache *isci_kmem_cache;
93extern struct isci_firmware *isci_firmware; 92extern struct isci_firmware *isci_firmware;
94 93
95#define ISCI_FW_NAME "isci/isci_firmware.bin" 94#define ISCI_FW_NAME "isci/isci_firmware.bin"
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index db2259ce003f..48556e47bb9d 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -67,40 +67,35 @@
67 67
68/** 68/**
69 * isci_remote_device_deconstruct() - This function frees an isci_remote_device. 69 * isci_remote_device_deconstruct() - This function frees an isci_remote_device.
70 * @isci_host: This parameter specifies the isci host object. 70 * @ihost: This parameter specifies the isci host object.
71 * @isci_device: This parameter specifies the remote device to be freed. 71 * @idev: This parameter specifies the remote device to be freed.
72 * 72 *
73 */ 73 */
74static void isci_remote_device_deconstruct( 74static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_remote_device *idev)
75 struct isci_host *isci_host,
76 struct isci_remote_device *isci_device)
77{ 75{
78 dev_dbg(&isci_host->pdev->dev, 76 dev_dbg(&ihost->pdev->dev,
79 "%s: isci_device = %p\n", __func__, isci_device); 77 "%s: isci_device = %p\n", __func__, idev);
80 78
81 /* There should not be any outstanding io's. All paths to 79 /* There should not be any outstanding io's. All paths to
82 * here should go through isci_remote_device_nuke_requests. 80 * here should go through isci_remote_device_nuke_requests.
83 * If we hit this condition, we will need a way to complete 81 * If we hit this condition, we will need a way to complete
84 * io requests in process */ 82 * io requests in process */
85 while (!list_empty(&isci_device->reqs_in_process)) { 83 while (!list_empty(&idev->reqs_in_process)) {
86 84
87 dev_err(&isci_host->pdev->dev, 85 dev_err(&ihost->pdev->dev,
88 "%s: ** request list not empty! **\n", __func__); 86 "%s: ** request list not empty! **\n", __func__);
89 BUG(); 87 BUG();
90 } 88 }
91 89
92 /* Remove all related references to this device and free 90 scic_remote_device_destruct(to_sci_dev(idev));
93 * the cache object. 91 idev->domain_dev->lldd_dev = NULL;
94 */ 92 idev->domain_dev = NULL;
95 scic_remote_device_destruct(to_sci_dev(isci_device)); 93 idev->isci_port = NULL;
96 isci_device->domain_dev->lldd_dev = NULL; 94 list_del_init(&idev->node);
97 list_del(&isci_device->node); 95
98 96 clear_bit(IDEV_START_PENDING, &idev->flags);
99 clear_bit(IDEV_STOP_PENDING, &isci_device->flags); 97 clear_bit(IDEV_STOP_PENDING, &idev->flags);
100 clear_bit(IDEV_START_PENDING, &isci_device->flags); 98 wake_up(&ihost->eventq);
101 wake_up(&isci_host->eventq);
102 complete(isci_device->cmp);
103 kmem_cache_free(isci_kmem_cache, isci_device);
104} 99}
105 100
106 101
@@ -259,25 +254,27 @@ void isci_remote_device_nuke_requests(
259 * pointer to new isci_remote_device. 254 * pointer to new isci_remote_device.
260 */ 255 */
261static struct isci_remote_device * 256static struct isci_remote_device *
262isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) 257isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport)
263{ 258{
264 struct isci_remote_device *isci_device; 259 struct isci_remote_device *idev;
260 int i;
265 261
266 isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL); 262 for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
263 idev = idev_by_id(ihost, i);
264 if (!test_and_set_bit(IDEV_ALLOCATED, &idev->flags))
265 break;
266 }
267 267
268 if (!isci_device) { 268 if (i >= SCI_MAX_REMOTE_DEVICES) {
269 dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__); 269 dev_warn(&ihost->pdev->dev, "%s: failed\n", __func__);
270 return NULL; 270 return NULL;
271 } 271 }
272 272
273 INIT_LIST_HEAD(&isci_device->reqs_in_process); 273 BUG_ON(!list_empty(&idev->reqs_in_process));
274 INIT_LIST_HEAD(&isci_device->node); 274 BUG_ON(!list_empty(&idev->node));
275 275 isci_remote_device_change_state(idev, isci_freed);
276 spin_lock_init(&isci_device->state_lock);
277 isci_remote_device_change_state(isci_device, isci_freed);
278
279 return isci_device;
280 276
277 return idev;
281} 278}
282 279
283/** 280/**
@@ -381,24 +378,22 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem
381{ 378{
382 enum sci_status status; 379 enum sci_status status;
383 unsigned long flags; 380 unsigned long flags;
384 DECLARE_COMPLETION_ONSTACK(completion);
385 381
386 dev_dbg(&ihost->pdev->dev, 382 dev_dbg(&ihost->pdev->dev,
387 "%s: isci_device = %p\n", __func__, idev); 383 "%s: isci_device = %p\n", __func__, idev);
388 384
389 isci_remote_device_change_state(idev, isci_stopping); 385 isci_remote_device_change_state(idev, isci_stopping);
390 set_bit(IDEV_STOP_PENDING, &idev->flags); 386 set_bit(IDEV_STOP_PENDING, &idev->flags);
391 idev->cmp = &completion;
392 387
393 spin_lock_irqsave(&ihost->scic_lock, flags); 388 spin_lock_irqsave(&ihost->scic_lock, flags);
394
395 status = scic_remote_device_stop(to_sci_dev(idev), 50); 389 status = scic_remote_device_stop(to_sci_dev(idev), 50);
396
397 spin_unlock_irqrestore(&ihost->scic_lock, flags); 390 spin_unlock_irqrestore(&ihost->scic_lock, flags);
398 391
399 /* Wait for the stop complete callback. */ 392 /* Wait for the stop complete callback. */
400 if (status == SCI_SUCCESS) 393 if (status == SCI_SUCCESS) {
401 wait_for_device_stop(ihost, idev); 394 wait_for_device_stop(ihost, idev);
395 clear_bit(IDEV_ALLOCATED, &idev->flags);
396 }
402 397
403 dev_dbg(&ihost->pdev->dev, 398 dev_dbg(&ihost->pdev->dev,
404 "%s: idev = %p - after completion wait\n", 399 "%s: idev = %p - after completion wait\n",
@@ -469,6 +464,8 @@ int isci_remote_device_found(struct domain_device *domain_dev)
469 return -ENODEV; 464 return -ENODEV;
470 465
471 isci_device = isci_remote_device_alloc(isci_host, isci_port); 466 isci_device = isci_remote_device_alloc(isci_host, isci_port);
467 if (!isci_device)
468 return -ENODEV;
472 469
473 INIT_LIST_HEAD(&isci_device->node); 470 INIT_LIST_HEAD(&isci_device->node);
474 domain_dev->lldd_dev = isci_device; 471 domain_dev->lldd_dev = isci_device;
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 3c22137c9f65..f45a5f064fce 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -63,8 +63,8 @@ struct isci_remote_device {
63 enum isci_status status; 63 enum isci_status status;
64 #define IDEV_START_PENDING 0 64 #define IDEV_START_PENDING 0
65 #define IDEV_STOP_PENDING 1 65 #define IDEV_STOP_PENDING 1
66 #define IDEV_ALLOCATED 2
66 unsigned long flags; 67 unsigned long flags;
67 struct completion *cmp;
68 struct isci_port *isci_port; 68 struct isci_port *isci_port;
69 struct domain_device *domain_dev; 69 struct domain_device *domain_dev;
70 struct list_head node; 70 struct list_head node;