Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: libata: fix kernel-doc parameter warning sata_mv: remove iounmap in mv_platform_remove and use devm_iomap ata: fix sparse warning in libata.h libata: implement libata.force module parameter sata_mv: use hpriv->base instead of the host->iomap sata_mv: Define module alias for platform device ata: fix sparse warnings in pata_legacy.c
This commit is contained in:
commit
7be5cb1461
|
@ -950,6 +950,41 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
when set.
|
when set.
|
||||||
Format: <int>
|
Format: <int>
|
||||||
|
|
||||||
|
libata.force= [LIBATA] Force configurations. The format is comma
|
||||||
|
separated list of "[ID:]VAL" where ID is
|
||||||
|
PORT[:DEVICE]. PORT and DEVICE are decimal numbers
|
||||||
|
matching port, link or device. Basically, it matches
|
||||||
|
the ATA ID string printed on console by libata. If
|
||||||
|
the whole ID part is omitted, the last PORT and DEVICE
|
||||||
|
values are used. If ID hasn't been specified yet, the
|
||||||
|
configuration applies to all ports, links and devices.
|
||||||
|
|
||||||
|
If only DEVICE is omitted, the parameter applies to
|
||||||
|
the port and all links and devices behind it. DEVICE
|
||||||
|
number of 0 either selects the first device or the
|
||||||
|
first fan-out link behind PMP device. It does not
|
||||||
|
select the host link. DEVICE number of 15 selects the
|
||||||
|
host link and device attached to it.
|
||||||
|
|
||||||
|
The VAL specifies the configuration to force. As long
|
||||||
|
as there's no ambiguity shortcut notation is allowed.
|
||||||
|
For example, both 1.5 and 1.5G would work for 1.5Gbps.
|
||||||
|
The following configurations can be forced.
|
||||||
|
|
||||||
|
* Cable type: 40c, 80c, short40c, unk, ign or sata.
|
||||||
|
Any ID with matching PORT is used.
|
||||||
|
|
||||||
|
* SATA link speed limit: 1.5Gbps or 3.0Gbps.
|
||||||
|
|
||||||
|
* Transfer mode: pio[0-7], mwdma[0-4] and udma[0-7].
|
||||||
|
udma[/][16,25,33,44,66,100,133] notation is also
|
||||||
|
allowed.
|
||||||
|
|
||||||
|
* [no]ncq: Turn on or off NCQ.
|
||||||
|
|
||||||
|
If there are multiple matching configurations changing
|
||||||
|
the same attribute, the last one is used.
|
||||||
|
|
||||||
load_ramdisk= [RAM] List of ramdisks to load from floppy
|
load_ramdisk= [RAM] List of ramdisks to load from floppy
|
||||||
See Documentation/ramdisk.txt.
|
See Documentation/ramdisk.txt.
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,28 @@ static struct workqueue_struct *ata_wq;
|
||||||
|
|
||||||
struct workqueue_struct *ata_aux_wq;
|
struct workqueue_struct *ata_aux_wq;
|
||||||
|
|
||||||
|
struct ata_force_param {
|
||||||
|
const char *name;
|
||||||
|
unsigned int cbl;
|
||||||
|
int spd_limit;
|
||||||
|
unsigned long xfer_mask;
|
||||||
|
unsigned int horkage_on;
|
||||||
|
unsigned int horkage_off;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ata_force_ent {
|
||||||
|
int port;
|
||||||
|
int device;
|
||||||
|
struct ata_force_param param;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ata_force_ent *ata_force_tbl;
|
||||||
|
static int ata_force_tbl_size;
|
||||||
|
|
||||||
|
static char ata_force_param_buf[PAGE_SIZE] __initdata;
|
||||||
|
module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0444);
|
||||||
|
MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
|
||||||
|
|
||||||
int atapi_enabled = 1;
|
int atapi_enabled = 1;
|
||||||
module_param(atapi_enabled, int, 0444);
|
module_param(atapi_enabled, int, 0444);
|
||||||
MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
|
MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
|
||||||
|
@ -129,6 +151,179 @@ MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(DRV_VERSION);
|
MODULE_VERSION(DRV_VERSION);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_force_cbl - force cable type according to libata.force
|
||||||
|
* @link: ATA link of interest
|
||||||
|
*
|
||||||
|
* Force cable type according to libata.force and whine about it.
|
||||||
|
* The last entry which has matching port number is used, so it
|
||||||
|
* can be specified as part of device force parameters. For
|
||||||
|
* example, both "a:40c,1.00:udma4" and "1.00:40c,udma4" have the
|
||||||
|
* same effect.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* EH context.
|
||||||
|
*/
|
||||||
|
void ata_force_cbl(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = ata_force_tbl_size - 1; i >= 0; i--) {
|
||||||
|
const struct ata_force_ent *fe = &ata_force_tbl[i];
|
||||||
|
|
||||||
|
if (fe->port != -1 && fe->port != ap->print_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fe->param.cbl == ATA_CBL_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ap->cbl = fe->param.cbl;
|
||||||
|
ata_port_printk(ap, KERN_NOTICE,
|
||||||
|
"FORCE: cable set to %s\n", fe->param.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_force_spd_limit - force SATA spd limit according to libata.force
|
||||||
|
* @link: ATA link of interest
|
||||||
|
*
|
||||||
|
* Force SATA spd limit according to libata.force and whine about
|
||||||
|
* it. When only the port part is specified (e.g. 1:), the limit
|
||||||
|
* applies to all links connected to both the host link and all
|
||||||
|
* fan-out ports connected via PMP. If the device part is
|
||||||
|
* specified as 0 (e.g. 1.00:), it specifies the first fan-out
|
||||||
|
* link not the host link. Device number 15 always points to the
|
||||||
|
* host link whether PMP is attached or not.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* EH context.
|
||||||
|
*/
|
||||||
|
static void ata_force_spd_limit(struct ata_link *link)
|
||||||
|
{
|
||||||
|
int linkno, i;
|
||||||
|
|
||||||
|
if (ata_is_host_link(link))
|
||||||
|
linkno = 15;
|
||||||
|
else
|
||||||
|
linkno = link->pmp;
|
||||||
|
|
||||||
|
for (i = ata_force_tbl_size - 1; i >= 0; i--) {
|
||||||
|
const struct ata_force_ent *fe = &ata_force_tbl[i];
|
||||||
|
|
||||||
|
if (fe->port != -1 && fe->port != link->ap->print_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fe->device != -1 && fe->device != linkno)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!fe->param.spd_limit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1;
|
||||||
|
ata_link_printk(link, KERN_NOTICE,
|
||||||
|
"FORCE: PHY spd limit set to %s\n", fe->param.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_force_xfermask - force xfermask according to libata.force
|
||||||
|
* @dev: ATA device of interest
|
||||||
|
*
|
||||||
|
* Force xfer_mask according to libata.force and whine about it.
|
||||||
|
* For consistency with link selection, device number 15 selects
|
||||||
|
* the first device connected to the host link.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* EH context.
|
||||||
|
*/
|
||||||
|
static void ata_force_xfermask(struct ata_device *dev)
|
||||||
|
{
|
||||||
|
int devno = dev->link->pmp + dev->devno;
|
||||||
|
int alt_devno = devno;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* allow n.15 for the first device attached to host port */
|
||||||
|
if (ata_is_host_link(dev->link) && devno == 0)
|
||||||
|
alt_devno = 15;
|
||||||
|
|
||||||
|
for (i = ata_force_tbl_size - 1; i >= 0; i--) {
|
||||||
|
const struct ata_force_ent *fe = &ata_force_tbl[i];
|
||||||
|
unsigned long pio_mask, mwdma_mask, udma_mask;
|
||||||
|
|
||||||
|
if (fe->port != -1 && fe->port != dev->link->ap->print_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fe->device != -1 && fe->device != devno &&
|
||||||
|
fe->device != alt_devno)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!fe->param.xfer_mask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ata_unpack_xfermask(fe->param.xfer_mask,
|
||||||
|
&pio_mask, &mwdma_mask, &udma_mask);
|
||||||
|
if (udma_mask)
|
||||||
|
dev->udma_mask = udma_mask;
|
||||||
|
else if (mwdma_mask) {
|
||||||
|
dev->udma_mask = 0;
|
||||||
|
dev->mwdma_mask = mwdma_mask;
|
||||||
|
} else {
|
||||||
|
dev->udma_mask = 0;
|
||||||
|
dev->mwdma_mask = 0;
|
||||||
|
dev->pio_mask = pio_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
ata_dev_printk(dev, KERN_NOTICE,
|
||||||
|
"FORCE: xfer_mask set to %s\n", fe->param.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_force_horkage - force horkage according to libata.force
|
||||||
|
* @dev: ATA device of interest
|
||||||
|
*
|
||||||
|
* Force horkage according to libata.force and whine about it.
|
||||||
|
* For consistency with link selection, device number 15 selects
|
||||||
|
* the first device connected to the host link.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* EH context.
|
||||||
|
*/
|
||||||
|
static void ata_force_horkage(struct ata_device *dev)
|
||||||
|
{
|
||||||
|
int devno = dev->link->pmp + dev->devno;
|
||||||
|
int alt_devno = devno;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* allow n.15 for the first device attached to host port */
|
||||||
|
if (ata_is_host_link(dev->link) && devno == 0)
|
||||||
|
alt_devno = 15;
|
||||||
|
|
||||||
|
for (i = 0; i < ata_force_tbl_size; i++) {
|
||||||
|
const struct ata_force_ent *fe = &ata_force_tbl[i];
|
||||||
|
|
||||||
|
if (fe->port != -1 && fe->port != dev->link->ap->print_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fe->device != -1 && fe->device != devno &&
|
||||||
|
fe->device != alt_devno)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(~dev->horkage & fe->param.horkage_on) &&
|
||||||
|
!(dev->horkage & fe->param.horkage_off))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dev->horkage |= fe->param.horkage_on;
|
||||||
|
dev->horkage &= ~fe->param.horkage_off;
|
||||||
|
|
||||||
|
ata_dev_printk(dev, KERN_NOTICE,
|
||||||
|
"FORCE: horkage modified (%s)\n", fe->param.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
|
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
|
||||||
* @tf: Taskfile to convert
|
* @tf: Taskfile to convert
|
||||||
|
@ -2067,6 +2262,7 @@ int ata_dev_configure(struct ata_device *dev)
|
||||||
|
|
||||||
/* set horkage */
|
/* set horkage */
|
||||||
dev->horkage |= ata_dev_blacklisted(dev);
|
dev->horkage |= ata_dev_blacklisted(dev);
|
||||||
|
ata_force_horkage(dev);
|
||||||
|
|
||||||
/* let ACPI work its magic */
|
/* let ACPI work its magic */
|
||||||
rc = ata_acpi_on_devcfg(dev);
|
rc = ata_acpi_on_devcfg(dev);
|
||||||
|
@ -3150,6 +3346,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
|
||||||
mode_mask = ATA_DMA_MASK_CFA;
|
mode_mask = ATA_DMA_MASK_CFA;
|
||||||
|
|
||||||
ata_dev_xfermask(dev);
|
ata_dev_xfermask(dev);
|
||||||
|
ata_force_xfermask(dev);
|
||||||
|
|
||||||
pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
|
pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
|
||||||
dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
|
dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
|
||||||
|
@ -6497,7 +6694,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
|
||||||
*/
|
*/
|
||||||
int sata_link_init_spd(struct ata_link *link)
|
int sata_link_init_spd(struct ata_link *link)
|
||||||
{
|
{
|
||||||
u32 scontrol, spd;
|
u32 scontrol;
|
||||||
|
u8 spd;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
|
rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
|
||||||
|
@ -6508,6 +6706,8 @@ int sata_link_init_spd(struct ata_link *link)
|
||||||
if (spd)
|
if (spd)
|
||||||
link->hw_sata_spd_limit &= (1 << spd) - 1;
|
link->hw_sata_spd_limit &= (1 << spd) - 1;
|
||||||
|
|
||||||
|
ata_force_spd_limit(link);
|
||||||
|
|
||||||
link->sata_spd_limit = link->hw_sata_spd_limit;
|
link->sata_spd_limit = link->hw_sata_spd_limit;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -7218,10 +7418,187 @@ int ata_pci_device_resume(struct pci_dev *pdev)
|
||||||
|
|
||||||
#endif /* CONFIG_PCI */
|
#endif /* CONFIG_PCI */
|
||||||
|
|
||||||
|
static int __init ata_parse_force_one(char **cur,
|
||||||
|
struct ata_force_ent *force_ent,
|
||||||
|
const char **reason)
|
||||||
|
{
|
||||||
|
/* FIXME: Currently, there's no way to tag init const data and
|
||||||
|
* using __initdata causes build failure on some versions of
|
||||||
|
* gcc. Once __initdataconst is implemented, add const to the
|
||||||
|
* following structure.
|
||||||
|
*/
|
||||||
|
static struct ata_force_param force_tbl[] __initdata = {
|
||||||
|
{ "40c", .cbl = ATA_CBL_PATA40 },
|
||||||
|
{ "80c", .cbl = ATA_CBL_PATA80 },
|
||||||
|
{ "short40c", .cbl = ATA_CBL_PATA40_SHORT },
|
||||||
|
{ "unk", .cbl = ATA_CBL_PATA_UNK },
|
||||||
|
{ "ign", .cbl = ATA_CBL_PATA_IGN },
|
||||||
|
{ "sata", .cbl = ATA_CBL_SATA },
|
||||||
|
{ "1.5Gbps", .spd_limit = 1 },
|
||||||
|
{ "3.0Gbps", .spd_limit = 2 },
|
||||||
|
{ "noncq", .horkage_on = ATA_HORKAGE_NONCQ },
|
||||||
|
{ "ncq", .horkage_off = ATA_HORKAGE_NONCQ },
|
||||||
|
{ "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) },
|
||||||
|
{ "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) },
|
||||||
|
{ "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) },
|
||||||
|
{ "pio3", .xfer_mask = 1 << (ATA_SHIFT_PIO + 3) },
|
||||||
|
{ "pio4", .xfer_mask = 1 << (ATA_SHIFT_PIO + 4) },
|
||||||
|
{ "pio5", .xfer_mask = 1 << (ATA_SHIFT_PIO + 5) },
|
||||||
|
{ "pio6", .xfer_mask = 1 << (ATA_SHIFT_PIO + 6) },
|
||||||
|
{ "mwdma0", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 0) },
|
||||||
|
{ "mwdma1", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 1) },
|
||||||
|
{ "mwdma2", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 2) },
|
||||||
|
{ "mwdma3", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 3) },
|
||||||
|
{ "mwdma4", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 4) },
|
||||||
|
{ "udma0", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) },
|
||||||
|
{ "udma16", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) },
|
||||||
|
{ "udma/16", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) },
|
||||||
|
{ "udma1", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) },
|
||||||
|
{ "udma25", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) },
|
||||||
|
{ "udma/25", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) },
|
||||||
|
{ "udma2", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) },
|
||||||
|
{ "udma33", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) },
|
||||||
|
{ "udma/33", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) },
|
||||||
|
{ "udma3", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) },
|
||||||
|
{ "udma44", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) },
|
||||||
|
{ "udma/44", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) },
|
||||||
|
{ "udma4", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) },
|
||||||
|
{ "udma66", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) },
|
||||||
|
{ "udma/66", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) },
|
||||||
|
{ "udma5", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) },
|
||||||
|
{ "udma100", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) },
|
||||||
|
{ "udma/100", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) },
|
||||||
|
{ "udma6", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
|
||||||
|
{ "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
|
||||||
|
{ "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
|
||||||
|
{ "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) },
|
||||||
|
};
|
||||||
|
char *start = *cur, *p = *cur;
|
||||||
|
char *id, *val, *endp;
|
||||||
|
const struct ata_force_param *match_fp = NULL;
|
||||||
|
int nr_matches = 0, i;
|
||||||
|
|
||||||
|
/* find where this param ends and update *cur */
|
||||||
|
while (*p != '\0' && *p != ',')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (*p == '\0')
|
||||||
|
*cur = p;
|
||||||
|
else
|
||||||
|
*cur = p + 1;
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
/* parse */
|
||||||
|
p = strchr(start, ':');
|
||||||
|
if (!p) {
|
||||||
|
val = strstrip(start);
|
||||||
|
goto parse_val;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
id = strstrip(start);
|
||||||
|
val = strstrip(p + 1);
|
||||||
|
|
||||||
|
/* parse id */
|
||||||
|
p = strchr(id, '.');
|
||||||
|
if (p) {
|
||||||
|
*p++ = '\0';
|
||||||
|
force_ent->device = simple_strtoul(p, &endp, 10);
|
||||||
|
if (p == endp || *endp != '\0') {
|
||||||
|
*reason = "invalid device";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
force_ent->port = simple_strtoul(id, &endp, 10);
|
||||||
|
if (p == endp || *endp != '\0') {
|
||||||
|
*reason = "invalid port/link";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_val:
|
||||||
|
/* parse val, allow shortcuts so that both 1.5 and 1.5Gbps work */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(force_tbl); i++) {
|
||||||
|
const struct ata_force_param *fp = &force_tbl[i];
|
||||||
|
|
||||||
|
if (strncasecmp(val, fp->name, strlen(val)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nr_matches++;
|
||||||
|
match_fp = fp;
|
||||||
|
|
||||||
|
if (strcasecmp(val, fp->name) == 0) {
|
||||||
|
nr_matches = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nr_matches) {
|
||||||
|
*reason = "unknown value";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (nr_matches > 1) {
|
||||||
|
*reason = "ambigious value";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
force_ent->param = *match_fp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init ata_parse_force_param(void)
|
||||||
|
{
|
||||||
|
int idx = 0, size = 1;
|
||||||
|
int last_port = -1, last_device = -1;
|
||||||
|
char *p, *cur, *next;
|
||||||
|
|
||||||
|
/* calculate maximum number of params and allocate force_tbl */
|
||||||
|
for (p = ata_force_param_buf; *p; p++)
|
||||||
|
if (*p == ',')
|
||||||
|
size++;
|
||||||
|
|
||||||
|
ata_force_tbl = kzalloc(sizeof(ata_force_tbl[0]) * size, GFP_KERNEL);
|
||||||
|
if (!ata_force_tbl) {
|
||||||
|
printk(KERN_WARNING "ata: failed to extend force table, "
|
||||||
|
"libata.force ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and populate the table */
|
||||||
|
for (cur = ata_force_param_buf; *cur != '\0'; cur = next) {
|
||||||
|
const char *reason = "";
|
||||||
|
struct ata_force_ent te = { .port = -1, .device = -1 };
|
||||||
|
|
||||||
|
next = cur;
|
||||||
|
if (ata_parse_force_one(&next, &te, &reason)) {
|
||||||
|
printk(KERN_WARNING "ata: failed to parse force "
|
||||||
|
"parameter \"%s\" (%s)\n",
|
||||||
|
cur, reason);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (te.port == -1) {
|
||||||
|
te.port = last_port;
|
||||||
|
te.device = last_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
ata_force_tbl[idx++] = te;
|
||||||
|
|
||||||
|
last_port = te.port;
|
||||||
|
last_device = te.device;
|
||||||
|
}
|
||||||
|
|
||||||
|
ata_force_tbl_size = idx;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init ata_init(void)
|
static int __init ata_init(void)
|
||||||
{
|
{
|
||||||
ata_probe_timeout *= HZ;
|
ata_probe_timeout *= HZ;
|
||||||
|
|
||||||
|
ata_parse_force_param();
|
||||||
|
|
||||||
ata_wq = create_workqueue("ata");
|
ata_wq = create_workqueue("ata");
|
||||||
if (!ata_wq)
|
if (!ata_wq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -7238,6 +7615,7 @@ static int __init ata_init(void)
|
||||||
|
|
||||||
static void __exit ata_exit(void)
|
static void __exit ata_exit(void)
|
||||||
{
|
{
|
||||||
|
kfree(ata_force_tbl);
|
||||||
destroy_workqueue(ata_wq);
|
destroy_workqueue(ata_wq);
|
||||||
destroy_workqueue(ata_aux_wq);
|
destroy_workqueue(ata_aux_wq);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2393,9 +2393,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PDIAG- should have been released, ask cable type if post-reset */
|
/* PDIAG- should have been released, ask cable type if post-reset */
|
||||||
if (ata_is_host_link(link) && ap->ops->cable_detect &&
|
if ((ehc->i.flags & ATA_EHI_DID_RESET) && ata_is_host_link(link)) {
|
||||||
(ehc->i.flags & ATA_EHI_DID_RESET))
|
if (ap->ops->cable_detect)
|
||||||
ap->cbl = ap->ops->cable_detect(ap);
|
ap->cbl = ap->ops->cable_detect(ap);
|
||||||
|
ata_force_cbl(ap);
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure new devices forward such that user doesn't see
|
/* Configure new devices forward such that user doesn't see
|
||||||
* device detection messages backwards.
|
* device detection messages backwards.
|
||||||
|
|
|
@ -828,7 +828,7 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atapi_drain_needed - Check whether data transfer may overflow
|
* atapi_drain_needed - Check whether data transfer may overflow
|
||||||
* @request: request to be checked
|
* @rq: request to be checked
|
||||||
*
|
*
|
||||||
* ATAPI commands which transfer variable length data to host
|
* ATAPI commands which transfer variable length data to host
|
||||||
* might overflow due to application error or hardare bug. This
|
* might overflow due to application error or hardare bug. This
|
||||||
|
|
|
@ -61,6 +61,7 @@ extern int atapi_passthru16;
|
||||||
extern int libata_fua;
|
extern int libata_fua;
|
||||||
extern int libata_noacpi;
|
extern int libata_noacpi;
|
||||||
extern int libata_allow_tpm;
|
extern int libata_allow_tpm;
|
||||||
|
extern void ata_force_cbl(struct ata_port *ap);
|
||||||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
|
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
|
||||||
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
||||||
u64 block, u32 n_block, unsigned int tf_flags,
|
u64 block, u32 n_block, unsigned int tf_flags,
|
||||||
|
|
|
@ -774,14 +774,14 @@ static struct ata_port_operations opti82c46x_port_ops = {
|
||||||
static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
{
|
{
|
||||||
struct ata_timing t;
|
struct ata_timing t;
|
||||||
struct legacy_data *qdi = ap->host->private_data;
|
struct legacy_data *ld_qdi = ap->host->private_data;
|
||||||
int active, recovery;
|
int active, recovery;
|
||||||
u8 timing;
|
u8 timing;
|
||||||
|
|
||||||
/* Get the timing data in cycles */
|
/* Get the timing data in cycles */
|
||||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||||
|
|
||||||
if (qdi->fast) {
|
if (ld_qdi->fast) {
|
||||||
active = 8 - FIT(t.active, 1, 8);
|
active = 8 - FIT(t.active, 1, 8);
|
||||||
recovery = 18 - FIT(t.recover, 3, 18);
|
recovery = 18 - FIT(t.recover, 3, 18);
|
||||||
} else {
|
} else {
|
||||||
|
@ -790,9 +790,9 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
}
|
}
|
||||||
timing = (recovery << 4) | active | 0x08;
|
timing = (recovery << 4) | active | 0x08;
|
||||||
|
|
||||||
qdi->clock[adev->devno] = timing;
|
ld_qdi->clock[adev->devno] = timing;
|
||||||
|
|
||||||
outb(timing, qdi->timing);
|
outb(timing, ld_qdi->timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -808,14 +808,14 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
{
|
{
|
||||||
struct ata_timing t;
|
struct ata_timing t;
|
||||||
struct legacy_data *qdi = ap->host->private_data;
|
struct legacy_data *ld_qdi = ap->host->private_data;
|
||||||
int active, recovery;
|
int active, recovery;
|
||||||
u8 timing;
|
u8 timing;
|
||||||
|
|
||||||
/* Get the timing data in cycles */
|
/* Get the timing data in cycles */
|
||||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||||
|
|
||||||
if (qdi->fast) {
|
if (ld_qdi->fast) {
|
||||||
active = 8 - FIT(t.active, 1, 8);
|
active = 8 - FIT(t.active, 1, 8);
|
||||||
recovery = 18 - FIT(t.recover, 3, 18);
|
recovery = 18 - FIT(t.recover, 3, 18);
|
||||||
} else {
|
} else {
|
||||||
|
@ -824,12 +824,12 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
}
|
}
|
||||||
timing = (recovery << 4) | active | 0x08;
|
timing = (recovery << 4) | active | 0x08;
|
||||||
|
|
||||||
qdi->clock[adev->devno] = timing;
|
ld_qdi->clock[adev->devno] = timing;
|
||||||
|
|
||||||
outb(timing, qdi->timing + 2 * ap->port_no);
|
outb(timing, ld_qdi->timing + 2 * ap->port_no);
|
||||||
/* Clear the FIFO */
|
/* Clear the FIFO */
|
||||||
if (adev->class != ATA_DEV_ATA)
|
if (adev->class != ATA_DEV_ATA)
|
||||||
outb(0x5F, qdi->timing + 3);
|
outb(0x5F, ld_qdi->timing + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -845,14 +845,14 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
{
|
{
|
||||||
struct ata_timing t;
|
struct ata_timing t;
|
||||||
struct legacy_data *qdi = ap->host->private_data;
|
struct legacy_data *ld_qdi = ap->host->private_data;
|
||||||
int active, recovery;
|
int active, recovery;
|
||||||
u8 timing;
|
u8 timing;
|
||||||
|
|
||||||
/* Get the timing data in cycles */
|
/* Get the timing data in cycles */
|
||||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||||
|
|
||||||
if (qdi->fast) {
|
if (ld_qdi->fast) {
|
||||||
active = 8 - FIT(t.active, 1, 8);
|
active = 8 - FIT(t.active, 1, 8);
|
||||||
recovery = 18 - FIT(t.recover, 3, 18);
|
recovery = 18 - FIT(t.recover, 3, 18);
|
||||||
} else {
|
} else {
|
||||||
|
@ -860,11 +860,11 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
recovery = 15 - FIT(t.recover, 0, 15);
|
recovery = 15 - FIT(t.recover, 0, 15);
|
||||||
}
|
}
|
||||||
timing = (recovery << 4) | active | 0x08;
|
timing = (recovery << 4) | active | 0x08;
|
||||||
qdi->clock[adev->devno] = timing;
|
ld_qdi->clock[adev->devno] = timing;
|
||||||
outb(timing, qdi->timing + 2 * adev->devno);
|
outb(timing, ld_qdi->timing + 2 * adev->devno);
|
||||||
/* Clear the FIFO */
|
/* Clear the FIFO */
|
||||||
if (adev->class != ATA_DEV_ATA)
|
if (adev->class != ATA_DEV_ATA)
|
||||||
outb(0x5F, qdi->timing + 3);
|
outb(0x5F, ld_qdi->timing + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -879,12 +879,12 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
struct ata_device *adev = qc->dev;
|
struct ata_device *adev = qc->dev;
|
||||||
struct legacy_data *qdi = ap->host->private_data;
|
struct legacy_data *ld_qdi = ap->host->private_data;
|
||||||
|
|
||||||
if (qdi->clock[adev->devno] != qdi->last) {
|
if (ld_qdi->clock[adev->devno] != ld_qdi->last) {
|
||||||
if (adev->pio_mode) {
|
if (adev->pio_mode) {
|
||||||
qdi->last = qdi->clock[adev->devno];
|
ld_qdi->last = ld_qdi->clock[adev->devno];
|
||||||
outb(qdi->clock[adev->devno], qdi->timing +
|
outb(ld_qdi->clock[adev->devno], ld_qdi->timing +
|
||||||
2 * ap->port_no);
|
2 * ap->port_no);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1037,12 +1037,12 @@ static u8 winbond_readcfg(unsigned long port, u8 reg)
|
||||||
static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
{
|
{
|
||||||
struct ata_timing t;
|
struct ata_timing t;
|
||||||
struct legacy_data *winbond = ap->host->private_data;
|
struct legacy_data *ld_winbond = ap->host->private_data;
|
||||||
int active, recovery;
|
int active, recovery;
|
||||||
u8 reg;
|
u8 reg;
|
||||||
int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
|
int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
|
||||||
|
|
||||||
reg = winbond_readcfg(winbond->timing, 0x81);
|
reg = winbond_readcfg(ld_winbond->timing, 0x81);
|
||||||
|
|
||||||
/* Get the timing data in cycles */
|
/* Get the timing data in cycles */
|
||||||
if (reg & 0x40) /* Fast VLB bus, assume 50MHz */
|
if (reg & 0x40) /* Fast VLB bus, assume 50MHz */
|
||||||
|
@ -1053,7 +1053,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
active = (FIT(t.active, 3, 17) - 1) & 0x0F;
|
active = (FIT(t.active, 3, 17) - 1) & 0x0F;
|
||||||
recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
|
recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
|
||||||
timing = (active << 4) | recovery;
|
timing = (active << 4) | recovery;
|
||||||
winbond_writecfg(winbond->timing, timing, reg);
|
winbond_writecfg(ld_winbond->timing, timing, reg);
|
||||||
|
|
||||||
/* Load the setup timing */
|
/* Load the setup timing */
|
||||||
|
|
||||||
|
@ -1063,7 +1063,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||||
if (!ata_pio_need_iordy(adev))
|
if (!ata_pio_need_iordy(adev))
|
||||||
reg |= 0x02; /* IORDY off */
|
reg |= 0x02; /* IORDY off */
|
||||||
reg |= (FIT(t.setup, 0, 3) << 6);
|
reg |= (FIT(t.setup, 0, 3) << 6);
|
||||||
winbond_writecfg(winbond->timing, timing + 1, reg);
|
winbond_writecfg(ld_winbond->timing, timing + 1, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int winbond_port(struct platform_device *dev,
|
static int winbond_port(struct platform_device *dev,
|
||||||
|
|
|
@ -870,7 +870,7 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
|
||||||
struct mv_host_priv *hpriv = ap->host->private_data;
|
struct mv_host_priv *hpriv = ap->host->private_data;
|
||||||
int hard_port = mv_hardport_from_port(ap->port_no);
|
int hard_port = mv_hardport_from_port(ap->port_no);
|
||||||
void __iomem *hc_mmio = mv_hc_base_from_port(
|
void __iomem *hc_mmio = mv_hc_base_from_port(
|
||||||
ap->host->iomap[MV_PRIMARY_BAR], hard_port);
|
mv_host_base(ap->host), hard_port);
|
||||||
u32 hc_irq_cause, ipending;
|
u32 hc_irq_cause, ipending;
|
||||||
|
|
||||||
/* clear EDMA event indicators, if any */
|
/* clear EDMA event indicators, if any */
|
||||||
|
@ -2947,7 +2947,8 @@ static int mv_platform_probe(struct platform_device *pdev)
|
||||||
hpriv->n_ports = n_ports;
|
hpriv->n_ports = n_ports;
|
||||||
|
|
||||||
host->iomap = NULL;
|
host->iomap = NULL;
|
||||||
hpriv->base = ioremap(res->start, res->end - res->start + 1);
|
hpriv->base = devm_ioremap(&pdev->dev, res->start,
|
||||||
|
res->end - res->start + 1);
|
||||||
hpriv->base -= MV_SATAHC0_REG_BASE;
|
hpriv->base -= MV_SATAHC0_REG_BASE;
|
||||||
|
|
||||||
rc = mv_create_dma_pools(hpriv, &pdev->dev);
|
rc = mv_create_dma_pools(hpriv, &pdev->dev);
|
||||||
|
@ -2979,11 +2980,8 @@ static int __devexit mv_platform_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct ata_host *host = dev_get_drvdata(dev);
|
struct ata_host *host = dev_get_drvdata(dev);
|
||||||
struct mv_host_priv *hpriv = host->private_data;
|
|
||||||
void __iomem *base = hpriv->base;
|
|
||||||
|
|
||||||
ata_host_detach(host);
|
ata_host_detach(host);
|
||||||
iounmap(base);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3194,6 +3192,7 @@ MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
|
||||||
MODULE_VERSION(DRV_VERSION);
|
MODULE_VERSION(DRV_VERSION);
|
||||||
|
MODULE_ALIAS("platform:sata_mv");
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
module_param(msi, int, 0444);
|
module_param(msi, int, 0444);
|
||||||
|
|
|
@ -1197,7 +1197,7 @@ static inline struct ata_link *ata_port_next_link(struct ata_link *link)
|
||||||
return ap->pmp_link;
|
return ap->pmp_link;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++link - ap->pmp_link < ap->nr_pmp_links)
|
if (++link < ap->nr_pmp_links + ap->pmp_link)
|
||||||
return link;
|
return link;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue