Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: [SCSI] sd: udev accessing an uninitialized scsi_disk field results in a crash [SCSI] st: A MTIOCTOP/MTWEOF within the early warning will cause the file number to be incorrect [SCSI] qla4xxx: bug fixes [SCSI] Fix scsi_add_device() for async scanning
This commit is contained in:
commit
ce35a81a71
10 changed files with 100 additions and 70 deletions
|
@ -418,7 +418,6 @@ struct scsi_qla_host {
|
||||||
* concurrently.
|
* concurrently.
|
||||||
*/
|
*/
|
||||||
struct mutex mbox_sem;
|
struct mutex mbox_sem;
|
||||||
wait_queue_head_t mailbox_wait_queue;
|
|
||||||
|
|
||||||
/* temporary mailbox status registers */
|
/* temporary mailbox status registers */
|
||||||
volatile uint8_t mbox_status_count;
|
volatile uint8_t mbox_status_count;
|
||||||
|
|
|
@ -76,4 +76,5 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
|
||||||
extern int ql4xextended_error_logging;
|
extern int ql4xextended_error_logging;
|
||||||
extern int ql4xdiscoverywait;
|
extern int ql4xdiscoverywait;
|
||||||
extern int ql4xdontresethba;
|
extern int ql4xdontresethba;
|
||||||
|
extern int ql4_mod_unload;
|
||||||
#endif /* _QLA4x_GBL_H */
|
#endif /* _QLA4x_GBL_H */
|
||||||
|
|
|
@ -958,25 +958,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
|
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
|
||||||
{
|
{
|
||||||
#define QL4_LOCK_DRVR_WAIT 300
|
#define QL4_LOCK_DRVR_WAIT 30
|
||||||
#define QL4_LOCK_DRVR_SLEEP 100
|
#define QL4_LOCK_DRVR_SLEEP 1
|
||||||
|
|
||||||
int drvr_wait = QL4_LOCK_DRVR_WAIT;
|
int drvr_wait = QL4_LOCK_DRVR_WAIT;
|
||||||
while (drvr_wait) {
|
while (drvr_wait) {
|
||||||
if (ql4xxx_lock_drvr(a) == 0) {
|
if (ql4xxx_lock_drvr(ha) == 0) {
|
||||||
msleep(QL4_LOCK_DRVR_SLEEP);
|
ssleep(QL4_LOCK_DRVR_SLEEP);
|
||||||
if (drvr_wait) {
|
if (drvr_wait) {
|
||||||
DEBUG2(printk("scsi%ld: %s: Waiting for "
|
DEBUG2(printk("scsi%ld: %s: Waiting for "
|
||||||
"Global Init Semaphore...n",
|
"Global Init Semaphore(%d)...n",
|
||||||
a->host_no,
|
ha->host_no,
|
||||||
__func__));
|
__func__, drvr_wait));
|
||||||
}
|
}
|
||||||
drvr_wait -= QL4_LOCK_DRVR_SLEEP;
|
drvr_wait -= QL4_LOCK_DRVR_SLEEP;
|
||||||
} else {
|
} else {
|
||||||
DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
|
DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
|
||||||
"acquired.n", a->host_no, __func__));
|
"acquired.n", ha->host_no, __func__));
|
||||||
return QLA_SUCCESS;
|
return QLA_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -433,7 +433,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
||||||
readl(&ha->reg->mailbox[i]);
|
readl(&ha->reg->mailbox[i]);
|
||||||
|
|
||||||
set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
|
set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
|
||||||
wake_up(&ha->mailbox_wait_queue);
|
|
||||||
}
|
}
|
||||||
} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
|
} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
|
||||||
/* Immediately process the AENs that don't require much work.
|
/* Immediately process the AENs that don't require much work.
|
||||||
|
@ -686,7 +685,8 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
|
||||||
&ha->reg->ctrl_status);
|
&ha->reg->ctrl_status);
|
||||||
readl(&ha->reg->ctrl_status);
|
readl(&ha->reg->ctrl_status);
|
||||||
|
|
||||||
set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
|
if (!ql4_mod_unload)
|
||||||
|
set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if (intr_status & INTR_PENDING) {
|
} else if (intr_status & INTR_PENDING) {
|
||||||
|
|
|
@ -29,18 +29,30 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||||
u_long wait_count;
|
u_long wait_count;
|
||||||
uint32_t intr_status;
|
uint32_t intr_status;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
|
||||||
|
|
||||||
mutex_lock(&ha->mbox_sem);
|
|
||||||
|
|
||||||
/* Mailbox code active */
|
|
||||||
set_bit(AF_MBOX_COMMAND, &ha->flags);
|
|
||||||
|
|
||||||
/* Make sure that pointers are valid */
|
/* Make sure that pointers are valid */
|
||||||
if (!mbx_cmd || !mbx_sts) {
|
if (!mbx_cmd || !mbx_sts) {
|
||||||
DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
|
DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
|
||||||
"pointer\n", ha->host_no, __func__));
|
"pointer\n", ha->host_no, __func__));
|
||||||
goto mbox_exit;
|
return status;
|
||||||
|
}
|
||||||
|
/* Mailbox code active */
|
||||||
|
wait_count = MBOX_TOV * 100;
|
||||||
|
|
||||||
|
while (wait_count--) {
|
||||||
|
mutex_lock(&ha->mbox_sem);
|
||||||
|
if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
|
||||||
|
set_bit(AF_MBOX_COMMAND, &ha->flags);
|
||||||
|
mutex_unlock(&ha->mbox_sem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mutex_unlock(&ha->mbox_sem);
|
||||||
|
if (!wait_count) {
|
||||||
|
DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
|
||||||
|
ha->host_no, __func__));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
msleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To prevent overwriting mailbox registers for a command that has
|
/* To prevent overwriting mailbox registers for a command that has
|
||||||
|
@ -73,8 +85,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
/* Wait for completion */
|
/* Wait for completion */
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
|
||||||
add_wait_queue(&ha->mailbox_wait_queue, &wait);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we don't want status, don't wait for the mailbox command to
|
* If we don't want status, don't wait for the mailbox command to
|
||||||
|
@ -83,8 +93,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||||
*/
|
*/
|
||||||
if (outCount == 0) {
|
if (outCount == 0) {
|
||||||
status = QLA_SUCCESS;
|
status = QLA_SUCCESS;
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
remove_wait_queue(&ha->mailbox_wait_queue, &wait);
|
|
||||||
goto mbox_exit;
|
goto mbox_exit;
|
||||||
}
|
}
|
||||||
/* Wait for command to complete */
|
/* Wait for command to complete */
|
||||||
|
@ -108,8 +116,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
msleep(10);
|
msleep(10);
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
remove_wait_queue(&ha->mailbox_wait_queue, &wait);
|
|
||||||
|
|
||||||
/* Check for mailbox timeout. */
|
/* Check for mailbox timeout. */
|
||||||
if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
|
if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
|
||||||
|
@ -155,9 +161,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
mbox_exit:
|
mbox_exit:
|
||||||
|
mutex_lock(&ha->mbox_sem);
|
||||||
clear_bit(AF_MBOX_COMMAND, &ha->flags);
|
clear_bit(AF_MBOX_COMMAND, &ha->flags);
|
||||||
clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
|
|
||||||
mutex_unlock(&ha->mbox_sem);
|
mutex_unlock(&ha->mbox_sem);
|
||||||
|
clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
|
||||||
"Option to enable extended error logging, "
|
"Option to enable extended error logging, "
|
||||||
"Default is 0 - no logging, 1 - debug logging");
|
"Default is 0 - no logging, 1 - debug logging");
|
||||||
|
|
||||||
|
int ql4_mod_unload = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SCSI host template entry points
|
* SCSI host template entry points
|
||||||
*/
|
*/
|
||||||
|
@ -422,6 +424,9 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
|
||||||
goto qc_host_busy;
|
goto qc_host_busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
|
||||||
|
goto qc_host_busy;
|
||||||
|
|
||||||
spin_unlock_irq(ha->host->host_lock);
|
spin_unlock_irq(ha->host->host_lock);
|
||||||
|
|
||||||
srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
|
srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
|
||||||
|
@ -707,16 +712,12 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
|
||||||
* qla4xxx_soft_reset - performs soft reset.
|
|
||||||
* @ha: Pointer to host adapter structure.
|
|
||||||
**/
|
|
||||||
int qla4xxx_soft_reset(struct scsi_qla_host *ha)
|
|
||||||
{
|
{
|
||||||
uint32_t max_wait_time;
|
|
||||||
unsigned long flags = 0;
|
|
||||||
int status = QLA_ERROR;
|
|
||||||
uint32_t ctrl_status;
|
uint32_t ctrl_status;
|
||||||
|
unsigned long flags = 0;
|
||||||
|
|
||||||
|
DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
|
||||||
|
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
|
@ -733,6 +734,20 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha)
|
||||||
readl(&ha->reg->ctrl_status);
|
readl(&ha->reg->ctrl_status);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla4xxx_soft_reset - performs soft reset.
|
||||||
|
* @ha: Pointer to host adapter structure.
|
||||||
|
**/
|
||||||
|
int qla4xxx_soft_reset(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
uint32_t max_wait_time;
|
||||||
|
unsigned long flags = 0;
|
||||||
|
int status = QLA_ERROR;
|
||||||
|
uint32_t ctrl_status;
|
||||||
|
|
||||||
|
qla4xxx_hw_reset(ha);
|
||||||
|
|
||||||
/* Wait until the Network Reset Intr bit is cleared */
|
/* Wait until the Network Reset Intr bit is cleared */
|
||||||
max_wait_time = RESET_INTR_TOV;
|
max_wait_time = RESET_INTR_TOV;
|
||||||
|
@ -966,10 +981,12 @@ static void qla4xxx_do_dpc(struct work_struct *work)
|
||||||
struct scsi_qla_host *ha =
|
struct scsi_qla_host *ha =
|
||||||
container_of(work, struct scsi_qla_host, dpc_work);
|
container_of(work, struct scsi_qla_host, dpc_work);
|
||||||
struct ddb_entry *ddb_entry, *dtemp;
|
struct ddb_entry *ddb_entry, *dtemp;
|
||||||
|
int status = QLA_ERROR;
|
||||||
|
|
||||||
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
|
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
|
||||||
"flags = 0x%08lx, dpc_flags = 0x%08lx\n",
|
"flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n",
|
||||||
ha->host_no, __func__, ha->flags, ha->dpc_flags));
|
ha->host_no, __func__, ha->flags, ha->dpc_flags,
|
||||||
|
readw(&ha->reg->ctrl_status)));
|
||||||
|
|
||||||
/* Initialization not yet finished. Don't do anything yet. */
|
/* Initialization not yet finished. Don't do anything yet. */
|
||||||
if (!test_bit(AF_INIT_DONE, &ha->flags))
|
if (!test_bit(AF_INIT_DONE, &ha->flags))
|
||||||
|
@ -983,31 +1000,28 @@ static void qla4xxx_do_dpc(struct work_struct *work)
|
||||||
test_bit(DPC_RESET_HA, &ha->dpc_flags))
|
test_bit(DPC_RESET_HA, &ha->dpc_flags))
|
||||||
qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
|
qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
|
||||||
|
|
||||||
if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
|
if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
|
||||||
uint8_t wait_time = RESET_INTR_TOV;
|
uint8_t wait_time = RESET_INTR_TOV;
|
||||||
unsigned long flags = 0;
|
|
||||||
|
|
||||||
qla4xxx_flush_active_srbs(ha);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
||||||
while ((readw(&ha->reg->ctrl_status) &
|
while ((readw(&ha->reg->ctrl_status) &
|
||||||
(CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
|
(CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
|
||||||
if (--wait_time == 0)
|
if (--wait_time == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock,
|
|
||||||
flags);
|
|
||||||
|
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
|
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
||||||
|
|
||||||
if (wait_time == 0)
|
if (wait_time == 0)
|
||||||
DEBUG2(printk("scsi%ld: %s: SR|FSR "
|
DEBUG2(printk("scsi%ld: %s: SR|FSR "
|
||||||
"bit not cleared-- resetting\n",
|
"bit not cleared-- resetting\n",
|
||||||
ha->host_no, __func__));
|
ha->host_no, __func__));
|
||||||
|
qla4xxx_flush_active_srbs(ha);
|
||||||
|
if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
|
||||||
|
qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
|
||||||
|
status = qla4xxx_initialize_adapter(ha,
|
||||||
|
PRESERVE_DDB_LIST);
|
||||||
|
}
|
||||||
|
clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
|
||||||
|
if (status == QLA_SUCCESS)
|
||||||
|
qla4xxx_enable_intrs(ha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,7 +1076,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
|
||||||
|
|
||||||
/* Issue Soft Reset to put firmware in unknown state */
|
/* Issue Soft Reset to put firmware in unknown state */
|
||||||
if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
|
if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
|
||||||
qla4xxx_soft_reset(ha);
|
qla4xxx_hw_reset(ha);
|
||||||
|
|
||||||
/* Remove timer thread, if present */
|
/* Remove timer thread, if present */
|
||||||
if (ha->timer_active)
|
if (ha->timer_active)
|
||||||
|
@ -1198,7 +1212,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
||||||
INIT_LIST_HEAD(&ha->free_srb_q);
|
INIT_LIST_HEAD(&ha->free_srb_q);
|
||||||
|
|
||||||
mutex_init(&ha->mbox_sem);
|
mutex_init(&ha->mbox_sem);
|
||||||
init_waitqueue_head(&ha->mailbox_wait_queue);
|
|
||||||
|
|
||||||
spin_lock_init(&ha->hardware_lock);
|
spin_lock_init(&ha->hardware_lock);
|
||||||
|
|
||||||
|
@ -1665,6 +1678,7 @@ static int __init qla4xxx_module_init(void)
|
||||||
|
|
||||||
static void __exit qla4xxx_module_exit(void)
|
static void __exit qla4xxx_module_exit(void)
|
||||||
{
|
{
|
||||||
|
ql4_mod_unload = 1;
|
||||||
pci_unregister_driver(&qla4xxx_pci_driver);
|
pci_unregister_driver(&qla4xxx_pci_driver);
|
||||||
iscsi_unregister_transport(&qla4xxx_iscsi_transport);
|
iscsi_unregister_transport(&qla4xxx_iscsi_transport);
|
||||||
kmem_cache_destroy(srb_cachep);
|
kmem_cache_destroy(srb_cachep);
|
||||||
|
|
|
@ -5,4 +5,4 @@
|
||||||
* See LICENSE.qla4xxx for copyright and licensing details.
|
* See LICENSE.qla4xxx for copyright and licensing details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define QLA4XXX_DRIVER_VERSION "5.00.07-k"
|
#define QLA4XXX_DRIVER_VERSION "5.00.07-k1"
|
||||||
|
|
|
@ -1453,6 +1453,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
|
||||||
struct device *parent = &shost->shost_gendev;
|
struct device *parent = &shost->shost_gendev;
|
||||||
struct scsi_target *starget;
|
struct scsi_target *starget;
|
||||||
|
|
||||||
|
if (strncmp(scsi_scan_type, "none", 4) == 0)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
if (!shost->async_scan)
|
||||||
|
scsi_complete_async_scans();
|
||||||
|
|
||||||
starget = scsi_alloc_target(parent, channel, id);
|
starget = scsi_alloc_target(parent, channel, id);
|
||||||
if (!starget)
|
if (!starget)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
|
@ -1647,16 +1647,6 @@ static int sd_probe(struct device *dev)
|
||||||
if (error)
|
if (error)
|
||||||
goto out_put;
|
goto out_put;
|
||||||
|
|
||||||
class_device_initialize(&sdkp->cdev);
|
|
||||||
sdkp->cdev.dev = &sdp->sdev_gendev;
|
|
||||||
sdkp->cdev.class = &sd_disk_class;
|
|
||||||
strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
|
|
||||||
|
|
||||||
if (class_device_add(&sdkp->cdev))
|
|
||||||
goto out_put;
|
|
||||||
|
|
||||||
get_device(&sdp->sdev_gendev);
|
|
||||||
|
|
||||||
sdkp->device = sdp;
|
sdkp->device = sdp;
|
||||||
sdkp->driver = &sd_template;
|
sdkp->driver = &sd_template;
|
||||||
sdkp->disk = gd;
|
sdkp->disk = gd;
|
||||||
|
@ -1670,6 +1660,16 @@ static int sd_probe(struct device *dev)
|
||||||
sdp->timeout = SD_MOD_TIMEOUT;
|
sdp->timeout = SD_MOD_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_device_initialize(&sdkp->cdev);
|
||||||
|
sdkp->cdev.dev = &sdp->sdev_gendev;
|
||||||
|
sdkp->cdev.class = &sd_disk_class;
|
||||||
|
strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
|
||||||
|
|
||||||
|
if (class_device_add(&sdkp->cdev))
|
||||||
|
goto out_put;
|
||||||
|
|
||||||
|
get_device(&sdp->sdev_gendev);
|
||||||
|
|
||||||
gd->major = sd_major((index & 0xf0) >> 4);
|
gd->major = sd_major((index & 0xf0) >> 4);
|
||||||
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
|
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
|
||||||
gd->minors = 16;
|
gd->minors = 16;
|
||||||
|
|
|
@ -2816,15 +2816,18 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
|
||||||
|
|
||||||
if (cmd_in == MTWEOF &&
|
if (cmd_in == MTWEOF &&
|
||||||
cmdstatp->have_sense &&
|
cmdstatp->have_sense &&
|
||||||
(cmdstatp->flags & SENSE_EOM) &&
|
(cmdstatp->flags & SENSE_EOM)) {
|
||||||
(cmdstatp->sense_hdr.sense_key == NO_SENSE ||
|
if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
|
||||||
cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
|
cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
|
||||||
undone == 0) {
|
ioctl_result = 0; /* EOF(s) written successfully at EOM */
|
||||||
ioctl_result = 0; /* EOF written successfully at EOM */
|
STps->eof = ST_NOEOF;
|
||||||
if (fileno >= 0)
|
} else { /* Writing EOF(s) failed */
|
||||||
fileno++;
|
if (fileno >= 0)
|
||||||
|
fileno -= undone;
|
||||||
|
if (undone < arg)
|
||||||
|
STps->eof = ST_NOEOF;
|
||||||
|
}
|
||||||
STps->drv_file = fileno;
|
STps->drv_file = fileno;
|
||||||
STps->eof = ST_NOEOF;
|
|
||||||
} else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
|
} else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
|
||||||
if (fileno >= 0)
|
if (fileno >= 0)
|
||||||
STps->drv_file = fileno - undone;
|
STps->drv_file = fileno - undone;
|
||||||
|
|
Loading…
Reference in a new issue