mtip32xx: Add new bitwise flag 'dd_flag'

* Merged the following flags into one variable 'dd_flag':
        * drv_cleanup_done
        * resumeflag
* Added the following flags into 'dd_flag'
        * remove pending
        * init done
* Removed 'ftlrebuildflag' (similar flag is already part of mti_port->flags)

Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Asai Thambi S P 2012-04-09 08:35:38 +02:00 committed by Jens Axboe
parent 6d27f09a63
commit 45038367c2
2 changed files with 168 additions and 55 deletions

View File

@ -36,6 +36,7 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <../drivers/ata/ahci.h> #include <../drivers/ata/ahci.h>
#include <linux/export.h>
#include "mtip32xx.h" #include "mtip32xx.h"
#define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32) #define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32)
@ -44,6 +45,7 @@
#define HW_PORT_PRIV_DMA_SZ \ #define HW_PORT_PRIV_DMA_SZ \
(HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ) (HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ)
#define HOST_CAP_NZDMA (1 << 19)
#define HOST_HSORG 0xFC #define HOST_HSORG 0xFC
#define HSORG_DISABLE_SLOTGRP_INTR (1<<24) #define HSORG_DISABLE_SLOTGRP_INTR (1<<24)
#define HSORG_DISABLE_SLOTGRP_PXIS (1<<16) #define HSORG_DISABLE_SLOTGRP_PXIS (1<<16)
@ -139,6 +141,12 @@ static void mtip_command_cleanup(struct driver_data *dd)
int group = 0, commandslot = 0, commandindex = 0; int group = 0, commandslot = 0, commandindex = 0;
struct mtip_cmd *command; struct mtip_cmd *command;
struct mtip_port *port = dd->port; struct mtip_port *port = dd->port;
static int in_progress;
if (in_progress)
return;
in_progress = 1;
for (group = 0; group < 4; group++) { for (group = 0; group < 4; group++) {
for (commandslot = 0; commandslot < 32; commandslot++) { for (commandslot = 0; commandslot < 32; commandslot++) {
@ -165,7 +173,8 @@ static void mtip_command_cleanup(struct driver_data *dd)
up(&port->cmd_slot); up(&port->cmd_slot);
atomic_set(&dd->drv_cleanup_done, true); set_bit(MTIP_DD_FLAG_CLEANUP_BIT, &dd->dd_flag);
in_progress = 0;
} }
/* /*
@ -262,6 +271,9 @@ static int hba_reset_nosleep(struct driver_data *dd)
&& time_before(jiffies, timeout)) && time_before(jiffies, timeout))
mdelay(1); mdelay(1);
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag))
return -1;
if (readl(dd->mmio + HOST_CTL) & HOST_RESET) if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
return -1; return -1;
@ -451,6 +463,9 @@ static void mtip_restart_port(struct mtip_port *port)
&& time_before(jiffies, timeout)) && time_before(jiffies, timeout))
; ;
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &port->dd->dd_flag))
return;
/* /*
* Chip quirk: escalate to hba reset if * Chip quirk: escalate to hba reset if
* PxCMD.CR not clear after 500 ms * PxCMD.CR not clear after 500 ms
@ -479,6 +494,9 @@ static void mtip_restart_port(struct mtip_port *port)
while (time_before(jiffies, timeout)) while (time_before(jiffies, timeout))
; ;
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &port->dd->dd_flag))
return;
/* Clear PxSCTL.DET */ /* Clear PxSCTL.DET */
writel(readl(port->mmio + PORT_SCR_CTL) & ~1, writel(readl(port->mmio + PORT_SCR_CTL) & ~1,
port->mmio + PORT_SCR_CTL); port->mmio + PORT_SCR_CTL);
@ -490,6 +508,9 @@ static void mtip_restart_port(struct mtip_port *port)
&& time_before(jiffies, timeout)) && time_before(jiffies, timeout))
; ;
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &port->dd->dd_flag))
return;
if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0) if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
dev_warn(&port->dd->pdev->dev, dev_warn(&port->dd->pdev->dev,
"COM reset failed\n"); "COM reset failed\n");
@ -520,7 +541,7 @@ static void mtip_timeout_function(unsigned long int data)
if (unlikely(!port)) if (unlikely(!port))
return; return;
if (atomic_read(&port->dd->resumeflag) == true) { if (test_bit(MTIP_DD_FLAG_RESUME_BIT, &port->dd->dd_flag)) {
mod_timer(&port->cmd_timer, mod_timer(&port->cmd_timer,
jiffies + msecs_to_jiffies(30000)); jiffies + msecs_to_jiffies(30000));
return; return;
@ -970,6 +991,9 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
/* don't proceed further */ /* don't proceed further */
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&dd->dd_flag))
return rv;
mtip_process_errors(dd, port_stat & PORT_IRQ_ERR); mtip_process_errors(dd, port_stat & PORT_IRQ_ERR);
} }
@ -1040,6 +1064,9 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
msleep(20); msleep(20);
continue; /* svc thd is actively issuing commands */ continue; /* svc thd is actively issuing commands */
} }
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&port->dd->dd_flag))
return -EFAULT;
/* /*
* Ignore s_active bit 0 of array element 0. * Ignore s_active bit 0 of array element 0.
* This bit will always be set * This bit will always be set
@ -1161,6 +1188,12 @@ static int mtip_exec_internal_command(struct mtip_port *port,
"Internal command did not complete [%d] " "Internal command did not complete [%d] "
"within timeout of %lu ms\n", "within timeout of %lu ms\n",
atomic, timeout); atomic, timeout);
if (mtip_check_surprise_removal(port->dd->pdev) ||
test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&port->dd->dd_flag)) {
rv = -ENXIO;
goto exec_ic_exit;
}
rv = -EAGAIN; rv = -EAGAIN;
} }
@ -1168,6 +1201,15 @@ static int mtip_exec_internal_command(struct mtip_port *port,
& (1 << MTIP_TAG_INTERNAL)) { & (1 << MTIP_TAG_INTERNAL)) {
dev_warn(&port->dd->pdev->dev, dev_warn(&port->dd->pdev->dev,
"Retiring internal command but CI is 1.\n"); "Retiring internal command but CI is 1.\n");
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&port->dd->dd_flag)) {
hba_reset_nosleep(port->dd);
rv = -ENXIO;
} else {
mtip_restart_port(port);
rv = -EAGAIN;
}
goto exec_ic_exit;
} }
} else { } else {
@ -1177,8 +1219,14 @@ static int mtip_exec_internal_command(struct mtip_port *port,
while ((readl( while ((readl(
port->cmd_issue[MTIP_TAG_INTERNAL]) port->cmd_issue[MTIP_TAG_INTERNAL])
& (1 << MTIP_TAG_INTERNAL)) & (1 << MTIP_TAG_INTERNAL))
&& time_before(jiffies, timeout)) && time_before(jiffies, timeout)) {
; if (mtip_check_surprise_removal(port->dd->pdev) ||
test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&port->dd->dd_flag)) {
rv = -ENXIO;
goto exec_ic_exit;
}
}
if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
& (1 << MTIP_TAG_INTERNAL)) { & (1 << MTIP_TAG_INTERNAL)) {
@ -1186,9 +1234,17 @@ static int mtip_exec_internal_command(struct mtip_port *port,
"Internal command did not complete [%d]\n", "Internal command did not complete [%d]\n",
atomic); atomic);
rv = -EAGAIN; rv = -EAGAIN;
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&port->dd->dd_flag)) {
hba_reset_nosleep(port->dd);
rv = -ENXIO;
} else {
mtip_restart_port(port);
rv = -EAGAIN;
} }
} }
}
exec_ic_exit:
/* Clear the allocated and active bits for the internal command. */ /* Clear the allocated and active bits for the internal command. */
atomic_set(&int_cmd->active, 0); atomic_set(&int_cmd->active, 0);
release_slot(port, MTIP_TAG_INTERNAL); release_slot(port, MTIP_TAG_INTERNAL);
@ -1242,6 +1298,9 @@ static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer)
int rv = 0; int rv = 0;
struct host_to_dev_fis fis; struct host_to_dev_fis fis;
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &port->dd->dd_flag))
return -EFAULT;
/* Build the FIS. */ /* Build the FIS. */
memset(&fis, 0, sizeof(struct host_to_dev_fis)); memset(&fis, 0, sizeof(struct host_to_dev_fis));
fis.type = 0x27; fis.type = 0x27;
@ -1507,9 +1566,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command)
fis.device = command[6] & ~0x10; /* Clear the dev bit*/ fis.device = command[6] & ~0x10; /* Clear the dev bit*/
dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, " dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, nsect %x, sect %x, lcyl %x, hcyl %x, sel %x\n",
"nsect %x, sect %x, lcyl %x, "
"hcyl %x, sel %x\n",
__func__, __func__,
command[0], command[0],
command[1], command[1],
@ -1536,8 +1593,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command)
command[4] = reply->cyl_low; command[4] = reply->cyl_low;
command[5] = reply->cyl_hi; command[5] = reply->cyl_hi;
dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, " dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, err %x , cyl_lo %x cyl_hi %x\n",
"err %x , cyl_lo %x cyl_hi %x\n",
__func__, __func__,
command[0], command[0],
command[1], command[1],
@ -2082,14 +2138,10 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
struct host_to_dev_fis *fis; struct host_to_dev_fis *fis;
struct mtip_port *port = dd->port; struct mtip_port *port = dd->port;
struct mtip_cmd *command = &port->commands[tag]; struct mtip_cmd *command = &port->commands[tag];
int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
/* Map the scatter list for DMA access */ /* Map the scatter list for DMA access */
if (dir == READ) nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
nents = dma_map_sg(&dd->pdev->dev, command->sg,
nents, DMA_FROM_DEVICE);
else
nents = dma_map_sg(&dd->pdev->dev, command->sg,
nents, DMA_TO_DEVICE);
command->scatter_ents = nents; command->scatter_ents = nents;
@ -2129,7 +2181,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
*/ */
command->comp_data = dd; command->comp_data = dd;
command->comp_func = mtip_async_complete; command->comp_func = mtip_async_complete;
command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); command->direction = dma_dir;
/* /*
* Set the completion function and data for the command passed * Set the completion function and data for the command passed
@ -2193,6 +2245,10 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
down(&dd->port->cmd_slot); down(&dd->port->cmd_slot);
*tag = get_slot(dd->port); *tag = get_slot(dd->port);
if (unlikely(test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag))) {
up(&dd->port->cmd_slot);
return NULL;
}
if (unlikely(*tag < 0)) if (unlikely(*tag < 0))
return NULL; return NULL;
@ -2209,7 +2265,7 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
* return value * return value
* The size, in bytes, of the data copied into buf. * The size, in bytes, of the data copied into buf.
*/ */
static ssize_t hw_show_registers(struct device *dev, static ssize_t mtip_hw_show_registers(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
@ -2255,7 +2311,7 @@ static ssize_t hw_show_registers(struct device *dev,
return size; return size;
} }
static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL); static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL);
/* /*
* Create the sysfs related attributes. * Create the sysfs related attributes.
@ -2386,10 +2442,12 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
"FTL rebuild in progress. Polling for completion.\n"); "FTL rebuild in progress. Polling for completion.\n");
start = jiffies; start = jiffies;
dd->ftlrebuildflag = 1;
timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS); timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS);
do { do {
if (unlikely(test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&dd->dd_flag)))
return -EFAULT;
if (mtip_check_surprise_removal(dd->pdev)) if (mtip_check_surprise_removal(dd->pdev))
return -EFAULT; return -EFAULT;
@ -2410,22 +2468,17 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
dev_warn(&dd->pdev->dev, dev_warn(&dd->pdev->dev,
"FTL rebuild complete (%d secs).\n", "FTL rebuild complete (%d secs).\n",
jiffies_to_msecs(jiffies - start) / 1000); jiffies_to_msecs(jiffies - start) / 1000);
dd->ftlrebuildflag = 0;
mtip_block_initialize(dd); mtip_block_initialize(dd);
break; return 0;
} }
ssleep(10); ssleep(10);
} while (time_before(jiffies, timeout)); } while (time_before(jiffies, timeout));
/* Check for timeout */ /* Check for timeout */
if (dd->ftlrebuildflag) {
dev_err(&dd->pdev->dev, dev_err(&dd->pdev->dev,
"Timed out waiting for FTL rebuild to complete (%d secs).\n", "Timed out waiting for FTL rebuild to complete (%d secs).\n",
jiffies_to_msecs(jiffies - start) / 1000); jiffies_to_msecs(jiffies - start) / 1000);
return -EFAULT; return -EFAULT;
}
return 0;
} }
/* /*
@ -2456,6 +2509,9 @@ static int mtip_service_thread(void *data)
if (kthread_should_stop()) if (kthread_should_stop())
break; break;
if (unlikely(test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT,
&dd->dd_flag)))
break;
set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
slot = 1; slot = 1;
@ -2515,6 +2571,7 @@ static int mtip_hw_init(struct driver_data *dd)
int i; int i;
int rv; int rv;
unsigned int num_command_slots; unsigned int num_command_slots;
unsigned long timeout, timetaken;
dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR]; dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
@ -2625,13 +2682,42 @@ static int mtip_hw_init(struct driver_data *dd)
dd->port->mmio + i*0x80 + PORT_SDBV; dd->port->mmio + i*0x80 + PORT_SDBV;
} }
/* Reset the HBA. */ timetaken = jiffies;
timeout = jiffies + msecs_to_jiffies(30000);
while (((readl(dd->port->mmio + PORT_SCR_STAT) & 0x0F) != 0x03) &&
time_before(jiffies, timeout)) {
mdelay(100);
}
if (unlikely(mtip_check_surprise_removal(dd->pdev))) {
timetaken = jiffies - timetaken;
dev_warn(&dd->pdev->dev,
"Surprise removal detected at %u ms\n",
jiffies_to_msecs(timetaken));
rv = -ENODEV;
goto out2 ;
}
if (unlikely(test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag))) {
timetaken = jiffies - timetaken;
dev_warn(&dd->pdev->dev,
"Removal detected at %u ms\n",
jiffies_to_msecs(timetaken));
rv = -EFAULT;
goto out2;
}
/* Conditionally reset the HBA. */
if (!(readl(dd->mmio + HOST_CAP) & HOST_CAP_NZDMA)) {
if (mtip_hba_reset(dd) < 0) { if (mtip_hba_reset(dd) < 0) {
dev_err(&dd->pdev->dev, dev_err(&dd->pdev->dev,
"Card did not reset within timeout\n"); "Card did not reset within timeout\n");
rv = -EIO; rv = -EIO;
goto out2; goto out2;
} }
} else {
/* Clear any pending interrupts on the HBA */
writel(readl(dd->mmio + HOST_IRQ_STAT),
dd->mmio + HOST_IRQ_STAT);
}
mtip_init_port(dd->port); mtip_init_port(dd->port);
mtip_start_port(dd->port); mtip_start_port(dd->port);
@ -2662,6 +2748,12 @@ static int mtip_hw_init(struct driver_data *dd)
mod_timer(&dd->port->cmd_timer, mod_timer(&dd->port->cmd_timer,
jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag)) {
rv = -EFAULT;
goto out3;
}
if (mtip_get_identify(dd->port, NULL) < 0) { if (mtip_get_identify(dd->port, NULL) < 0) {
rv = -EFAULT; rv = -EFAULT;
goto out3; goto out3;
@ -2714,9 +2806,12 @@ static int mtip_hw_exit(struct driver_data *dd)
* Send standby immediate (E0h) to the drive so that it * Send standby immediate (E0h) to the drive so that it
* saves its state. * saves its state.
*/ */
if (atomic_read(&dd->drv_cleanup_done) != true) { if (!test_bit(MTIP_DD_FLAG_CLEANUP_BIT, &dd->dd_flag)) {
mtip_standby_immediate(dd->port); if (test_bit(MTIP_FLAG_REBUILD_BIT, &dd->dd_flag))
if (mtip_standby_immediate(dd->port))
dev_warn(&dd->pdev->dev,
"STANDBY IMMEDIATE failed\n");
/* de-initialize the port. */ /* de-initialize the port. */
mtip_deinit_port(dd->port); mtip_deinit_port(dd->port);
@ -2894,6 +2989,9 @@ static int mtip_block_ioctl(struct block_device *dev,
if (!dd) if (!dd)
return -ENOTTY; return -ENOTTY;
if (unlikely(test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag)))
return -ENOTTY;
switch (cmd) { switch (cmd) {
case BLKFLSBUF: case BLKFLSBUF:
return -ENOTTY; return -ENOTTY;
@ -2929,6 +3027,9 @@ static int mtip_block_compat_ioctl(struct block_device *dev,
if (!dd) if (!dd)
return -ENOTTY; return -ENOTTY;
if (unlikely(test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag)))
return -ENOTTY;
switch (cmd) { switch (cmd) {
case BLKFLSBUF: case BLKFLSBUF:
return -ENOTTY; return -ENOTTY;
@ -3051,6 +3152,11 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
int nents = 0; int nents = 0;
int tag = 0; int tag = 0;
if (test_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag)) {
bio_endio(bio, -ENXIO);
return;
}
if (unlikely(!bio_has_data(bio))) { if (unlikely(!bio_has_data(bio))) {
blk_queue_flush(queue, 0); blk_queue_flush(queue, 0);
bio_endio(bio, 0); bio_endio(bio, 0);
@ -3063,7 +3169,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) { if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) {
dev_warn(&dd->pdev->dev, dev_warn(&dd->pdev->dev,
"Maximum number of SGL entries exceeded"); "Maximum number of SGL entries exceeded\n");
bio_io_error(bio); bio_io_error(bio);
mtip_hw_release_scatterlist(dd, tag); mtip_hw_release_scatterlist(dd, tag);
return; return;
@ -3212,8 +3318,10 @@ skip_create_disk:
kobject_put(kobj); kobject_put(kobj);
} }
if (dd->mtip_svc_handler) if (dd->mtip_svc_handler) {
set_bit(MTIP_DD_FLAG_INIT_DONE_BIT, &dd->dd_flag);
return rv; /* service thread created for handling rebuild */ return rv; /* service thread created for handling rebuild */
}
start_service_thread: start_service_thread:
sprintf(thd_name, "mtip_svc_thd_%02d", index); sprintf(thd_name, "mtip_svc_thd_%02d", index);
@ -3228,6 +3336,9 @@ start_service_thread:
goto kthread_run_error; goto kthread_run_error;
} }
if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC)
rv = wait_for_rebuild;
return rv; return rv;
kthread_run_error: kthread_run_error:
@ -3274,11 +3385,13 @@ static int mtip_block_remove(struct driver_data *dd)
} }
/* Clean up the sysfs attributes managed by the protocol layer. */ /* Clean up the sysfs attributes managed by the protocol layer. */
if (test_bit(MTIP_DD_FLAG_INIT_DONE_BIT, &dd->dd_flag)) {
kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
if (kobj) { if (kobj) {
mtip_hw_sysfs_exit(dd, kobj); mtip_hw_sysfs_exit(dd, kobj);
kobject_put(kobj); kobject_put(kobj);
} }
}
/* /*
* Delete our gendisk structure. This also removes the device * Delete our gendisk structure. This also removes the device
@ -3361,8 +3474,6 @@ static int mtip_pci_probe(struct pci_dev *pdev,
return -ENOMEM; return -ENOMEM;
} }
atomic_set(&dd->resumeflag, false);
/* Attach the private data to this PCI device. */ /* Attach the private data to this PCI device. */
pci_set_drvdata(pdev, dd); pci_set_drvdata(pdev, dd);
@ -3419,7 +3530,8 @@ static int mtip_pci_probe(struct pci_dev *pdev,
* instance number. * instance number.
*/ */
instance++; instance++;
if (rv != MTIP_FTL_REBUILD_MAGIC)
set_bit(MTIP_DD_FLAG_INIT_DONE_BIT, &dd->dd_flag);
goto done; goto done;
block_initialize_err: block_initialize_err:
@ -3433,9 +3545,6 @@ iomap_err:
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
return rv; return rv;
done: done:
/* Set the atomic variable as 0 */
atomic_set(&dd->drv_cleanup_done, false);
return rv; return rv;
} }
@ -3451,8 +3560,10 @@ static void mtip_pci_remove(struct pci_dev *pdev)
struct driver_data *dd = pci_get_drvdata(pdev); struct driver_data *dd = pci_get_drvdata(pdev);
int counter = 0; int counter = 0;
set_bit(MTIP_DD_FLAG_REMOVE_PENDING_BIT, &dd->dd_flag);
if (mtip_check_surprise_removal(pdev)) { if (mtip_check_surprise_removal(pdev)) {
while (atomic_read(&dd->drv_cleanup_done) == false) { while (!test_bit(MTIP_DD_FLAG_CLEANUP_BIT, &dd->dd_flag)) {
counter++; counter++;
msleep(20); msleep(20);
if (counter == 10) { if (counter == 10) {
@ -3490,7 +3601,7 @@ static int mtip_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
return -EFAULT; return -EFAULT;
} }
atomic_set(&dd->resumeflag, true); set_bit(MTIP_DD_FLAG_RESUME_BIT, &dd->dd_flag);
/* Disable ports & interrupts then send standby immediate */ /* Disable ports & interrupts then send standby immediate */
rv = mtip_block_suspend(dd); rv = mtip_block_suspend(dd);
@ -3556,7 +3667,7 @@ static int mtip_pci_resume(struct pci_dev *pdev)
dev_err(&pdev->dev, "Unable to resume\n"); dev_err(&pdev->dev, "Unable to resume\n");
err: err:
atomic_set(&dd->resumeflag, false); clear_bit(MTIP_DD_FLAG_RESUME_BIT, &dd->dd_flag);
return rv; return rv;
} }

View File

@ -121,6 +121,12 @@
#define MTIP_FLAG_REBUILD_BIT 5 #define MTIP_FLAG_REBUILD_BIT 5
#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8 #define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8
/* below are bit numbers in 'dd_flag' defined in driver_data */
#define MTIP_DD_FLAG_REMOVE_PENDING_BIT 1
#define MTIP_DD_FLAG_RESUME_BIT 2
#define MTIP_DD_FLAG_CLEANUP_BIT 3
#define MTIP_DD_FLAG_INIT_DONE_BIT 4
/* Register Frame Information Structure (FIS), host to device. */ /* Register Frame Information Structure (FIS), host to device. */
struct host_to_dev_fis { struct host_to_dev_fis {
/* /*
@ -404,13 +410,9 @@ struct driver_data {
unsigned slot_groups; /* number of slot groups the product supports */ unsigned slot_groups; /* number of slot groups the product supports */
atomic_t drv_cleanup_done; /* Atomic variable for SRSI */
unsigned long index; /* Index to determine the disk name */ unsigned long index; /* Index to determine the disk name */
unsigned int ftlrebuildflag; /* FTL rebuild flag */ unsigned long dd_flag; /* NOTE: use atomic bit operations on this */
atomic_t resumeflag; /* Atomic variable to track suspend/resume */
struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
}; };