diff options
Diffstat (limited to 'drivers')
27 files changed, 234 insertions, 321 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 8e28f92..e2903d0 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -292,6 +292,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ + { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 1145637..2289efd 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -339,6 +339,7 @@ extern struct device_attribute *ahci_sdev_attrs[]; .sdev_attrs = ahci_sdev_attrs extern struct ata_port_operations ahci_ops; +extern struct ata_port_operations ahci_platform_ops; extern struct ata_port_operations ahci_pmp_retry_srst_ops; unsigned int ahci_dev_classify(struct ata_port *ap); @@ -368,6 +369,7 @@ irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance); irqreturn_t ahci_thread_fn(int irq, void *dev_instance); void ahci_print_info(struct ata_host *host, const char *scc_s); int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis); +void ahci_error_handler(struct ata_port *ap); static inline void __iomem *__ahci_port_base(struct ata_host *host, unsigned int port_no) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 58debb0..ae2d73f 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -1,6 +1,6 @@ /* + * copyright (c) 2013 Freescale Semiconductor, Inc. * Freescale IMX AHCI SATA platform driver - * Copyright 2013 Freescale Semiconductor, Inc. * * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov * @@ -25,10 +25,13 @@ #include <linux/of_device.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/libata.h> #include "ahci.h" enum { - HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ + PORT_PHY_CTL = 0x178, /* Port0 PHY Control */ + PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */ + HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ }; struct imx_ahci_priv { @@ -36,6 +39,56 @@ struct imx_ahci_priv { struct clk *sata_ref_clk; struct clk *ahb_clk; struct regmap *gpr; + bool no_device; + bool first_time; +}; + +static int ahci_imx_hotplug; +module_param_named(hotplug, ahci_imx_hotplug, int, 0644); +MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); + +static void ahci_imx_error_handler(struct ata_port *ap) +{ + u32 reg_val; + struct ata_device *dev; + struct ata_host *host = dev_get_drvdata(ap->dev); + struct ahci_host_priv *hpriv = host->private_data; + void __iomem *mmio = hpriv->mmio; + struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); + + ahci_error_handler(ap); + + if (!(imxpriv->first_time) || ahci_imx_hotplug) + return; + + imxpriv->first_time = false; + + ata_for_each_dev(dev, &ap->link, ENABLED) + return; + /* + * Disable link to save power. An imx ahci port can't be recovered + * without full reset once the pddq mode is enabled making it + * impossible to use as part of libata LPM. + */ + reg_val = readl(mmio + PORT_PHY_CTL); + writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + clk_disable_unprepare(imxpriv->sata_ref_clk); + imxpriv->no_device = true; +} + +static struct ata_port_operations ahci_imx_ops = { + .inherits = &ahci_platform_ops, + .error_handler = ahci_imx_error_handler, +}; + +static const struct ata_port_info ahci_imx_port_info = { + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_imx_ops, }; static int imx6q_sata_init(struct device *dev, void __iomem *mmio) @@ -117,9 +170,51 @@ static void imx6q_sata_exit(struct device *dev) clk_disable_unprepare(imxpriv->sata_ref_clk); } +static int imx_ahci_suspend(struct device *dev) +{ + struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + + /* + * If no_device is set, The CLKs had been gated off in the + * initialization so don't do it again here. + */ + if (!imxpriv->no_device) { + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + clk_disable_unprepare(imxpriv->sata_ref_clk); + } + + return 0; +} + +static int imx_ahci_resume(struct device *dev) +{ + struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + int ret; + + if (!imxpriv->no_device) { + ret = clk_prepare_enable(imxpriv->sata_ref_clk); + if (ret < 0) { + dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret); + return ret; + } + + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + IMX6Q_GPR13_SATA_MPLL_CLK_EN); + usleep_range(1000, 2000); + } + + return 0; +} + static struct ahci_platform_data imx6q_sata_pdata = { .init = imx6q_sata_init, .exit = imx6q_sata_exit, + .ata_port_info = &ahci_imx_port_info, + .suspend = imx_ahci_suspend, + .resume = imx_ahci_resume, }; static const struct of_device_id imx_ahci_of_match[] = { @@ -152,6 +247,8 @@ static int imx_ahci_probe(struct platform_device *pdev) ahci_dev = &ahci_pdev->dev; ahci_dev->parent = dev; + imxpriv->no_device = false; + imxpriv->first_time = true; imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); if (IS_ERR(imxpriv->ahb_clk)) { dev_err(dev, "can't get ahb clock.\n"); diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 7d3b853..f955431 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -49,10 +49,11 @@ static struct platform_device_id ahci_devtype[] = { }; MODULE_DEVICE_TABLE(platform, ahci_devtype); -static struct ata_port_operations ahci_platform_ops = { +struct ata_port_operations ahci_platform_ops = { .inherits = &ahci_ops, .host_stop = ahci_host_stop, }; +EXPORT_SYMBOL_GPL(ahci_platform_ops); static struct ata_port_operations ahci_platform_retry_srst_ops = { .inherits = &ahci_pmp_retry_srst_ops, diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 513ad7e..6334c8d 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -100,7 +100,7 @@ enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ - ICH5_PMR = 0x90, /* port mapping register */ + ICH5_PMR = 0x90, /* address map register */ ICH5_PCS = 0x92, /* port control and status */ PIIX_SIDPR_BAR = 5, PIIX_SIDPR_LEN = 16, @@ -233,7 +233,7 @@ static const struct pci_device_id piix_pci_tbl[] = { PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata }, /* 82801GB/GR/GH (ICH7, identical to ICH6) */ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, - /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ + /* 82801GBM/GHM (ICH7M, identical to ICH6M) */ { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata }, /* Enterprise Southbridge 2 (631xESB/632xESB) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, @@ -517,7 +517,7 @@ static int ich_pata_cable_detect(struct ata_port *ap) const struct ich_laptop *lap = &ich_laptop[0]; u8 mask; - /* Check for specials - Acer Aspire 5602WLMi */ + /* Check for specials */ while (lap->device) { if (lap->device == pdev->device && lap->subvendor == pdev->subsystem_vendor && @@ -1366,38 +1366,39 @@ static const int *piix_init_sata_map(struct pci_dev *pdev, const int *map; int i, invalid_map = 0; u8 map_value; + char buf[32]; + char *p = buf, *end = buf + sizeof(buf); pci_read_config_byte(pdev, ICH5_PMR, &map_value); map = map_db->map[map_value & map_db->mask]; - dev_info(&pdev->dev, "MAP ["); for (i = 0; i < 4; i++) { switch (map[i]) { case RV: invalid_map = 1; - pr_cont(" XX"); + p += scnprintf(p, end - p, " XX"); break; case NA: - pr_cont(" --"); + p += scnprintf(p, end - p, " --"); break; case IDE: WARN_ON((i & 1) || map[i + 1] != IDE); pinfo[i / 2] = piix_port_info[ich_pata_100]; i++; - pr_cont(" IDE IDE"); + p += scnprintf(p, end - p, " IDE IDE"); break; default: - pr_cont(" P%d", map[i]); + p += scnprintf(p, end - p, " P%d", map[i]); if (i & 1) pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS; break; } } - pr_cont(" ]\n"); + dev_info(&pdev->dev, "MAP [%s ]\n", buf); if (invalid_map) dev_err(&pdev->dev, "invalid MAP value %u\n", map_value); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index aaac4fb..c482f8c 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -89,7 +89,6 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, static int ahci_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static void ahci_postreset(struct ata_link *link, unsigned int *class); -static void ahci_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static void ahci_dev_config(struct ata_device *dev); #ifdef CONFIG_PM @@ -189,14 +188,15 @@ struct ata_port_operations ahci_pmp_retry_srst_ops = { }; EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops); -int ahci_em_messages = 1; +static bool ahci_em_messages __read_mostly = true; EXPORT_SYMBOL_GPL(ahci_em_messages); -module_param(ahci_em_messages, int, 0444); +module_param(ahci_em_messages, bool, 0444); /* add other LED protocol types when they become supported */ MODULE_PARM_DESC(ahci_em_messages, "AHCI Enclosure Management Message control (0 = off, 1 = on)"); -int devslp_idle_timeout = 1000; /* device sleep idle timeout in ms */ +/* device sleep idle timeout in ms */ +static int devslp_idle_timeout __read_mostly = 1000; module_param(devslp_idle_timeout, int, 0644); MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout"); @@ -1275,9 +1275,11 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, { struct ata_port *ap = link->ap; struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; const char *reason = NULL; unsigned long now, msecs; struct ata_taskfile tf; + bool fbs_disabled = false; int rc; DPRINTK("ENTER\n"); @@ -1287,6 +1289,16 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, if (rc && rc != -EOPNOTSUPP) ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc); + /* + * According to AHCI-1.2 9.3.9: if FBS is enable, software shall + * clear PxFBS.EN to '0' prior to issuing software reset to devices + * that is attached to port multiplier. + */ + if (!ata_is_host_link(link) && pp->fbs_enabled) { + ahci_disable_fbs(ap); + fbs_disabled = true; + } + ata_tf_init(link->device, &tf); /* issue the first D2H Register FIS */ @@ -1327,6 +1339,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, } else *class = ahci_dev_classify(ap); + /* re-enable FBS if disabled before */ + if (fbs_disabled) + ahci_enable_fbs(ap); + DPRINTK("EXIT, class=%u\n", *class); return 0; @@ -1989,7 +2005,7 @@ static void ahci_thaw(struct ata_port *ap) writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); } -static void ahci_error_handler(struct ata_port *ap) +void ahci_error_handler(struct ata_port *ap) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) { /* restart engine */ @@ -2002,6 +2018,7 @@ static void ahci_error_handler(struct ata_port *ap) if (!ata_dev_enabled(ap->link.device)) ahci_stop_engine(ap); } +EXPORT_SYMBOL_GPL(ahci_error_handler); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 83b1a9f..81a94a3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4126,6 +4126,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, /* Devices we expect to fail diagnostics */ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 370462f..77bbc82 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2293,6 +2293,7 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_IDLE, "IDLE" }, { ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" }, { ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" }, + { ATA_CMD_DOWNLOAD_MICRO_DMA, "DOWNLOAD MICROCODE DMA" }, { ATA_CMD_NOP, "NOP" }, { ATA_CMD_FLUSH, "FLUSH CACHE" }, { ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" }, @@ -2313,6 +2314,8 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" }, { ATA_CMD_FPDMA_READ, "READ FPDMA QUEUED" }, { ATA_CMD_FPDMA_WRITE, "WRITE FPDMA QUEUED" }, + { ATA_CMD_FPDMA_SEND, "SEND FPDMA QUEUED" }, + { ATA_CMD_FPDMA_RECV, "RECEIVE FPDMA QUEUED" }, { ATA_CMD_PIO_READ, "READ SECTOR(S)" }, { ATA_CMD_PIO_READ_EXT, "READ SECTOR(S) EXT" }, { ATA_CMD_PIO_WRITE, "WRITE SECTOR(S)" }, @@ -2339,12 +2342,15 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_WRITE_LOG_EXT, "WRITE LOG EXT" }, { ATA_CMD_READ_LOG_DMA_EXT, "READ LOG DMA EXT" }, { ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" }, + { ATA_CMD_TRUSTED_NONDATA, "TRUSTED NON-DATA" }, { ATA_CMD_TRUSTED_RCV, "TRUSTED RECEIVE" }, { ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" }, { ATA_CMD_TRUSTED_SND, "TRUSTED SEND" }, { ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" }, { ATA_CMD_PMP_READ, "READ BUFFER" }, + { ATA_CMD_PMP_READ_DMA, "READ BUFFER DMA" }, { ATA_CMD_PMP_WRITE, "WRITE BUFFER" }, + { ATA_CMD_PMP_WRITE_DMA, "WRITE BUFFER DMA" }, { ATA_CMD_CONF_OVERLAY, "DEVICE CONFIGURATION OVERLAY" }, { ATA_CMD_SEC_SET_PASS, "SECURITY SET PASSWORD" }, { ATA_CMD_SEC_UNLOCK, "SECURITY UNLOCK" }, @@ -2363,6 +2369,8 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_CFA_TRANS_SECT, "CFA TRANSLATE SECTOR" }, { ATA_CMD_CFA_ERASE, "CFA ERASE SECTORS" }, { ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" }, + { ATA_CMD_REQ_SENSE_DATA, "REQUEST SENSE DATA EXT" }, + { ATA_CMD_SANITIZE_DEVICE, "SANITIZE DEVICE" }, { ATA_CMD_READ_LONG, "READ LONG (with retries)" }, { ATA_CMD_READ_LONG_ONCE, "READ LONG (without retries)" }, { ATA_CMD_WRITE_LONG, "WRITE LONG (with retries)" }, diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 150a917..e37413228 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -321,25 +321,25 @@ int ata_tport_add(struct device *parent, /* * ATA link attributes */ +static int noop(int x) { return x; } - -#define ata_link_show_linkspeed(field) \ +#define ata_link_show_linkspeed(field, format) \ static ssize_t \ show_ata_link_##field(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct ata_link *link = transport_class_to_link(dev); \ \ - return sprintf(buf,"%s\n", sata_spd_string(fls(link->field))); \ + return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \ } -#define ata_link_linkspeed_attr(field) \ - ata_link_show_linkspeed(field) \ +#define ata_link_linkspeed_attr(field, format) \ + ata_link_show_linkspeed(field, format) \ static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL) -ata_link_linkspeed_attr(hw_sata_spd_limit); -ata_link_linkspeed_attr(sata_spd_limit); -ata_link_linkspeed_attr(sata_spd); +ata_link_linkspeed_attr(hw_sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd, noop); static DECLARE_TRANSPORT_CLASS(ata_link_class, diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index 7f5e5d9..ea3b3dc 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -343,13 +343,11 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr) { struct device_node *sata_node = dev->of_node; int phy_count = 0, phy, port = 0, i; - void __iomem *cphy_base[CPHY_PHY_COUNT]; - struct device_node *phy_nodes[CPHY_PHY_COUNT]; - u32 tx_atten[CPHY_PORT_COUNT]; + void __iomem *cphy_base[CPHY_PHY_COUNT] = {}; + struct device_node *phy_nodes[CPHY_PHY_COUNT] = {}; + u32 tx_atten[CPHY_PORT_COUNT] = {}; memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); - memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); - memset(tx_atten, 0xff, CPHY_PORT_COUNT); do { u32 tmp; diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c index c2d95e9..1dae9a9 100644 --- a/drivers/ata/sata_rcar.c +++ b/drivers/ata/sata_rcar.c @@ -792,7 +792,7 @@ static int sata_rcar_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get access to sata clock\n"); return PTR_ERR(priv->clk); } - clk_enable(priv->clk); + clk_prepare_enable(priv->clk); host = ata_host_alloc(&pdev->dev, 1); if (!host) { @@ -822,7 +822,7 @@ static int sata_rcar_probe(struct platform_device *pdev) return 0; cleanup: - clk_disable(priv->clk); + clk_disable_unprepare(priv->clk); return ret; } @@ -841,7 +841,7 @@ static int sata_rcar_remove(struct platform_device *pdev) iowrite32(0, base + SATAINTSTAT_REG); iowrite32(0x7ff, base + SATAINTMASK_REG); - clk_disable(priv->clk); + clk_disable_unprepare(priv->clk); return 0; } @@ -861,7 +861,7 @@ static int sata_rcar_suspend(struct device *dev) /* mask */ iowrite32(0x7ff, base + SATAINTMASK_REG); - clk_disable(priv->clk); + clk_disable_unprepare(priv->clk); } return ret; @@ -873,7 +873,7 @@ static int sata_rcar_resume(struct device *dev) struct sata_rcar_priv *priv = host->private_data; void __iomem *base = priv->base; - clk_enable(priv->clk); + clk_prepare_enable(priv->clk); /* ack and mask */ iowrite32(0, base + SATAINTSTAT_REG); diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 7413d06..0f38201 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -216,7 +216,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid, newattrs.ia_gid = gid; newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID; mutex_lock(&dentry->d_inode->i_mutex); - notify_change(dentry, &newattrs); + notify_change(dentry, &newattrs, NULL); mutex_unlock(&dentry->d_inode->i_mutex); /* mark as kernel-created inode */ @@ -322,9 +322,9 @@ static int handle_remove(const char *nodename, struct device *dev) newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); - notify_change(dentry, &newattrs); + notify_change(dentry, &newattrs, NULL); mutex_unlock(&dentry->d_inode->i_mutex); - err = vfs_unlink(parent.dentry->d_inode, dentry); + err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); if (!err || err == -ENOENT) deleted = 1; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 2f685f6..ffa97d2 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -114,7 +114,7 @@ static int misc_open(struct inode * inode, struct file * file) int minor = iminor(inode); struct miscdevice *c; int err = -ENODEV; - const struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *new_fops = NULL; mutex_lock(&misc_mtx); @@ -141,17 +141,11 @@ static int misc_open(struct inode * inode, struct file * file) } err = 0; - old_fops = file->f_op; - file->f_op = new_fops; + replace_fops(file, new_fops); if (file->f_op->open) { file->private_data = c; - err=file->f_op->open(inode,file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } + err = file->f_op->open(inode,file); } - fops_put(old_fops); fail: mutex_unlock(&misc_mtx); return err; diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 3f84277..22d14ec 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -148,7 +148,7 @@ int drm_stub_open(struct inode *inode, struct file *filp) struct drm_minor *minor; int minor_id = iminor(inode); int err = -ENODEV; - const struct file_operations *old_fops; + const struct file_operations *new_fops; DRM_DEBUG("\n"); @@ -163,18 +163,13 @@ int drm_stub_open(struct inode *inode, struct file *filp) if (drm_device_is_unplugged(dev)) goto out; - old_fops = filp->f_op; - filp->f_op = fops_get(dev->driver->fops); - if (filp->f_op == NULL) { - filp->f_op = old_fops; + new_fops = fops_get(dev->driver->fops); + if (!new_fops) goto out; - } - if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) { - fops_put(filp->f_op); - filp->f_op = fops_get(old_fops); - } - fops_put(old_fops); + replace_fops(filp, new_fops); + if (filp->f_op->open) + err = filp->f_op->open(inode, filp); out: mutex_unlock(&drm_global_mutex); return err; diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 0b4616b..c0363f1 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -206,8 +206,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) /* TODO */ dvbdev->users--; if (dvbdev->users == 1 && dmxdev->exit == 1) { - fops_put(file->f_op); - file->f_op = NULL; mutex_unlock(&dmxdev->mutex); wake_up(&dvbdev->wait_queue); } else @@ -1120,8 +1118,6 @@ static int dvb_demux_release(struct inode *inode, struct file *file) mutex_lock(&dmxdev->mutex); dmxdev->dvbdev->users--; if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) { - fops_put(file->f_op); - file->f_op = NULL; mutex_unlock(&dmxdev->mutex); wake_up(&dmxdev->dvbdev->wait_queue); } else diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 401ef64..983db75 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -74,22 +74,15 @@ static int dvb_device_open(struct inode *inode, struct file *file) if (dvbdev && dvbdev->fops) { int err = 0; - const struct file_operations *old_fops; + const struct file_operations *new_fops; - file->private_data = dvbdev; - old_fops = file->f_op; - file->f_op = fops_get(dvbdev->fops); - if (file->f_op == NULL) { - file->f_op = old_fops; + new_fops = fops_get(dvbdev->fops); + if (!new_fops) goto fail; - } - if(file->f_op->open) + file->private_data = dvbdev; + replace_fops(file, new_fops); + if (file->f_op->open) err = file->f_op->open(inode,file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - fops_put(old_fops); up_read(&minor_rwsem); mutex_unlock(&dvbdev_mutex); return err; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index bdc1d15..d1c7de9 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -575,7 +575,7 @@ static int alloc_device(struct nandsim *ns) cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600); if (IS_ERR(cfile)) return PTR_ERR(cfile); - if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) { + if (!cfile->f_op->read && !cfile->f_op->aio_read) { NS_ERR("alloc_device: cache file not readable\n"); err = -EINVAL; goto err_close; diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index c071d41..33bb1f2 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -900,10 +900,9 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, * number. */ image_seq = be32_to_cpu(ech->image_seq); - if (!ubi->image_seq && image_seq) + if (!ubi->image_seq) ubi->image_seq = image_seq; - if (ubi->image_seq && image_seq && - ubi->image_seq != image_seq) { + if (image_seq && ubi->image_seq != image_seq) { ubi_err("bad image sequence number %d in PEB %d, expected %d", image_seq, pnum, ubi->image_seq); ubi_dump_ec_hdr(ech); @@ -1417,9 +1416,11 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) ai = alloc_ai("ubi_aeb_slab_cache2"); if (!ai) return -ENOMEM; - } - err = scan_all(ubi, ai, UBI_FM_MAX_START); + err = scan_all(ubi, ai, 0); + } else { + err = scan_all(ubi, ai, UBI_FM_MAX_START); + } } } #else diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index f5aa4b0..ead8613 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -407,6 +407,7 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, */ for (i = 0; i < pool_size; i++) { int scrub = 0; + int image_seq; pnum = be32_to_cpu(pebs[i]); @@ -425,10 +426,16 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, } else if (ret == UBI_IO_BITFLIPS) scrub = 1; - if (be32_to_cpu(ech->image_seq) != ubi->image_seq) { + /* + * Older UBI implementations have image_seq set to zero, so + * we shouldn't fail if image_seq == 0. + */ + image_seq = be32_to_cpu(ech->image_seq); + + if (image_seq && (image_seq != ubi->image_seq)) { ubi_err("bad image seq: 0x%x, expected: 0x%x", be32_to_cpu(ech->image_seq), ubi->image_seq); - err = UBI_BAD_FASTMAP; + ret = UBI_BAD_FASTMAP; goto out; } @@ -819,6 +826,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) list_move_tail(&tmp_aeb->u.list, &ai->free); + ubi_assert(list_empty(&used)); + ubi_assert(list_empty(&eba_orphans)); + ubi_assert(list_empty(&free)); + /* * If fastmap is leaking PEBs (must not happen), raise a * fat warning and fall back to scanning mode. @@ -834,6 +845,19 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, fail_bad: ret = UBI_BAD_FASTMAP; fail: + list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) { + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); + list_del(&tmp_aeb->u.list); + } + list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) { + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); + list_del(&tmp_aeb->u.list); + } + list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) { + kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); + list_del(&tmp_aeb->u.list); + } + return ret; } @@ -923,6 +947,8 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, } for (i = 0; i < used_blocks; i++) { + int image_seq; + pnum = be32_to_cpu(fmsb->block_loc[i]); if (ubi_io_is_bad(ubi, pnum)) { @@ -940,10 +966,17 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, } else if (ret == UBI_IO_BITFLIPS) fm->to_be_tortured[i] = 1; + image_seq = be32_to_cpu(ech->image_seq); if (!ubi->image_seq) - ubi->image_seq = be32_to_cpu(ech->image_seq); + ubi->image_seq = image_seq; - if (be32_to_cpu(ech->image_seq) != ubi->image_seq) { + /* + * Older UBI implementations have image_seq set to zero, so + * we shouldn't fail if image_seq == 0. + */ + if (image_seq && (image_seq != ubi->image_seq)) { + ubi_err("wrong image seq:%d instead of %d", + be32_to_cpu(ech->image_seq), ubi->image_seq); ret = UBI_BAD_FASTMAP; goto free_hdr; } diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index c95bfb1..02317c1 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -599,10 +599,6 @@ static void refill_wl_user_pool(struct ubi_device *ubi) return_unused_pool_pebs(ubi, pool); for (pool->size = 0; pool->size < pool->max_size; pool->size++) { - if (!ubi->free.rb_node || - (ubi->free_count - ubi->beb_rsvd_pebs < 1)) - break; - pool->pebs[pool->size] = __wl_get_peb(ubi); if (pool->pebs[pool->size] < 0) break; diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 2dfb06a..1e9da40 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -86,9 +86,6 @@ struct comedi32_insnlist_struct { static int translated_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - if (!file->f_op) - return -ENOTTY; - if (file->f_op->unlocked_ioctl) return file->f_op->unlocked_ioctl(file, cmd, arg); diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 359c6c1..eefdb8d 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -105,8 +105,8 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define ll_vfs_unlink(inode,entry,mnt) vfs_unlink(inode,entry) #define ll_vfs_mknod(dir,entry,mnt,mode,dev) vfs_mknod(dir,entry,mode,dev) #define ll_security_inode_unlink(dir,entry,mnt) security_inode_unlink(dir,entry) -#define ll_vfs_rename(old,old_dir,mnt,new,new_dir,mnt1) \ - vfs_rename(old,old_dir,new,new_dir) +#define ll_vfs_rename(old,old_dir,mnt,new,new_dir,mnt1,delegated_inode) \ + vfs_rename(old,old_dir,new,new_dir,delegated_inode) #define cfs_bio_io_error(a,b) bio_io_error((a)) #define cfs_bio_endio(a,b,c) bio_endio((a),(c)) diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 34815b5..90bbdae 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -83,7 +83,7 @@ int ll_unlock(__u32 mode, struct lustre_handle *lockh) } -/* called from iget5_locked->find_inode() under inode_lock spinlock */ +/* called from iget5_locked->find_inode() under inode_hash_lock spinlock */ static int ll_test_inode(struct inode *inode, void *opaque) { struct ll_inode_info *lli = ll_i2info(inode); diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index 1ef06fe..09474e7 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -224,7 +224,7 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt, GOTO(put_old, err = PTR_ERR(dchild_new)); err = ll_vfs_rename(dir->d_inode, dchild_old, mnt, - dir->d_inode, dchild_new, mnt); + dir->d_inode, dchild_new, mnt, NULL); dput(dchild_new); put_old: diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 44f24fa..36523ed 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -430,11 +430,6 @@ int ATOMIC_SUB_RETURN(ATOMIC_T *v, int i); int ATOMIC_INC_RETURN(ATOMIC_T *v); int ATOMIC_DEC_RETURN(ATOMIC_T *v); -/* File operation APIs, just for linux now */ -int rtw_is_file_readable(char *path); -int rtw_retrive_from_file(char *path, u8 __user *buf, u32 sz); -int rtw_store_to_file(char *path, u8 __user *buf, u32 sz); - struct rtw_netdev_priv_indicator { void *priv; u32 sizeof_priv; diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 5a9e9e4..a1ae727 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -356,214 +356,6 @@ inline int ATOMIC_DEC_RETURN(ATOMIC_T *v) return atomic_dec_return(v); } -/* Open a file with the specific @param path, @param flag, @param mode - * @param fpp the pointer of struct file pointer to get struct file pointer while file opening is success - * @param path the path of the file to open - * @param flag file operation flags, please refer to linux document - * @param mode please refer to linux document - * @return Linux specific error code - */ -static int openfile(struct file **fpp, char *path, int flag, int mode) -{ - struct file *fp; - - fp = filp_open(path, flag, mode); - if (IS_ERR(fp)) { - *fpp = NULL; - return PTR_ERR(fp); - } else { - *fpp = fp; - return 0; - } -} - -/* Close the file with the specific @param fp - * @param fp the pointer of struct file to close - * @return always 0 - */ -static int closefile(struct file *fp) -{ - filp_close(fp, NULL); - return 0; -} - -static int readfile(struct file *fp, char __user *buf, int len) -{ - int rlen = 0, sum = 0; - - if (!fp->f_op || !fp->f_op->read) - return -EPERM; - - while (sum < len) { - rlen = fp->f_op->read(fp, buf+sum, len-sum, &fp->f_pos); - if (rlen > 0) - sum += rlen; - else if (0 != rlen) - return rlen; - else - break; - } - return sum; -} - -static int writefile(struct file *fp, char __user *buf, int len) -{ - int wlen = 0, sum = 0; - - if (!fp->f_op || !fp->f_op->write) - return -EPERM; - - while (sum < len) { - wlen = fp->f_op->write(fp, buf+sum, len-sum, &fp->f_pos); - if (wlen > 0) - sum += wlen; - else if (0 != wlen) - return wlen; - else - break; - } - return sum; -} - -/* Test if the specifi @param path is a file and readable - * @param path the path of the file to test - * @return Linux specific error code - */ -static int isfilereadable(char *path) -{ - struct file *fp; - int ret = 0; - mm_segment_t oldfs; - char __user buf; - - fp = filp_open(path, O_RDONLY, 0); - if (IS_ERR(fp)) { - ret = PTR_ERR(fp); - } else { - oldfs = get_fs(); set_fs(get_ds()); - - if (1 != readfile(fp, &buf, 1)) - ret = PTR_ERR(fp); - - set_fs(oldfs); - filp_close(fp, NULL); - } - return ret; -} - -/* Open the file with @param path and retrive the file content into - * memory starting from @param buf for @param sz at most - * @param path the path of the file to open and read - * @param buf the starting address of the buffer to store file content - * @param sz how many bytes to read at most - * @return the byte we've read, or Linux specific error code - */ -static int retrievefromfile(char *path, u8 __user *buf, u32 sz) -{ - int ret = -1; - mm_segment_t oldfs; - struct file *fp; - - if (path && buf) { - ret = openfile(&fp, path, O_RDONLY, 0); - if (0 == ret) { - DBG_88E("%s openfile path:%s fp =%p\n", __func__, - path, fp); - - oldfs = get_fs(); set_fs(get_ds()); - ret = readfile(fp, buf, sz); - set_fs(oldfs); - closefile(fp); - - DBG_88E("%s readfile, ret:%d\n", __func__, ret); - - } else { - DBG_88E("%s openfile path:%s Fail, ret:%d\n", __func__, - path, ret); - } - } else { - DBG_88E("%s NULL pointer\n", __func__); - ret = -EINVAL; - } - return ret; -} - -/* -* Open the file with @param path and wirte @param sz byte of data starting from @param buf into the file -* @param path the path of the file to open and write -* @param buf the starting address of the data to write into file -* @param sz how many bytes to write at most -* @return the byte we've written, or Linux specific error code -*/ -static int storetofile(char *path, u8 __user *buf, u32 sz) -{ - int ret = 0; - mm_segment_t oldfs; - struct file *fp; - - if (path && buf) { - ret = openfile(&fp, path, O_CREAT|O_WRONLY, 0666); - if (0 == ret) { - DBG_88E("%s openfile path:%s fp =%p\n", __func__, path, fp); - - oldfs = get_fs(); set_fs(get_ds()); - ret = writefile(fp, buf, sz); - set_fs(oldfs); - closefile(fp); - - DBG_88E("%s writefile, ret:%d\n", __func__, ret); - - } else { - DBG_88E("%s openfile path:%s Fail, ret:%d\n", __func__, path, ret); - } - } else { - DBG_88E("%s NULL pointer\n", __func__); - ret = -EINVAL; - } - return ret; -} - -/* -* Test if the specifi @param path is a file and readable -* @param path the path of the file to test -* @return true or false -*/ -int rtw_is_file_readable(char *path) -{ - if (isfilereadable(path) == 0) - return true; - else - return false; -} - -/* -* Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most -* @param path the path of the file to open and read -* @param buf the starting address of the buffer to store file content -* @param sz how many bytes to read at most -* @return the byte we've read -*/ -int rtw_retrive_from_file(char *path, u8 __user *buf, u32 sz) -{ - int ret = retrievefromfile(path, buf, sz); - - return ret >= 0 ? ret : 0; -} - -/* - * Open the file with @param path and wirte @param sz byte of data - * starting from @param buf into the file - * @param path the path of the file to open and write - * @param buf the starting address of the data to write into file - * @param sz how many bytes to write at most - * @return the byte we've written - */ -int rtw_store_to_file(char *path, u8 __user *buf, u32 sz) -{ - int ret = storetofile(path, buf, sz); - return ret >= 0 ? ret : 0; -} - struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv) { diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 3bdfbf8..ea337a7 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -29,27 +29,19 @@ static DECLARE_RWSEM(minor_rwsem); static int usb_open(struct inode *inode, struct file *file) { - int minor = iminor(inode); - const struct file_operations *c; int err = -ENODEV; - const struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *new_fops; down_read(&minor_rwsem); - c = usb_minors[minor]; + new_fops = fops_get(usb_minors[iminor(inode)]); - if (!c || !(new_fops = fops_get(c))) + if (!new_fops) goto done; - old_fops = file->f_op; - file->f_op = new_fops; + replace_fops(file, new_fops); /* Curiouser and curiouser... NULL ->open() as "no device" ? */ if (file->f_op->open) err = file->f_op->open(inode, file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - fops_put(old_fops); done: up_read(&minor_rwsem); return err; |