--- zzzz-none-000/linux-3.10.107/drivers/ata/libata-core.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/ata/libata-core.c 2021-02-04 17:41:59.000000000 +0000 @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + #include "libata.h" #include "libata-transport.h" @@ -569,10 +573,10 @@ fis[14] = 0; fis[15] = tf->ctl; - fis[16] = 0; - fis[17] = 0; - fis[18] = 0; - fis[19] = 0; + fis[16] = tf->auxiliary & 0xff; + fis[17] = (tf->auxiliary >> 8) & 0xff; + fis[18] = (tf->auxiliary >> 16) & 0xff; + fis[19] = (tf->auxiliary >> 24) & 0xff; } /** @@ -724,6 +728,19 @@ return block; } +#ifdef CONFIG_ATA_LEDS +#define LIBATA_BLINK_DELAY 20 /* ms */ +static inline void ata_led_act(struct ata_port *ap) +{ + unsigned long led_delay = LIBATA_BLINK_DELAY; + + if (unlikely(!ap->ledtrig)) + return; + + led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); +} +#endif + /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @tf: Target ATA taskfile @@ -1042,8 +1059,8 @@ * None. * * RETURNS: - * Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, %ATA_DEV_PMP or - * %ATA_DEV_UNKNOWN the event of failure. + * Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, %ATA_DEV_PMP, + * %ATA_DEV_ZAC, or %ATA_DEV_UNKNOWN the event of failure. */ unsigned int ata_dev_classify(const struct ata_taskfile *tf) { @@ -1088,6 +1105,11 @@ return ATA_DEV_SEMB; } + if ((tf->lbam == 0xcd) && (tf->lbah == 0xab)) { + DPRINTK("found ZAC device by sig\n"); + return ATA_DEV_ZAC; + } + DPRINTK("unknown device\n"); return ATA_DEV_UNKNOWN; } @@ -1328,7 +1350,7 @@ int rc; /* do we need to do it? */ - if (dev->class != ATA_DEV_ATA || + if ((dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC) || !ata_id_has_lba(dev->id) || !ata_id_hpa_enabled(dev->id) || (dev->horkage & ATA_HORKAGE_BROKEN_HPA)) return 0; @@ -1524,7 +1546,7 @@ * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command - * @dma_dir: Data tranfer direction of the command + * @dma_dir: Data transfer direction of the command * @sgl: sg list for the data buffer of the command * @n_elem: Number of sg entries * @timeout: Timeout in msecs (0 for default) @@ -1579,8 +1601,6 @@ else tag = 0; - if (test_and_set_bit(tag, &ap->qc_allocated)) - BUG(); qc = __ata_qc_from_tag(ap, tag); qc->tag = tag; @@ -1712,7 +1732,7 @@ * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command - * @dma_dir: Data tranfer direction of the command + * @dma_dir: Data transfer direction of the command * @buf: Data buffer of the command * @buflen: Length of data buffer * @timeout: Timeout in msecs (0 for default) @@ -1746,33 +1766,6 @@ } /** - * ata_do_simple_cmd - execute simple internal command - * @dev: Device to which the command is sent - * @cmd: Opcode to execute - * - * Execute a 'simple' command, that only consists of the opcode - * 'cmd' itself, without filling any other registers - * - * LOCKING: - * Kernel thread context (may sleep). - * - * RETURNS: - * Zero on success, AC_ERR_* mask on failure - */ -unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd) -{ - struct ata_taskfile tf; - - ata_tf_init(dev, &tf); - - tf.command = cmd; - tf.flags |= ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_NODATA; - - return ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); -} - -/** * ata_pio_need_iordy - check if iordy needed * @adev: ATA device * @@ -1888,6 +1881,7 @@ case ATA_DEV_SEMB: class = ATA_DEV_ATA; /* some hard drives report SEMB sig */ case ATA_DEV_ATA: + case ATA_DEV_ZAC: tf.command = ATA_CMD_ID_ATA; break; case ATA_DEV_ATAPI: @@ -1979,7 +1973,7 @@ rc = -EINVAL; reason = "device reports invalid type"; - if (class == ATA_DEV_ATA) { + if (class == ATA_DEV_ATA || class == ATA_DEV_ZAC) { if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)) goto err_out; if (ap->host->flags & ATA_HOST_IGNORE_ATA && @@ -2014,7 +2008,8 @@ goto retry; } - if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { + if ((flags & ATA_READID_POSTRESET) && + (class == ATA_DEV_ATA || class == ATA_DEV_ZAC)) { /* * The exact sequence expected by certain pre-ATA4 drives is: * SRST RESET @@ -2139,6 +2134,29 @@ else snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth, ddepth, aa_desc); + + if ((ap->flags & ATA_FLAG_FPDMA_AUX) && + ata_id_has_ncq_send_and_recv(dev->id)) { + err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV, + 0, ap->sector_buf, 1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to get NCQ Send/Recv Log Emask 0x%x\n", + err_mask); + } else { + u8 *cmds = dev->ncq_send_recv_cmds; + + dev->flags |= ATA_DFLAG_NCQ_SEND_RECV; + memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE); + + if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) { + ata_dev_dbg(dev, "disabling queued TRIM support\n"); + cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &= + ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM; + } + } + } + return 0; } @@ -2256,7 +2274,7 @@ sizeof(modelbuf)); /* ATA-specific feature tests */ - if (dev->class == ATA_DEV_ATA) { + if (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ZAC) { if (ata_id_is_cfa(id)) { /* CPRM may make this media unusable */ if (id[ATA_ID_CFA_KEY_MGMT] & 1) @@ -2455,6 +2473,10 @@ dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_1024) + dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_1024, + dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; @@ -3631,7 +3653,7 @@ * EH context. * * RETURNS: - * 0 on succes, -errno otherwise. + * 0 on success, -errno otherwise. */ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy, bool spm_wakeup) @@ -4009,6 +4031,7 @@ if (ata_class_enabled(new_class) && new_class != ATA_DEV_ATA && new_class != ATA_DEV_ATAPI && + new_class != ATA_DEV_ZAC && new_class != ATA_DEV_SEMB) { ata_dev_info(dev, "class mismatch %u != %u\n", dev->class, new_class); @@ -4122,6 +4145,18 @@ { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + /* + * Causes silent data corruption with higher max sects. + * http://lkml.kernel.org/g/x49wpy40ysk.fsf@segfault.boston.devel.redhat.com + */ + { "ST380013AS", "3.20", ATA_HORKAGE_MAX_SEC_1024 }, + + /* + * These devices time out with higher max sects. + * https://bugzilla.kernel.org/show_bug.cgi?id=121671 + */ + { "LITEON CX1-JB*-HP", NULL, ATA_HORKAGE_MAX_SEC_1024 }, + /* Devices we expect to fail diagnostics */ /* Devices where NCQ should be avoided */ @@ -4201,10 +4236,52 @@ { "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER }, { "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER }, + /* devices that don't properly handle queued TRIM commands */ + { "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Micron_M5[15]0_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + /* devices that don't properly handle TRIM commands */ { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, }, /* + * As defined, the DRAT (Deterministic Read After Trim) and RZAT + * (Return Zero After Trim) flags in the ATA Command Set are + * unreliable in the sense that they only define what happens if + * the device successfully executed the DSM TRIM command. TRIM + * is only advisory, however, and the device is free to silently + * ignore all or parts of the request. + * + * Whitelist drives that are known to reliably return zeroes + * after TRIM. + */ + + /* + * The intel 510 drive has buggy DRAT/RZAT. Explicitly exclude + * that model before whitelisting all other intel SSDs. + */ + { "INTEL*SSDSC2MH*", NULL, 0, }, + + { "Micron*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "INTEL*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "SSD*INTEL*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Samsung*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "SAMSUNG*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "ST[1248][0248]0[FH]*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + + /* * Some WD SATA-I drives spin up and down erratically when the link * is put into the slumber mode. We don't have full list of the * affected devices. Disable LPM if the device matches one of the @@ -4225,73 +4302,6 @@ { } }; -/** - * glob_match - match a text string against a glob-style pattern - * @text: the string to be examined - * @pattern: the glob-style pattern to be matched against - * - * Either/both of text and pattern can be empty strings. - * - * Match text against a glob-style pattern, with wildcards and simple sets: - * - * ? matches any single character. - * * matches any run of characters. - * [xyz] matches a single character from the set: x, y, or z. - * [a-d] matches a single character from the range: a, b, c, or d. - * [a-d0-9] matches a single character from either range. - * - * The special characters ?, [, -, or *, can be matched using a set, eg. [*] - * Behaviour with malformed patterns is undefined, though generally reasonable. - * - * Sample patterns: "SD1?", "SD1[0-5]", "*R0", "SD*1?[012]*xx" - * - * This function uses one level of recursion per '*' in pattern. - * Since it calls _nothing_ else, and has _no_ explicit local variables, - * this will not cause stack problems for any reasonable use here. - * - * RETURNS: - * 0 on match, 1 otherwise. - */ -static int glob_match (const char *text, const char *pattern) -{ - do { - /* Match single character or a '?' wildcard */ - if (*text == *pattern || *pattern == '?') { - if (!*pattern++) - return 0; /* End of both strings: match */ - } else { - /* Match single char against a '[' bracketed ']' pattern set */ - if (!*text || *pattern != '[') - break; /* Not a pattern set */ - while (*++pattern && *pattern != ']' && *text != *pattern) { - if (*pattern == '-' && *(pattern - 1) != '[') - if (*text > *(pattern - 1) && *text < *(pattern + 1)) { - ++pattern; - break; - } - } - if (!*pattern || *pattern == ']') - return 1; /* No match */ - while (*pattern && *pattern++ != ']'); - } - } while (*++text && *pattern); - - /* Match any run of chars against a '*' wildcard */ - if (*pattern == '*') { - if (!*++pattern) - return 0; /* Match: avoid recursion at end of pattern */ - /* Loop to handle additional pattern chars after the wildcard */ - while (*text) { - if (glob_match(text, pattern) == 0) - return 0; /* Remainder matched */ - ++text; /* Absorb (match) this char and try again */ - } - } - if (!*text && !*pattern) - return 0; /* End of both strings: match */ - return 1; /* No match */ -} - static unsigned long ata_dev_blacklisted(const struct ata_device *dev) { unsigned char model_num[ATA_ID_PROD_LEN + 1]; @@ -4302,10 +4312,10 @@ ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev)); while (ad->model_num) { - if (!glob_match(model_num, ad->model_num)) { + if (glob_match(ad->model_num, model_num)) { if (ad->model_rev == NULL) return ad->horkage; - if (!glob_match(model_rev, ad->model_rev)) + if (glob_match(ad->model_rev, model_rev)) return ad->horkage; } ad++; @@ -4760,66 +4770,40 @@ } /** - * ata_qc_new - Request an available ATA command, for queueing - * @ap: target port - * - * Some ATA host controllers may implement a queue depth which is less - * than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond - * the hardware limitation. + * ata_qc_new_init - Request an available ATA command, and initialize it + * @dev: Device from whom we request an available command structure + * @tag: tag * * LOCKING: * None. */ -static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) { - struct ata_queued_cmd *qc = NULL; - unsigned int max_queue = ap->host->n_tags; - unsigned int i, tag; + struct ata_port *ap = dev->link->ap; + struct ata_queued_cmd *qc; /* no command while frozen */ if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) return NULL; - for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) { - tag = tag < max_queue ? tag : 0; - - /* the last tag is reserved for internal command. */ - if (tag == ATA_TAG_INTERNAL) - continue; - - if (!test_and_set_bit(tag, &ap->qc_allocated)) { - qc = __ata_qc_from_tag(ap, tag); - qc->tag = tag; - ap->last_tag = tag; - break; - } + /* libsas case */ + if (ap->flags & ATA_FLAG_SAS_HOST) { + tag = ata_sas_allocate_tag(ap); + if (tag < 0) + return NULL; } +#ifdef CONFIG_ATA_LEDS + ata_led_act(ap); +#endif - return qc; -} - -/** - * ata_qc_new_init - Request an available ATA command, and initialize it - * @dev: Device from whom we request an available command structure - * - * LOCKING: - * None. - */ - -struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev) -{ - struct ata_port *ap = dev->link->ap; - struct ata_queued_cmd *qc; - - qc = ata_qc_new(ap); - if (qc) { - qc->scsicmd = NULL; - qc->ap = ap; - qc->dev = dev; + qc = __ata_qc_from_tag(ap, tag); + qc->tag = tag; + qc->scsicmd = NULL; + qc->ap = ap; + qc->dev = dev; - ata_qc_reinit(qc); - } + ata_qc_reinit(qc); return qc; } @@ -4846,7 +4830,8 @@ tag = qc->tag; if (likely(ata_tag_valid(tag))) { qc->tag = ATA_TAG_POISON; - clear_bit(tag, &ap->qc_allocated); + if (ap->flags & ATA_FLAG_SAS_HOST) + ata_sas_free_tag(tag, ap); } } @@ -4955,6 +4940,7 @@ */ if (unlikely(ata_tag_internal(qc->tag))) { fill_result_tf(qc); + trace_ata_qc_complete_internal(qc); __ata_qc_complete(qc); return; } @@ -4965,6 +4951,7 @@ */ if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { fill_result_tf(qc); + trace_ata_qc_complete_failed(qc); ata_qc_schedule_eh(qc); return; } @@ -4975,6 +4962,7 @@ if (qc->flags & ATA_QCFLAG_RESULT_TF) fill_result_tf(qc); + trace_ata_qc_complete_done(qc); /* Some commands need post-processing after successful * completion. */ @@ -5122,7 +5110,7 @@ } ap->ops->qc_prep(qc); - + trace_ata_qc_issue(qc); qc->err_mask |= ap->ops->qc_issue(qc); if (unlikely(qc->err_mask)) goto err; @@ -5340,22 +5328,17 @@ } #ifdef CONFIG_PM -static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg, - unsigned int action, unsigned int ehi_flags, - int *async) +static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg, + unsigned int action, unsigned int ehi_flags, + bool async) { struct ata_link *link; unsigned long flags; - int rc = 0; /* Previous resume operation might still be in * progress. Wait for PM_PENDING to clear. */ if (ap->pflags & ATA_PFLAG_PM_PENDING) { - if (async) { - *async = -EAGAIN; - return 0; - } ata_port_wait_eh(ap); WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); } @@ -5364,11 +5347,6 @@ spin_lock_irqsave(ap->lock, flags); ap->pm_mesg = mesg; - if (async) - ap->pm_result = async; - else - ap->pm_result = &rc; - ap->pflags |= ATA_PFLAG_PM_PENDING; ata_for_each_link(link, ap, HOST_FIRST) { link->eh_info.action |= action; @@ -5379,87 +5357,81 @@ spin_unlock_irqrestore(ap->lock, flags); - /* wait and check result */ if (!async) { ata_port_wait_eh(ap); WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); } - - return rc; } -static int __ata_port_suspend_common(struct ata_port *ap, pm_message_t mesg, int *async) +/* + * On some hardware, device fails to respond after spun down for suspend. As + * the device won't be used before being resumed, we don't need to touch the + * device. Ask EH to skip the usual stuff and proceed directly to suspend. + * + * http://thread.gmane.org/gmane.linux.ide/46764 + */ +static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET + | ATA_EHI_NO_AUTOPSY + | ATA_EHI_NO_RECOVERY; + +static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg) { - /* - * On some hardware, device fails to respond after spun down - * for suspend. As the device won't be used before being - * resumed, we don't need to touch the device. Ask EH to skip - * the usual stuff and proceed directly to suspend. - * - * http://thread.gmane.org/gmane.linux.ide/46764 - */ - unsigned int ehi_flags = ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY | - ATA_EHI_NO_RECOVERY; - return ata_port_request_pm(ap, mesg, 0, ehi_flags, async); + ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false); } -static int ata_port_suspend_common(struct device *dev, pm_message_t mesg) +static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg) { - struct ata_port *ap = to_ata_port(dev); - - return __ata_port_suspend_common(ap, mesg, NULL); + ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true); } -static int ata_port_suspend(struct device *dev) +static int ata_port_pm_suspend(struct device *dev) { + struct ata_port *ap = to_ata_port(dev); + if (pm_runtime_suspended(dev)) return 0; - return ata_port_suspend_common(dev, PMSG_SUSPEND); + ata_port_suspend(ap, PMSG_SUSPEND); + return 0; } -static int ata_port_do_freeze(struct device *dev) +static int ata_port_pm_freeze(struct device *dev) { + struct ata_port *ap = to_ata_port(dev); + if (pm_runtime_suspended(dev)) return 0; - return ata_port_suspend_common(dev, PMSG_FREEZE); + ata_port_suspend(ap, PMSG_FREEZE); + return 0; } -static int ata_port_poweroff(struct device *dev) +static int ata_port_pm_poweroff(struct device *dev) { - return ata_port_suspend_common(dev, PMSG_HIBERNATE); + ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE); + return 0; } -static int __ata_port_resume_common(struct ata_port *ap, pm_message_t mesg, - int *async) -{ - int rc; +static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY + | ATA_EHI_QUIET; - rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET, - ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async); - return rc; +static void ata_port_resume(struct ata_port *ap, pm_message_t mesg) +{ + ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false); } -static int ata_port_resume_common(struct device *dev, pm_message_t mesg) +static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg) { - struct ata_port *ap = to_ata_port(dev); - - return __ata_port_resume_common(ap, mesg, NULL); + ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true); } -static int ata_port_resume(struct device *dev) +static int ata_port_pm_resume(struct device *dev) { - int rc; - - rc = ata_port_resume_common(dev, PMSG_RESUME); - if (!rc) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - - return rc; + ata_port_resume_async(to_ata_port(dev), PMSG_RESUME); + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + return 0; } /* @@ -5483,26 +5455,28 @@ return -EBUSY; } - return pm_runtime_suspend(dev); + return 0; } static int ata_port_runtime_suspend(struct device *dev) { - return ata_port_suspend_common(dev, PMSG_AUTO_SUSPEND); + ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND); + return 0; } static int ata_port_runtime_resume(struct device *dev) { - return ata_port_resume_common(dev, PMSG_AUTO_RESUME); + ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME); + return 0; } static const struct dev_pm_ops ata_port_pm_ops = { - .suspend = ata_port_suspend, - .resume = ata_port_resume, - .freeze = ata_port_do_freeze, - .thaw = ata_port_resume, - .poweroff = ata_port_poweroff, - .restore = ata_port_resume, + .suspend = ata_port_pm_suspend, + .resume = ata_port_pm_resume, + .freeze = ata_port_pm_freeze, + .thaw = ata_port_pm_resume, + .poweroff = ata_port_pm_poweroff, + .restore = ata_port_pm_resume, .runtime_suspend = ata_port_runtime_suspend, .runtime_resume = ata_port_runtime_resume, @@ -5514,18 +5488,17 @@ * level. sas suspend/resume is async to allow parallel port recovery * since sas has multiple ata_port instances per Scsi_Host. */ -int ata_sas_port_async_suspend(struct ata_port *ap, int *async) +void ata_sas_port_suspend(struct ata_port *ap) { - return __ata_port_suspend_common(ap, PMSG_SUSPEND, async); + ata_port_suspend_async(ap, PMSG_SUSPEND); } -EXPORT_SYMBOL_GPL(ata_sas_port_async_suspend); +EXPORT_SYMBOL_GPL(ata_sas_port_suspend); -int ata_sas_port_async_resume(struct ata_port *ap, int *async) +void ata_sas_port_resume(struct ata_port *ap) { - return __ata_port_resume_common(ap, PMSG_RESUME, async); + ata_port_resume_async(ap, PMSG_RESUME); } -EXPORT_SYMBOL_GPL(ata_sas_port_async_resume); - +EXPORT_SYMBOL_GPL(ata_sas_port_resume); /** * ata_host_suspend - suspend host @@ -5689,6 +5662,7 @@ ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN; ap->lock = &host->lock; ap->print_id = -1; + ap->local_port_no = -1; ap->host = host; ap->dev = host->dev; @@ -5719,6 +5693,9 @@ ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; #endif +#ifdef CONFIG_ATA_LEDS + ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); +#endif ata_sff_port_init(ap); return ap; @@ -5740,6 +5717,12 @@ kfree(ap->pmp_link); kfree(ap->slave_link); +#ifdef CONFIG_ATA_LEDS + if (ap->ledtrig) { + led_trigger_unregister(ap->ledtrig); + kfree(ap->ledtrig); + }; +#endif kfree(ap); host->ports[i] = NULL; } @@ -6182,10 +6165,27 @@ kfree(host->ports[i]); /* give ports names and add SCSI hosts */ - for (i = 0; i < host->n_ports; i++) + for (i = 0; i < host->n_ports; i++) { host->ports[i]->print_id = atomic_inc_return(&ata_print_id); + host->ports[i]->local_port_no = i + 1; + } +#ifdef CONFIG_ATA_LEDS + for (i = 0; i < host->n_ports; i++) { + if (unlikely(!host->ports[i]->ledtrig)) + continue; - + snprintf(host->ports[i]->ledtrig_name, + sizeof(host->ports[i]->ledtrig_name), "ata%u", + host->ports[i]->print_id); + + host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; + + if (led_trigger_register(host->ports[i]->ledtrig)) { + kfree(host->ports[i]->ledtrig); + host->ports[i]->ledtrig = NULL; + } + } +#endif /* Create associated sysfs transport objects */ for (i = 0; i < host->n_ports; i++) { rc = ata_tport_add(host->dev,host->ports[i]); @@ -6198,8 +6198,6 @@ if (rc) goto err_tadd; - ata_acpi_hotplug_init(host); - /* set cable, sata_spd_limit and report */ for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; @@ -6284,7 +6282,7 @@ } rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags, - dev_driver_string(host->dev), host); + dev_name(host->dev), host); if (rc) return rc; @@ -6346,10 +6344,9 @@ for (i = 0; i < SATA_PMP_MAX_PORTS; i++) ata_tlink_delete(&ap->pmp_link[i]); } - ata_tport_delete(ap); - /* remove the associated SCSI host */ scsi_remove_host(ap->scsi_host); + ata_tport_delete(ap); } /** @@ -6506,12 +6503,7 @@ 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 = { + static const struct ata_force_param force_tbl[] __initconst = { { "40c", .cbl = ATA_CBL_PATA40 }, { "80c", .cbl = ATA_CBL_PATA80 }, { "short40c", .cbl = ATA_CBL_PATA40_SHORT }, @@ -6522,6 +6514,8 @@ { "3.0Gbps", .spd_limit = 2 }, { "noncq", .horkage_on = ATA_HORKAGE_NONCQ }, { "ncq", .horkage_off = ATA_HORKAGE_NONCQ }, + { "noncqtrim", .horkage_on = ATA_HORKAGE_NO_NCQ_TRIM }, + { "ncqtrim", .horkage_off = ATA_HORKAGE_NO_NCQ_TRIM }, { "dump_id", .horkage_on = ATA_HORKAGE_DUMP_ID }, { "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) }, { "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) }, @@ -6690,8 +6684,6 @@ ata_parse_force_param(); - ata_acpi_register(); - rc = ata_sff_init(); if (rc) { kfree(ata_force_tbl); @@ -6718,7 +6710,6 @@ ata_release_transport(ata_scsi_transport_template); libata_transport_exit(); ata_sff_exit(); - ata_acpi_unregister(); kfree(ata_force_tbl); } @@ -6865,32 +6856,28 @@ /* * Utility print functions */ -int ata_port_printk(const struct ata_port *ap, const char *level, - const char *fmt, ...) +void ata_port_printk(const struct ata_port *ap, const char *level, + const char *fmt, ...) { struct va_format vaf; va_list args; - int r; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - r = printk("%sata%u: %pV", level, ap->print_id, &vaf); + printk("%sata%u: %pV", level, ap->print_id, &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(ata_port_printk); -int ata_link_printk(const struct ata_link *link, const char *level, - const char *fmt, ...) +void ata_link_printk(const struct ata_link *link, const char *level, + const char *fmt, ...) { struct va_format vaf; va_list args; - int r; va_start(args, fmt); @@ -6898,37 +6885,32 @@ vaf.va = &args; if (sata_pmp_attached(link->ap) || link->ap->slave_link) - r = printk("%sata%u.%02u: %pV", - level, link->ap->print_id, link->pmp, &vaf); + printk("%sata%u.%02u: %pV", + level, link->ap->print_id, link->pmp, &vaf); else - r = printk("%sata%u: %pV", - level, link->ap->print_id, &vaf); + printk("%sata%u: %pV", + level, link->ap->print_id, &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(ata_link_printk); -int ata_dev_printk(const struct ata_device *dev, const char *level, +void ata_dev_printk(const struct ata_device *dev, const char *level, const char *fmt, ...) { struct va_format vaf; va_list args; - int r; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - r = printk("%sata%u.%02u: %pV", - level, dev->link->ap->print_id, dev->link->pmp + dev->devno, - &vaf); + printk("%sata%u.%02u: %pV", + level, dev->link->ap->print_id, dev->link->pmp + dev->devno, + &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(ata_dev_printk);