|
@@ -81,12 +81,17 @@
|
|
|
/* Device instance number, incremented each time a device is probed. */
|
|
|
static int instance;
|
|
|
|
|
|
+struct list_head online_list;
|
|
|
+struct list_head removing_list;
|
|
|
+spinlock_t dev_lock;
|
|
|
+
|
|
|
/*
|
|
|
* Global variable used to hold the major block device number
|
|
|
* allocated in mtip_init().
|
|
|
*/
|
|
|
static int mtip_major;
|
|
|
static struct dentry *dfs_parent;
|
|
|
+static struct dentry *dfs_device_status;
|
|
|
|
|
|
static u32 cpu_use[NR_CPUS];
|
|
|
|
|
@@ -2707,6 +2712,100 @@ static ssize_t mtip_hw_show_status(struct device *dev,
|
|
|
|
|
|
static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
|
|
|
|
|
|
+/* debugsfs entries */
|
|
|
+
|
|
|
+static ssize_t show_device_status(struct device_driver *drv, char *buf)
|
|
|
+{
|
|
|
+ int size = 0;
|
|
|
+ struct driver_data *dd, *tmp;
|
|
|
+ unsigned long flags;
|
|
|
+ char id_buf[42];
|
|
|
+ u16 status = 0;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&dev_lock, flags);
|
|
|
+ size += sprintf(&buf[size], "Devices Present:\n");
|
|
|
+ list_for_each_entry_safe(dd, tmp, &online_list, online_list) {
|
|
|
+ if (dd && dd->pdev) {
|
|
|
+ if (dd->port &&
|
|
|
+ dd->port->identify &&
|
|
|
+ dd->port->identify_valid) {
|
|
|
+ strlcpy(id_buf,
|
|
|
+ (char *) (dd->port->identify + 10), 21);
|
|
|
+ status = *(dd->port->identify + 141);
|
|
|
+ } else {
|
|
|
+ memset(id_buf, 0, 42);
|
|
|
+ status = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dd->port &&
|
|
|
+ test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
|
|
|
+ size += sprintf(&buf[size],
|
|
|
+ " device %s %s (ftl rebuild %d %%)\n",
|
|
|
+ dev_name(&dd->pdev->dev),
|
|
|
+ id_buf,
|
|
|
+ status);
|
|
|
+ } else {
|
|
|
+ size += sprintf(&buf[size],
|
|
|
+ " device %s %s\n",
|
|
|
+ dev_name(&dd->pdev->dev),
|
|
|
+ id_buf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ size += sprintf(&buf[size], "Devices Being Removed:\n");
|
|
|
+ list_for_each_entry_safe(dd, tmp, &removing_list, remove_list) {
|
|
|
+ if (dd && dd->pdev) {
|
|
|
+ if (dd->port &&
|
|
|
+ dd->port->identify &&
|
|
|
+ dd->port->identify_valid) {
|
|
|
+ strlcpy(id_buf,
|
|
|
+ (char *) (dd->port->identify+10), 21);
|
|
|
+ status = *(dd->port->identify + 141);
|
|
|
+ } else {
|
|
|
+ memset(id_buf, 0, 42);
|
|
|
+ status = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dd->port &&
|
|
|
+ test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
|
|
|
+ size += sprintf(&buf[size],
|
|
|
+ " device %s %s (ftl rebuild %d %%)\n",
|
|
|
+ dev_name(&dd->pdev->dev),
|
|
|
+ id_buf,
|
|
|
+ status);
|
|
|
+ } else {
|
|
|
+ size += sprintf(&buf[size],
|
|
|
+ " device %s %s\n",
|
|
|
+ dev_name(&dd->pdev->dev),
|
|
|
+ id_buf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spin_unlock_irqrestore(&dev_lock, flags);
|
|
|
+
|
|
|
+ return size;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t mtip_hw_read_device_status(struct file *f, char __user *ubuf,
|
|
|
+ size_t len, loff_t *offset)
|
|
|
+{
|
|
|
+ int size = *offset;
|
|
|
+ char buf[MTIP_DFS_MAX_BUF_SIZE];
|
|
|
+
|
|
|
+ if (!len || *offset)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ size += show_device_status(NULL, buf);
|
|
|
+
|
|
|
+ *offset = size <= len ? size : len;
|
|
|
+ size = copy_to_user(ubuf, buf, *offset);
|
|
|
+ if (size)
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ return *offset;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
|
|
|
size_t len, loff_t *offset)
|
|
|
{
|
|
@@ -2801,6 +2900,13 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
|
|
|
return *offset;
|
|
|
}
|
|
|
|
|
|
+static const struct file_operations mtip_device_status_fops = {
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ .open = simple_open,
|
|
|
+ .read = mtip_hw_read_device_status,
|
|
|
+ .llseek = no_llseek,
|
|
|
+};
|
|
|
+
|
|
|
static const struct file_operations mtip_regs_fops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.open = simple_open,
|
|
@@ -4158,6 +4264,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
|
|
|
const struct cpumask *node_mask;
|
|
|
int cpu, i = 0, j = 0;
|
|
|
int my_node = NUMA_NO_NODE;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
/* Allocate memory for this devices private data. */
|
|
|
my_node = pcibus_to_node(pdev->bus);
|
|
@@ -4215,6 +4322,9 @@ static int mtip_pci_probe(struct pci_dev *pdev,
|
|
|
dd->pdev = pdev;
|
|
|
dd->numa_node = my_node;
|
|
|
|
|
|
+ INIT_LIST_HEAD(&dd->online_list);
|
|
|
+ INIT_LIST_HEAD(&dd->remove_list);
|
|
|
+
|
|
|
memset(dd->workq_name, 0, 32);
|
|
|
snprintf(dd->workq_name, 31, "mtipq%d", dd->instance);
|
|
|
|
|
@@ -4304,6 +4414,12 @@ static int mtip_pci_probe(struct pci_dev *pdev,
|
|
|
set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
|
|
|
else
|
|
|
rv = 0; /* device in rebuild state, return 0 from probe */
|
|
|
+
|
|
|
+ /* Add to online list even if in ftl rebuild */
|
|
|
+ spin_lock_irqsave(&dev_lock, flags);
|
|
|
+ list_add(&dd->online_list, &online_list);
|
|
|
+ spin_unlock_irqrestore(&dev_lock, flags);
|
|
|
+
|
|
|
goto done;
|
|
|
|
|
|
block_initialize_err:
|
|
@@ -4337,9 +4453,15 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|
|
{
|
|
|
struct driver_data *dd = pci_get_drvdata(pdev);
|
|
|
int counter = 0;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev_lock, flags);
|
|
|
+ list_del_init(&dd->online_list);
|
|
|
+ list_add(&dd->remove_list, &removing_list);
|
|
|
+ spin_unlock_irqrestore(&dev_lock, flags);
|
|
|
+
|
|
|
if (mtip_check_surprise_removal(pdev)) {
|
|
|
while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
|
|
|
counter++;
|
|
@@ -4365,6 +4487,10 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|
|
|
|
|
pci_disable_msi(pdev);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev_lock, flags);
|
|
|
+ list_del_init(&dd->remove_list);
|
|
|
+ spin_unlock_irqrestore(&dev_lock, flags);
|
|
|
+
|
|
|
kfree(dd);
|
|
|
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
|
|
|
}
|
|
@@ -4512,6 +4638,11 @@ static int __init mtip_init(void)
|
|
|
|
|
|
pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
|
|
|
|
|
|
+ spin_lock_init(&dev_lock);
|
|
|
+
|
|
|
+ INIT_LIST_HEAD(&online_list);
|
|
|
+ INIT_LIST_HEAD(&removing_list);
|
|
|
+
|
|
|
/* Allocate a major block device number to use with this driver. */
|
|
|
error = register_blkdev(0, MTIP_DRV_NAME);
|
|
|
if (error <= 0) {
|
|
@@ -4521,11 +4652,18 @@ static int __init mtip_init(void)
|
|
|
}
|
|
|
mtip_major = error;
|
|
|
|
|
|
- if (!dfs_parent) {
|
|
|
- dfs_parent = debugfs_create_dir("rssd", NULL);
|
|
|
- if (IS_ERR_OR_NULL(dfs_parent)) {
|
|
|
- pr_warn("Error creating debugfs parent\n");
|
|
|
- dfs_parent = NULL;
|
|
|
+ dfs_parent = debugfs_create_dir("rssd", NULL);
|
|
|
+ if (IS_ERR_OR_NULL(dfs_parent)) {
|
|
|
+ pr_warn("Error creating debugfs parent\n");
|
|
|
+ dfs_parent = NULL;
|
|
|
+ }
|
|
|
+ if (dfs_parent) {
|
|
|
+ dfs_device_status = debugfs_create_file("device_status",
|
|
|
+ S_IRUGO, dfs_parent, NULL,
|
|
|
+ &mtip_device_status_fops);
|
|
|
+ if (IS_ERR_OR_NULL(dfs_device_status)) {
|
|
|
+ pr_err("Error creating device_status node\n");
|
|
|
+ dfs_device_status = NULL;
|
|
|
}
|
|
|
}
|
|
|
|