Commit 7ad4b4ae authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-3.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver fixes from Greg KH:
 "Here are three small driver fixes for reported issues for 3.19-rc5.

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'char-misc-3.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  mcb: mcb-pci: Only remap the 1st 0x200 bytes of BAR 0
  mei: add ABI documentation for fw_status exported through sysfs
  mei: clean reset bit before reset
parents 62b15300 7b7c5491
...@@ -14,3 +14,18 @@ Description: ...@@ -14,3 +14,18 @@ Description:
The /sys/class/mei/meiN directory is created for The /sys/class/mei/meiN directory is created for
each probed mei device each probed mei device
What: /sys/class/mei/meiN/fw_status
Date: Nov 2014
KernelVersion: 3.19
Contact: Tomas Winkler <tomas.winkler@intel.com>
Description: Display fw status registers content
The ME FW writes its status information into fw status
registers for BIOS and OS to monitor fw health.
The register contains running state, power management
state, error codes, and others. The way the registers
are decoded depends on PCH or SoC generation.
Also number of registers varies between 1 and 6
depending on generation.
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45 #define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45
#define CHAMELEON_FILENAME_LEN 12 #define CHAMELEON_FILENAME_LEN 12
#define CHAMELEONV2_MAGIC 0xabce #define CHAMELEONV2_MAGIC 0xabce
#define CHAM_HEADER_SIZE 0x200
enum chameleon_descriptor_type { enum chameleon_descriptor_type {
CHAMELEON_DTYPE_GENERAL = 0x0, CHAMELEON_DTYPE_GENERAL = 0x0,
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
struct priv { struct priv {
struct mcb_bus *bus; struct mcb_bus *bus;
phys_addr_t mapbase;
void __iomem *base; void __iomem *base;
}; };
...@@ -31,8 +32,8 @@ static int mcb_pci_get_irq(struct mcb_device *mdev) ...@@ -31,8 +32,8 @@ static int mcb_pci_get_irq(struct mcb_device *mdev)
static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct resource *res;
struct priv *priv; struct priv *priv;
phys_addr_t mapbase;
int ret; int ret;
int num_cells; int num_cells;
unsigned long flags; unsigned long flags;
...@@ -47,19 +48,21 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -47,19 +48,21 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENODEV; return -ENODEV;
} }
mapbase = pci_resource_start(pdev, 0); priv->mapbase = pci_resource_start(pdev, 0);
if (!mapbase) { if (!priv->mapbase) {
dev_err(&pdev->dev, "No PCI resource\n"); dev_err(&pdev->dev, "No PCI resource\n");
goto err_start; goto err_start;
} }
ret = pci_request_region(pdev, 0, KBUILD_MODNAME); res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE,
if (ret) { KBUILD_MODNAME);
dev_err(&pdev->dev, "Failed to request PCI BARs\n"); if (IS_ERR(res)) {
dev_err(&pdev->dev, "Failed to request PCI memory\n");
ret = PTR_ERR(res);
goto err_start; goto err_start;
} }
priv->base = pci_iomap(pdev, 0, 0); priv->base = ioremap(priv->mapbase, CHAM_HEADER_SIZE);
if (!priv->base) { if (!priv->base) {
dev_err(&pdev->dev, "Cannot ioremap\n"); dev_err(&pdev->dev, "Cannot ioremap\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -84,7 +87,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -84,7 +87,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
priv->bus->get_irq = mcb_pci_get_irq; priv->bus->get_irq = mcb_pci_get_irq;
ret = chameleon_parse_cells(priv->bus, mapbase, priv->base); ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base);
if (ret < 0) if (ret < 0)
goto err_drvdata; goto err_drvdata;
num_cells = ret; num_cells = ret;
...@@ -93,8 +96,10 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -93,8 +96,10 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mcb_bus_add_devices(priv->bus); mcb_bus_add_devices(priv->bus);
return 0;
err_drvdata: err_drvdata:
pci_iounmap(pdev, priv->base); iounmap(priv->base);
err_ioremap: err_ioremap:
pci_release_region(pdev, 0); pci_release_region(pdev, 0);
err_start: err_start:
...@@ -107,6 +112,10 @@ static void mcb_pci_remove(struct pci_dev *pdev) ...@@ -107,6 +112,10 @@ static void mcb_pci_remove(struct pci_dev *pdev)
struct priv *priv = pci_get_drvdata(pdev); struct priv *priv = pci_get_drvdata(pdev);
mcb_release_bus(priv->bus); mcb_release_bus(priv->bus);
iounmap(priv->base);
release_region(priv->mapbase, CHAM_HEADER_SIZE);
pci_disable_device(pdev);
} }
static const struct pci_device_id mcb_pci_tbl[] = { static const struct pci_device_id mcb_pci_tbl[] = {
......
...@@ -234,6 +234,18 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) ...@@ -234,6 +234,18 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
struct mei_me_hw *hw = to_me_hw(dev); struct mei_me_hw *hw = to_me_hw(dev);
u32 hcsr = mei_hcsr_read(hw); u32 hcsr = mei_hcsr_read(hw);
/* H_RST may be found lit before reset is started,
* for example if preceding reset flow hasn't completed.
* In that case asserting H_RST will be ignored, therefore
* we need to clean H_RST bit to start a successful reset sequence.
*/
if ((hcsr & H_RST) == H_RST) {
dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
hcsr &= ~H_RST;
mei_me_reg_write(hw, H_CSR, hcsr);
hcsr = mei_hcsr_read(hw);
}
hcsr |= H_RST | H_IG | H_IS; hcsr |= H_RST | H_IG | H_IS;
if (intr_enable) if (intr_enable)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment