mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-29 00:04:55 +00:00
[PATCH] libata-hp: implement warmplug
Implement warmplug. User-initiated unplug can be detected by hostt->slave_destroy() and plug by transportt->user_scan(). This patch only implements the two callbacks. The next function will hook them. Signed-off-by: Tejun Heo <htejun@gmail.com>
This commit is contained in:
parent
580b210232
commit
83c47bcb3c
3 changed files with 91 additions and 0 deletions
|
@ -5942,6 +5942,7 @@ EXPORT_SYMBOL_GPL(ata_port_queue_task);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
|
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
|
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
|
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
|
||||||
|
EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
|
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_release);
|
EXPORT_SYMBOL_GPL(ata_scsi_release);
|
||||||
EXPORT_SYMBOL_GPL(ata_host_intr);
|
EXPORT_SYMBOL_GPL(ata_host_intr);
|
||||||
|
|
|
@ -57,6 +57,8 @@ static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
|
||||||
const struct scsi_device *scsidev);
|
const struct scsi_device *scsidev);
|
||||||
static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
|
static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
|
||||||
const struct scsi_device *scsidev);
|
const struct scsi_device *scsidev);
|
||||||
|
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
|
||||||
|
unsigned int id, unsigned int lun);
|
||||||
|
|
||||||
|
|
||||||
#define RW_RECOVERY_MPAGE 0x1
|
#define RW_RECOVERY_MPAGE 0x1
|
||||||
|
@ -726,6 +728,40 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
|
||||||
return 0; /* scsi layer doesn't check return value, sigh */
|
return 0; /* scsi layer doesn't check return value, sigh */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_scsi_slave_destroy - SCSI device is about to be destroyed
|
||||||
|
* @sdev: SCSI device to be destroyed
|
||||||
|
*
|
||||||
|
* @sdev is about to be destroyed for hot/warm unplugging. If
|
||||||
|
* this unplugging was initiated by libata as indicated by NULL
|
||||||
|
* dev->sdev, this function doesn't have to do anything.
|
||||||
|
* Otherwise, SCSI layer initiated warm-unplug is in progress.
|
||||||
|
* Clear dev->sdev, schedule the device for ATA detach and invoke
|
||||||
|
* EH.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Defined by SCSI layer. We don't really care.
|
||||||
|
*/
|
||||||
|
void ata_scsi_slave_destroy(struct scsi_device *sdev)
|
||||||
|
{
|
||||||
|
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||||
|
unsigned long flags;
|
||||||
|
struct ata_device *dev;
|
||||||
|
|
||||||
|
if (!ap->ops->error_handler)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||||
|
dev = __ata_scsi_find_dev(ap, sdev);
|
||||||
|
if (dev && dev->sdev) {
|
||||||
|
/* SCSI device already in CANCEL state, no need to offline it */
|
||||||
|
dev->sdev = NULL;
|
||||||
|
dev->flags |= ATA_DFLAG_DETACH;
|
||||||
|
ata_port_schedule_eh(ap);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_scsi_change_queue_depth - SCSI callback for queue depth config
|
* ata_scsi_change_queue_depth - SCSI callback for queue depth config
|
||||||
* @sdev: SCSI device to configure queue depth for
|
* @sdev: SCSI device to configure queue depth for
|
||||||
|
@ -2902,3 +2938,56 @@ void ata_scsi_hotplug(void *data)
|
||||||
|
|
||||||
DPRINTK("EXIT\n");
|
DPRINTK("EXIT\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_scsi_user_scan - indication for user-initiated bus scan
|
||||||
|
* @shost: SCSI host to scan
|
||||||
|
* @channel: Channel to scan
|
||||||
|
* @id: ID to scan
|
||||||
|
* @lun: LUN to scan
|
||||||
|
*
|
||||||
|
* This function is called when user explicitly requests bus
|
||||||
|
* scan. Set probe pending flag and invoke EH.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* SCSI layer (we don't care)
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Zero.
|
||||||
|
*/
|
||||||
|
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
|
||||||
|
unsigned int id, unsigned int lun)
|
||||||
|
{
|
||||||
|
struct ata_port *ap = ata_shost_to_port(shost);
|
||||||
|
unsigned long flags;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!ap->ops->error_handler)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if ((channel != SCAN_WILD_CARD && channel != 0) ||
|
||||||
|
(lun != SCAN_WILD_CARD && lun != 0))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ap->host_set->lock, flags);
|
||||||
|
|
||||||
|
if (id == SCAN_WILD_CARD) {
|
||||||
|
ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
|
||||||
|
ap->eh_info.action |= ATA_EH_SOFTRESET;
|
||||||
|
} else {
|
||||||
|
struct ata_device *dev = ata_find_dev(ap, id);
|
||||||
|
|
||||||
|
if (dev) {
|
||||||
|
ap->eh_info.probe_mask |= 1 << dev->devno;
|
||||||
|
ap->eh_info.action |= ATA_EH_SOFTRESET;
|
||||||
|
} else
|
||||||
|
rc = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 0)
|
||||||
|
ata_port_schedule_eh(ap);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ap->host_set->lock, flags);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
|
@ -734,6 +734,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
|
||||||
struct block_device *bdev,
|
struct block_device *bdev,
|
||||||
sector_t capacity, int geom[]);
|
sector_t capacity, int geom[]);
|
||||||
extern int ata_scsi_slave_config(struct scsi_device *sdev);
|
extern int ata_scsi_slave_config(struct scsi_device *sdev);
|
||||||
|
extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
|
||||||
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
||||||
int queue_depth);
|
int queue_depth);
|
||||||
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
||||||
|
|
Loading…
Reference in a new issue