dect
/
linux-2.6
Archived
13
0
Fork 0

Char/Misc driver merge for 3.8-rc1

Here is the "big" char/misc driver patches for 3.8-rc1.  I'm starting to
 put random driver subsystems that I had previously sent you through the
 driver-core tree in this tree, as it makes more sense to do so.
 
 Nothing major here, the various __dev* removals, some mei driver
 updates, and other random driver-specific things from the different
 maintainers and developers.
 
 Note, some MFD drivers got added through this tree, and they are also
 coming in through the "real" MFD tree as well, due to some major
 mis-communication between me and the different developers.  If you have
 any merge conflicts, take the ones from the MFD tree, not these ones,
 sorry about that.
 
 All of this has been in linux-next for a while.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iEYEABECAAYFAlDHj7AACgkQMUfUDdst+ym7pQCgxhFDGQRJimG+Ddag+ghfLhQh
 Ql0AoJsWVFvQjb7q1NO7OvOABaxjEJdu
 =na5b
 -----END PGP SIGNATURE-----

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

Pull Char/Misc driver merge from Greg Kroah-Hartman:
 "Here is the "big" char/misc driver patches for 3.8-rc1.  I'm starting
  to put random driver subsystems that I had previously sent you through
  the driver-core tree in this tree, as it makes more sense to do so.

  Nothing major here, the various __dev* removals, some mei driver
  updates, and other random driver-specific things from the different
  maintainers and developers.

  Note, some MFD drivers got added through this tree, and they are also
  coming in through the "real" MFD tree as well, due to some major
  mis-communication between me and the different developers.  If you
  have any merge conflicts, take the ones from the MFD tree, not these
  ones, sorry about that.

  All of this has been in linux-next for a while.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

Fix up trivial conflict in drivers/mmc/host/Kconfig due to new drivers
having been added (both at the end, as usual..)

* tag 'char-misc-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (84 commits)
  MAINTAINERS: remove drivers/staging/hv/
  misc/st_kim: Free resources in the error path of probe()
  drivers/char: for hpet, add count checking, and ~0UL instead of -1
  w1-gpio: Simplify & get rid of defines
  w1-gpio: Pinctrl-fy
  extcon: remove use of __devexit_p
  extcon: remove use of __devinit
  extcon: remove use of __devexit
  drivers: uio: Only allocate new private data when probing device tree node
  drivers: uio_dmem_genirq: Allow partial success when opening device
  drivers: uio_dmem_genirq: Don't use DMA_ERROR_CODE to indicate unmapped regions
  drivers: uio_dmem_genirq: Don't mix address spaces for dynamic region vaddr
  uio: remove use of __devexit
  uio: remove use of __devinitdata
  uio: remove use of __devinit
  uio: remove use of __devexit_p
  char: remove use of __devexit
  char: remove use of __devinitconst
  char: remove use of __devinitdata
  char: remove use of __devinit
  ...
This commit is contained in:
Linus Torvalds 2012-12-11 13:56:38 -08:00
commit 6a5971d8fe
135 changed files with 8214 additions and 1864 deletions

View File

@ -719,6 +719,62 @@ framework to set up sysfs files for this region. Simply leave it alone.
</para>
</sect1>
<sect1 id="using uio_dmem_genirq">
<title>Using uio_dmem_genirq for platform devices</title>
<para>
In addition to statically allocated memory ranges, they may also be
a desire to use dynamically allocated regions in a user space driver.
In particular, being able to access memory made available through the
dma-mapping API, may be particularly useful. The
<varname>uio_dmem_genirq</varname> driver provides a way to accomplish
this.
</para>
<para>
This driver is used in a similar manner to the
<varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt
configuration and handling.
</para>
<para>
Set the <varname>.name</varname> element of
<varname>struct platform_device</varname> to
<varname>"uio_dmem_genirq"</varname> to use this driver.
</para>
<para>
When using this driver, fill in the <varname>.platform_data</varname>
element of <varname>struct platform_device</varname>, which is of type
<varname>struct uio_dmem_genirq_pdata</varname> and which contains the
following elements:
</para>
<itemizedlist>
<listitem><varname>struct uio_info uioinfo</varname>: The same
structure used as the <varname>uio_pdrv_genirq</varname> platform
data</listitem>
<listitem><varname>unsigned int *dynamic_region_sizes</varname>:
Pointer to list of sizes of dynamic memory regions to be mapped into
user space.
</listitem>
<listitem><varname>unsigned int num_dynamic_regions</varname>:
Number of elements in <varname>dynamic_region_sizes</varname> array.
</listitem>
</itemizedlist>
<para>
The dynamic regions defined in the platform data will be appended to
the <varname> mem[] </varname> array after the platform device
resources, which implies that the total number of static and dynamic
memory regions cannot exceed <varname>MAX_UIO_MAPS</varname>.
</para>
<para>
The dynamic memory regions will be allocated when the UIO device file,
<varname>/dev/uioX</varname> is opened.
Simiar to static memory resources, the memory region information for
dynamic regions is then visible via sysfs at
<varname>/sys/class/uio/uioX/maps/mapY/*</varname>.
The dynmaic memory regions will be freed when the UIO device file is
closed. When no processes are holding the device file open, the address
returned to userspace is ~0.
</para>
</sect1>
</chapter>
<chapter id="userspace_driver" xreflabel="Writing a driver in user space">

View File

@ -3596,7 +3596,6 @@ S: Maintained
F: drivers/hv/
F: drivers/hid/hid-hyperv.c
F: drivers/net/hyperv/
F: drivers/staging/hv/
I2C OVER PARALLEL PORT
M: Jean Delvare <khali@linux-fr.org>

View File

@ -374,7 +374,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
#ifdef CONFIG_MMU
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range(unsigned long addr, size_t size);
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
extern int devmem_is_allowed(unsigned long pfn);
#endif

View File

@ -279,7 +279,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
* You really shouldn't be using read() or write() on /dev/mem. This
* might go away in the future.
*/
int valid_phys_addr_range(unsigned long addr, size_t size)
int valid_phys_addr_range(phys_addr_t addr, size_t size)
{
if (addr < PHYS_OFFSET)
return 0;

View File

@ -90,7 +90,7 @@ phys_to_virt (unsigned long address)
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
extern int valid_phys_addr_range (phys_addr_t addr, size_t count); /* efi.c */
extern int valid_mmap_phys_addr_range (unsigned long pfn, size_t count);
/*

View File

@ -870,7 +870,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
EXPORT_SYMBOL(kern_mem_attribute);
int
valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
valid_phys_addr_range (phys_addr_t phys_addr, unsigned long size)
{
u64 attr;

View File

@ -382,7 +382,7 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
#define xlate_dev_kmem_ptr(p) p
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
int valid_phys_addr_range(unsigned long addr, size_t size);
int valid_phys_addr_range(phys_addr_t addr, size_t size);
int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
#endif /* __KERNEL__ */

View File

@ -238,7 +238,7 @@ bottomup:
* You really shouldn't be using read() or write() on /dev/mem. This
* might go away in the future.
*/
int valid_phys_addr_range(unsigned long addr, size_t count)
int valid_phys_addr_range(phys_addr_t addr, size_t count)
{
if (addr < __MEMORY_START)
return 0;

View File

@ -249,7 +249,7 @@ static const struct agp_bridge_driver ali_m1541_bridge = {
};
static struct agp_device_ids ali_agp_device_ids[] __devinitdata =
static struct agp_device_ids ali_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_AL_M1541,
@ -374,7 +374,7 @@ found:
return agp_add_bridge(bridge);
}
static void __devexit agp_ali_remove(struct pci_dev *pdev)
static void agp_ali_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -388,7 +388,7 @@ static const struct agp_bridge_driver amd_irongate_driver = {
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
static struct agp_device_ids amd_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006,
@ -480,7 +480,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
static void agp_amdk7_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -579,7 +579,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
return 0;
}
static void __devexit agp_amd64_remove(struct pci_dev *pdev)
static void agp_amd64_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -445,7 +445,7 @@ static const struct agp_bridge_driver ati_generic_bridge = {
};
static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
static struct agp_device_ids ati_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_ATI_RS100,
@ -533,7 +533,7 @@ found:
return agp_add_bridge(bridge);
}
static void __devexit agp_ati_remove(struct pci_dev *pdev)
static void agp_ati_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -407,7 +407,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
static void agp_efficeon_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -611,7 +611,7 @@ static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
static void agp_intel_i460_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -819,7 +819,7 @@ found_gmch:
return err;
}
static void __devexit agp_intel_remove(struct pci_dev *pdev)
static void agp_intel_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -388,7 +388,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
static void agp_nvidia_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -327,7 +327,7 @@ static int __devinit agp_sgi_init(void)
return 0;
}
static void __devexit agp_sgi_cleanup(void)
static void agp_sgi_cleanup(void)
{
kfree(sgi_tioca_agp_bridges);
sgi_tioca_agp_bridges = NULL;

View File

@ -17,8 +17,8 @@
#define PCI_DEVICE_ID_SI_662 0x0662
#define PCI_DEVICE_ID_SI_671 0x0671
static bool __devinitdata agp_sis_force_delay = 0;
static int __devinitdata agp_sis_agp_spec = -1;
static bool agp_sis_force_delay = 0;
static int agp_sis_agp_spec = -1;
static int sis_fetch_size(void)
{
@ -148,7 +148,7 @@ static struct agp_bridge_driver sis_driver = {
};
// chipsets that require the 'delay hack'
static int sis_broken_chipsets[] __devinitdata = {
static int sis_broken_chipsets[] = {
PCI_DEVICE_ID_SI_648,
PCI_DEVICE_ID_SI_746,
0 // terminator
@ -211,7 +211,7 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_sis_remove(struct pci_dev *pdev)
static void agp_sis_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -518,7 +518,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
static void agp_serverworks_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -557,7 +557,7 @@ const struct agp_bridge_driver u3_agp_driver = {
.needs_scratch_page = true,
};
static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
static struct agp_device_ids uninorth_agp_device_ids[] = {
{
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
.chipset_name = "UniNorth",
@ -663,7 +663,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_uninorth_remove(struct pci_dev *pdev)
static void agp_uninorth_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -224,7 +224,7 @@ static const struct agp_bridge_driver via_driver = {
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
static struct agp_device_ids via_agp_device_ids[] __devinitdata =
static struct agp_device_ids via_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_VIA_82C597_0,
@ -485,7 +485,7 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
static void __devexit agp_via_remove(struct pci_dev *pdev)
static void agp_via_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);

View File

@ -816,7 +816,7 @@ static unsigned long __hpet_calibrate(struct hpets *hpetp)
static unsigned long hpet_calibrate(struct hpets *hpetp)
{
unsigned long ret = -1;
unsigned long ret = ~0UL;
unsigned long tmp;
/*
@ -1001,6 +1001,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
irqp = &res->data.extended_irq;
for (i = 0; i < irqp->interrupt_count; i++) {
if (hdp->hd_nirqs >= HPET_MAX_TIMERS)
break;
irq = acpi_register_gsi(NULL, irqp->interrupts[i],
irqp->triggering, irqp->polarity);
if (irq < 0)

View File

@ -98,7 +98,7 @@ err_enable:
return ret;
}
static int __devexit atmel_trng_remove(struct platform_device *pdev)
static int atmel_trng_remove(struct platform_device *pdev)
{
struct atmel_trng *trng = platform_get_drvdata(pdev);

View File

@ -145,7 +145,7 @@ out:
return ret;
}
static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
static int bcm63xx_rng_remove(struct platform_device *pdev)
{
struct hwrng *rng = platform_get_drvdata(pdev);
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);

View File

@ -134,7 +134,7 @@ static int __devinit exynos_rng_probe(struct platform_device *pdev)
return hwrng_register(&exynos_rng->rng);
}
static int __devexit exynos_rng_remove(struct platform_device *pdev)
static int exynos_rng_remove(struct platform_device *pdev)
{
struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);

View File

@ -25,7 +25,7 @@
#define DRV_MODULE_VERSION "0.2"
#define DRV_MODULE_RELDATE "July 27, 2011"
static char version[] __devinitdata =
static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
@ -719,7 +719,7 @@ out:
return err;
}
static int __devexit n2rng_remove(struct platform_device *op)
static int n2rng_remove(struct platform_device *op)
{
struct n2rng *np = dev_get_drvdata(&op->dev);

View File

@ -122,7 +122,7 @@ static int __devinit rng_probe(struct platform_device *ofdev)
return err;
}
static int __devexit rng_remove(struct platform_device *dev)
static int rng_remove(struct platform_device *dev)
{
void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;

View File

@ -151,7 +151,7 @@ err_enable:
return ret;
}
static int __devexit picoxcell_trng_remove(struct platform_device *pdev)
static int picoxcell_trng_remove(struct platform_device *pdev)
{
hwrng_unregister(&picoxcell_trng);
clk_disable(rng_clk);

View File

@ -111,7 +111,7 @@ static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
return err;
}
static int __devexit ppc4xx_rng_remove(struct platform_device *dev)
static int ppc4xx_rng_remove(struct platform_device *dev)
{
void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;

View File

@ -130,7 +130,7 @@ failed:
return ret;
}
static int __devexit timeriomem_rng_remove(struct platform_device *pdev)
static int timeriomem_rng_remove(struct platform_device *pdev)
{
del_timer_sync(&timeriomem_rng_timer);
hwrng_unregister(&timeriomem_rng_ops);

View File

@ -119,7 +119,7 @@ static int virtrng_probe(struct virtio_device *vdev)
return probe_common(vdev);
}
static void __devexit virtrng_remove(struct virtio_device *vdev)
static void virtrng_remove(struct virtio_device *vdev)
{
remove_common(vdev);
}

View File

@ -1836,7 +1836,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
return rv;
}
static int __devinit hardcode_find_bmc(void)
static int hardcode_find_bmc(void)
{
int ret = -ENODEV;
int i;
@ -2023,7 +2023,7 @@ struct SPMITable {
s8 spmi_id[1]; /* A '\0' terminated array starts here. */
};
static int __devinit try_init_spmi(struct SPMITable *spmi)
static int try_init_spmi(struct SPMITable *spmi)
{
struct smi_info *info;
@ -2106,7 +2106,7 @@ static int __devinit try_init_spmi(struct SPMITable *spmi)
return 0;
}
static void __devinit spmi_find_bmc(void)
static void spmi_find_bmc(void)
{
acpi_status status;
struct SPMITable *spmi;
@ -2128,7 +2128,7 @@ static void __devinit spmi_find_bmc(void)
}
}
static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
static int ipmi_pnp_probe(struct pnp_dev *dev,
const struct pnp_device_id *dev_id)
{
struct acpi_device *acpi_dev;
@ -2228,7 +2228,7 @@ err_free:
return -EINVAL;
}
static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
static void ipmi_pnp_remove(struct pnp_dev *dev)
{
struct smi_info *info = pnp_get_drvdata(dev);
@ -2258,7 +2258,7 @@ struct dmi_ipmi_data {
u8 slave_addr;
};
static int __devinit decode_dmi(const struct dmi_header *dm,
static int decode_dmi(const struct dmi_header *dm,
struct dmi_ipmi_data *dmi)
{
const u8 *data = (const u8 *)dm;
@ -2320,7 +2320,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
return 0;
}
static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
{
struct smi_info *info;
@ -2388,7 +2388,7 @@ static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
kfree(info);
}
static void __devinit dmi_find_bmc(void)
static void dmi_find_bmc(void)
{
const struct dmi_device *dev = NULL;
struct dmi_ipmi_data data;
@ -2424,7 +2424,7 @@ static void ipmi_pci_cleanup(struct smi_info *info)
pci_disable_device(pdev);
}
static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
static int ipmi_pci_probe_regspacing(struct smi_info *info)
{
if (info->si_type == SI_KCS) {
unsigned char status;
@ -2456,7 +2456,7 @@ static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
return DEFAULT_REGSPACING;
}
static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
static int ipmi_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int rv;
@ -2529,7 +2529,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
return 0;
}
static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
static void ipmi_pci_remove(struct pci_dev *pdev)
{
struct smi_info *info = pci_get_drvdata(pdev);
cleanup_one_si(info);
@ -2551,7 +2551,7 @@ static struct pci_driver ipmi_pci_driver = {
#endif /* CONFIG_PCI */
static struct of_device_id ipmi_match[];
static int __devinit ipmi_probe(struct platform_device *dev)
static int ipmi_probe(struct platform_device *dev)
{
#ifdef CONFIG_OF
const struct of_device_id *match;
@ -2635,7 +2635,7 @@ static int __devinit ipmi_probe(struct platform_device *dev)
return 0;
}
static int __devexit ipmi_remove(struct platform_device *dev)
static int ipmi_remove(struct platform_device *dev)
{
#ifdef CONFIG_OF
cleanup_one_si(dev_get_drvdata(&dev->dev));
@ -3047,7 +3047,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
}
}
static __devinitdata struct ipmi_default_vals
static struct ipmi_default_vals
{
int type;
int port;
@ -3059,7 +3059,7 @@ static __devinitdata struct ipmi_default_vals
{ .port = 0 }
};
static void __devinit default_find_bmc(void)
static void default_find_bmc(void)
{
struct smi_info *info;
int i;
@ -3359,7 +3359,7 @@ static int try_smi_init(struct smi_info *new_smi)
return rv;
}
static int __devinit init_ipmi_si(void)
static int init_ipmi_si(void)
{
int i;
char *str;

View File

@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev)
return 0;
}
static const struct cx_device_id __devinitconst mbcs_id_table[] = {
static const struct cx_device_id mbcs_id_table[] = {
{
.part_num = MBCS_PART_NUM,
.mfg_num = MBCS_MFG_NUM,

View File

@ -48,7 +48,7 @@ static inline unsigned long size_inside_page(unsigned long start,
}
#ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
static inline int valid_phys_addr_range(unsigned long addr, size_t count)
static inline int valid_phys_addr_range(phys_addr_t addr, size_t count)
{
return addr + count <= __pa(high_memory);
}
@ -96,7 +96,7 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
static ssize_t read_mem(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
phys_addr_t p = *ppos;
ssize_t read, sz;
char *ptr;
@ -153,7 +153,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
static ssize_t write_mem(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
phys_addr_t p = *ppos;
ssize_t written, sz;
unsigned long copied;
void *ptr;
@ -226,7 +226,7 @@ int __weak phys_mem_access_prot_allowed(struct file *file,
*
*/
#ifdef pgprot_noncached
static int uncached_access(struct file *file, unsigned long addr)
static int uncached_access(struct file *file, phys_addr_t addr)
{
#if defined(CONFIG_IA64)
/*
@ -258,7 +258,7 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot)
{
#ifdef pgprot_noncached
unsigned long offset = pfn << PAGE_SHIFT;
phys_addr_t offset = pfn << PAGE_SHIFT;
if (uncached_access(file, offset))
return pgprot_noncached(vma_prot);

View File

@ -345,8 +345,7 @@ static void __exit pc8736x_gpio_cleanup(void)
unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT);
release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
platform_device_del(pdev);
platform_device_put(pdev);
platform_device_unregister(pdev);
}
module_init(pc8736x_gpio_init);

View File

@ -363,7 +363,7 @@ static struct miscdevice ps3flash_misc = {
.fops = &ps3flash_fops,
};
static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
static int ps3flash_probe(struct ps3_system_bus_device *_dev)
{
struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
struct ps3flash_private *priv;

View File

@ -1164,7 +1164,7 @@ static struct acpi_driver sonypi_acpi_driver = {
};
#endif
static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
static int sonypi_create_input_devices(struct platform_device *pdev)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
@ -1225,7 +1225,7 @@ static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
return error;
}
static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
static int sonypi_setup_ioports(struct sonypi_device *dev,
const struct sonypi_ioport_list *ioport_list)
{
/* try to detect if sony-laptop is being used and thus
@ -1265,7 +1265,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
return -EBUSY;
}
static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
static int sonypi_setup_irq(struct sonypi_device *dev,
const struct sonypi_irq_list *irq_list)
{
while (irq_list->irq) {
@ -1282,7 +1282,7 @@ static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
return -EBUSY;
}
static void __devinit sonypi_display_info(void)
static void sonypi_display_info(void)
{
printk(KERN_INFO "sonypi: detected type%d model, "
"verbose = %d, fnkeyinit = %s, camera = %s, "
@ -1304,7 +1304,7 @@ static void __devinit sonypi_display_info(void)
sonypi_misc_device.minor);
}
static int __devinit sonypi_probe(struct platform_device *dev)
static int sonypi_probe(struct platform_device *dev)
{
const struct sonypi_ioport_list *ioport_list;
const struct sonypi_irq_list *irq_list;
@ -1428,7 +1428,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
return error;
}
static int __devexit sonypi_remove(struct platform_device *dev)
static int sonypi_remove(struct platform_device *dev)
{
sonypi_disable();
@ -1491,7 +1491,7 @@ static struct platform_driver sonypi_driver = {
.pm = SONYPI_PM,
},
.probe = sonypi_probe,
.remove = __devexit_p(sonypi_remove),
.remove = sonypi_remove,
.shutdown = sonypi_shutdown,
};

View File

@ -284,7 +284,7 @@ static void tb0219_pci_irq_init(void)
vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
}
static int __devinit tb0219_probe(struct platform_device *dev)
static int tb0219_probe(struct platform_device *dev)
{
int retval;
@ -318,7 +318,7 @@ static int __devinit tb0219_probe(struct platform_device *dev)
return 0;
}
static int __devexit tb0219_remove(struct platform_device *dev)
static int tb0219_remove(struct platform_device *dev)
{
_machine_restart = old_machine_restart;
@ -334,7 +334,7 @@ static struct platform_device *tb0219_platform_device;
static struct platform_driver tb0219_device_driver = {
.probe = tb0219_probe,
.remove = __devexit_p(tb0219_remove),
.remove = tb0219_remove,
.driver = {
.name = "TB0219",
.owner = THIS_MODULE,

View File

@ -656,7 +656,7 @@ static int tpm_tis_i2c_probe(struct i2c_client *client,
return rc;
}
static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
static int tpm_tis_i2c_remove(struct i2c_client *client)
{
struct tpm_chip *chip = tpm_dev.chip;
release_locality(chip, chip->vendor.locality, 1);

View File

@ -32,7 +32,7 @@
static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
static struct vio_device_id tpm_ibmvtpm_device_table[] = {
{ "IBM,vtpm", "IBM,vtpm"},
{ "", "" }
};
@ -267,7 +267,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
* Return value:
* 0
*/
static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
{
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
int rc = 0;

View File

@ -594,7 +594,7 @@ err_last:
return rc;
}
static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
static void tpm_inf_pnp_remove(struct pnp_dev *dev)
{
struct tpm_chip *chip = pnp_get_drvdata(dev);

View File

@ -769,7 +769,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
return ret;
}
static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
static struct pnp_device_id tpm_pnp_tbl[] = {
{"PNP0C31", 0}, /* TPM */
{"ATM1200", 0}, /* Atmel */
{"IFX0102", 0}, /* Infineon */
@ -783,7 +783,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
static void tpm_tis_pnp_remove(struct pnp_dev *dev)
{
struct tpm_chip *chip = pnp_get_drvdata(dev);

View File

@ -1846,7 +1846,7 @@ static void remove_controlq_data(struct ports_device *portdev)
* config space to see how many ports the host has spawned. We
* initialize each port found.
*/
static int __devinit virtcons_probe(struct virtio_device *vdev)
static int virtcons_probe(struct virtio_device *vdev)
{
struct ports_device *portdev;
int err;

View File

@ -595,7 +595,7 @@ static const struct file_operations hwicap_fops = {
.llseek = noop_llseek,
};
static int __devinit hwicap_setup(struct device *dev, int id,
static int hwicap_setup(struct device *dev, int id,
const struct resource *regs_res,
const struct hwicap_driver_config *config,
const struct config_registers *config_regs)
@ -717,7 +717,7 @@ static struct hwicap_driver_config fifo_icap_config = {
.reset = fifo_icap_reset,
};
static int __devexit hwicap_remove(struct device *dev)
static int hwicap_remove(struct device *dev)
{
struct hwicap_drvdata *drvdata;
@ -740,7 +740,7 @@ static int __devexit hwicap_remove(struct device *dev)
}
#ifdef CONFIG_OF
static int __devinit hwicap_of_probe(struct platform_device *op,
static int hwicap_of_probe(struct platform_device *op,
const struct hwicap_driver_config *config)
{
struct resource res;
@ -785,8 +785,8 @@ static inline int hwicap_of_probe(struct platform_device *op,
}
#endif /* CONFIG_OF */
static const struct of_device_id __devinitconst hwicap_of_match[];
static int __devinit hwicap_drv_probe(struct platform_device *pdev)
static const struct of_device_id hwicap_of_match[];
static int hwicap_drv_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct resource *res;
@ -822,14 +822,14 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev)
&buffer_icap_config, regs);
}
static int __devexit hwicap_drv_remove(struct platform_device *pdev)
static int hwicap_drv_remove(struct platform_device *pdev)
{
return hwicap_remove(&pdev->dev);
}
#ifdef CONFIG_OF
/* Match table for device tree binding */
static const struct of_device_id __devinitconst hwicap_of_match[] = {
static const struct of_device_id hwicap_of_match[] = {
{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
{},

View File

@ -91,7 +91,7 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
return IRQ_HANDLED;
}
static int __devinit adc_jack_probe(struct platform_device *pdev)
static int adc_jack_probe(struct platform_device *pdev)
{
struct adc_jack_data *data;
struct adc_jack_pdata *pdata = pdev->dev.platform_data;
@ -175,7 +175,7 @@ out:
return err;
}
static int __devexit adc_jack_remove(struct platform_device *pdev)
static int adc_jack_remove(struct platform_device *pdev)
{
struct adc_jack_data *data = platform_get_drvdata(pdev);
@ -188,7 +188,7 @@ static int __devexit adc_jack_remove(struct platform_device *pdev)
static struct platform_driver adc_jack_driver = {
.probe = adc_jack_probe,
.remove = __devexit_p(adc_jack_remove),
.remove = adc_jack_remove,
.driver = {
.name = "adc-jack",
.owner = THIS_MODULE,

View File

@ -337,7 +337,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
return IRQ_HANDLED;
}
static int __devinit arizona_extcon_probe(struct platform_device *pdev)
static int arizona_extcon_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata;
@ -517,7 +517,7 @@ err:
return ret;
}
static int __devexit arizona_extcon_remove(struct platform_device *pdev)
static int arizona_extcon_remove(struct platform_device *pdev)
{
struct arizona_extcon_info *info = platform_get_drvdata(pdev);
struct arizona *arizona = info->arizona;
@ -544,7 +544,7 @@ static struct platform_driver arizona_extcon_driver = {
.owner = THIS_MODULE,
},
.probe = arizona_extcon_probe,
.remove = __devexit_p(arizona_extcon_remove),
.remove = arizona_extcon_remove,
};
module_platform_driver(arizona_extcon_driver);

View File

@ -76,7 +76,7 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
return -EINVAL;
}
static int __devinit gpio_extcon_probe(struct platform_device *pdev)
static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
struct gpio_extcon_data *extcon_data;
@ -137,7 +137,7 @@ err:
return ret;
}
static int __devexit gpio_extcon_remove(struct platform_device *pdev)
static int gpio_extcon_remove(struct platform_device *pdev)
{
struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
@ -150,7 +150,7 @@ static int __devexit gpio_extcon_remove(struct platform_device *pdev)
static struct platform_driver gpio_extcon_driver = {
.probe = gpio_extcon_probe,
.remove = __devexit_p(gpio_extcon_remove),
.remove = gpio_extcon_remove,
.driver = {
.name = "extcon-gpio",
.owner = THIS_MODULE,

View File

@ -648,7 +648,7 @@ out:
return ret;
}
static int __devinit max77693_muic_probe(struct platform_device *pdev)
static int max77693_muic_probe(struct platform_device *pdev)
{
struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
@ -774,7 +774,7 @@ err_kfree:
return ret;
}
static int __devexit max77693_muic_remove(struct platform_device *pdev)
static int max77693_muic_remove(struct platform_device *pdev)
{
struct max77693_muic_info *info = platform_get_drvdata(pdev);
int i;
@ -795,7 +795,7 @@ static struct platform_driver max77693_muic_driver = {
.owner = THIS_MODULE,
},
.probe = max77693_muic_probe,
.remove = __devexit_p(max77693_muic_remove),
.remove = max77693_muic_remove,
};
module_platform_driver(max77693_muic_driver);

View File

@ -426,7 +426,7 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info)
max8997_muic_handle_charger_type(info, chg_type);
}
static int __devinit max8997_muic_probe(struct platform_device *pdev)
static int max8997_muic_probe(struct platform_device *pdev)
{
struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
@ -508,7 +508,7 @@ err_kfree:
return ret;
}
static int __devexit max8997_muic_remove(struct platform_device *pdev)
static int max8997_muic_remove(struct platform_device *pdev)
{
struct max8997_muic_info *info = platform_get_drvdata(pdev);
int i;
@ -531,7 +531,7 @@ static struct platform_driver max8997_muic_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_muic_probe,
.remove = __devexit_p(max8997_muic_remove),
.remove = max8997_muic_remove,
};
module_platform_driver(max8997_muic_driver);

View File

@ -13,4 +13,10 @@ config HYPERV_UTILS
help
Select this option to enable the Hyper-V Utilities.
config HYPERV_BALLOON
tristate "Microsoft Hyper-V Balloon driver"
depends on HYPERV
help
Select this option to enable Hyper-V Balloon driver.
endmenu

View File

@ -1,5 +1,6 @@
obj-$(CONFIG_HYPERV) += hv_vmbus.o
obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o
obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o
hv_vmbus-y := vmbus_drv.o \
hv.o connection.o channel.o \

View File

@ -33,14 +33,6 @@
#define NUM_PAGES_SPANNED(addr, len) \
((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
/* Internal routines */
static int create_gpadl_header(
void *kbuffer, /* must be phys and virt contiguous */
u32 size, /* page-size multiple */
struct vmbus_channel_msginfo **msginfo,
u32 *messagecount);
static void vmbus_setevent(struct vmbus_channel *channel);
/*
* vmbus_setevent- Trigger an event notification on the specified
* channel.

View File

@ -265,14 +265,9 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
{
struct vmbus_channel_offer_channel *offer;
struct vmbus_channel *newchannel;
uuid_le *guidtype;
uuid_le *guidinstance;
offer = (struct vmbus_channel_offer_channel *)hdr;
guidtype = &offer->offer.if_type;
guidinstance = &offer->offer.if_instance;
/* Allocate the channel object and save this offer. */
newchannel = alloc_channel();
if (!newchannel) {
@ -470,7 +465,6 @@ static void vmbus_onversion_response(
{
struct vmbus_channel_msginfo *msginfo;
struct vmbus_channel_message_header *requestheader;
struct vmbus_channel_initiate_contact *initiate;
struct vmbus_channel_version_response *version_response;
unsigned long flags;
@ -484,8 +478,6 @@ static void vmbus_onversion_response(
if (requestheader->msgtype ==
CHANNELMSG_INITIATE_CONTACT) {
initiate =
(struct vmbus_channel_initiate_contact *)requestheader;
memcpy(&msginfo->response.version_response,
version_response,
sizeof(struct vmbus_channel_version_response));

1041
drivers/hv/hv_balloon.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -42,3 +42,13 @@ config MEMSTICK_R592
To compile this driver as a module, choose M here: the module will
be called r592.
config MEMSTICK_REALTEK_PCI
tristate "Realtek PCI-E Memstick Card Interface Driver"
depends on MFD_RTSX_PCI
help
Say Y here to include driver code to support Memstick card interface
of Realtek PCI-E card reader
To compile this driver as a module, choose M here: the module will
be called rtsx_pci_ms.

View File

@ -5,3 +5,4 @@
obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o
obj-$(CONFIG_MEMSTICK_R592) += r592.o
obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o

View File

@ -0,0 +1,641 @@
/* Realtek PCI-Express Memstick Card Interface driver
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Wei WANG <wei_wang@realsil.com.cn>
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/memstick.h>
#include <linux/mfd/rtsx_pci.h>
#include <asm/unaligned.h>
struct realtek_pci_ms {
struct platform_device *pdev;
struct rtsx_pcr *pcr;
struct memstick_host *msh;
struct memstick_request *req;
struct mutex host_mutex;
struct work_struct handle_req;
u8 ssc_depth;
unsigned int clock;
unsigned char ifmode;
bool eject;
};
static inline struct device *ms_dev(struct realtek_pci_ms *host)
{
return &(host->pdev->dev);
}
static inline void ms_clear_error(struct realtek_pci_ms *host)
{
rtsx_pci_write_register(host->pcr, CARD_STOP,
MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
}
#ifdef DEBUG
static void ms_print_debug_regs(struct realtek_pci_ms *host)
{
struct rtsx_pcr *pcr = host->pcr;
u16 i;
u8 *ptr;
/* Print MS host internal registers */
rtsx_pci_init_cmd(pcr);
for (i = 0xFD40; i <= 0xFD44; i++)
rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
for (i = 0xFD52; i <= 0xFD69; i++)
rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
rtsx_pci_send_cmd(pcr, 100);
ptr = rtsx_pci_get_cmd_data(pcr);
for (i = 0xFD40; i <= 0xFD44; i++)
dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
for (i = 0xFD52; i <= 0xFD69; i++)
dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
}
#else
#define ms_print_debug_regs(host)
#endif
static int ms_power_on(struct realtek_pci_ms *host)
{
struct rtsx_pcr *pcr = host->pcr;
int err;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
CARD_SHARE_MASK, CARD_SHARE_48_MS);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
MS_CLK_EN, MS_CLK_EN);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
if (err < 0)
return err;
err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
if (err < 0)
return err;
/* Wait ms power stable */
msleep(150);
err = rtsx_pci_write_register(pcr, CARD_OE,
MS_OUTPUT_EN, MS_OUTPUT_EN);
if (err < 0)
return err;
return 0;
}
static int ms_power_off(struct realtek_pci_ms *host)
{
struct rtsx_pcr *pcr = host->pcr;
int err;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
if (err < 0)
return err;
return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
}
static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
u8 tpc, u8 cfg, struct scatterlist *sg)
{
struct rtsx_pcr *pcr = host->pcr;
int err;
unsigned int length = sg->length;
u16 sec_cnt = (u16)(length / 512);
u8 val, trans_mode, dma_dir;
dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
__func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
length);
if (data_dir == READ) {
dma_dir = DMA_DIR_FROM_CARD;
trans_mode = MS_TM_AUTO_READ;
} else {
dma_dir = DMA_DIR_TO_CARD;
trans_mode = MS_TM_AUTO_WRITE;
}
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
0xFF, (u8)(sec_cnt >> 8));
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
0xFF, (u8)sec_cnt);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
DMA_DONE_INT, DMA_DONE_INT);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
0x01, RING_BUFFER);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
0xFF, MS_TRANSFER_START | trans_mode);
rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
MS_TRANSFER_END, MS_TRANSFER_END);
rtsx_pci_send_cmd_no_wait(pcr);
err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000);
if (err < 0) {
ms_clear_error(host);
return err;
}
rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
return -EIO;
return 0;
}
static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc,
u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
{
struct rtsx_pcr *pcr = host->pcr;
int err, i;
dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
if (!data)
return -EINVAL;
rtsx_pci_init_cmd(pcr);
for (i = 0; i < cnt; i++)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
PPBUF_BASE2 + i, 0xFF, data[i]);
if (cnt % 2)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
PPBUF_BASE2 + i, 0xFF, 0xFF);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
0x01, PINGPONG_BUFFER);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
MS_TRANSFER_END, MS_TRANSFER_END);
if (int_reg)
rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
err = rtsx_pci_send_cmd(pcr, 5000);
if (err < 0) {
u8 val;
rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
if (int_reg)
*int_reg = val & 0x0F;
ms_print_debug_regs(host);
ms_clear_error(host);
if (!(tpc & 0x08)) {
if (val & MS_CRC16_ERR)
return -EIO;
} else {
if (!(val & 0x80)) {
if (val & (MS_INT_ERR | MS_INT_CMDNK))
return -EIO;
}
}
return -ETIMEDOUT;
}
if (int_reg) {
u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1;
*int_reg = *ptr & 0x0F;
}
return 0;
}
static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc,
u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
{
struct rtsx_pcr *pcr = host->pcr;
int err, i;
u8 *ptr;
dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
if (!data)
return -EINVAL;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
0x01, PINGPONG_BUFFER);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
MS_TRANSFER_END, MS_TRANSFER_END);
for (i = 0; i < cnt - 1; i++)
rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
if (cnt % 2)
rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
else
rtsx_pci_add_cmd(pcr, READ_REG_CMD,
PPBUF_BASE2 + cnt - 1, 0, 0);
if (int_reg)
rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
err = rtsx_pci_send_cmd(pcr, 5000);
if (err < 0) {
u8 val;
rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
if (int_reg)
*int_reg = val & 0x0F;
ms_print_debug_regs(host);
ms_clear_error(host);
if (!(tpc & 0x08)) {
if (val & MS_CRC16_ERR)
return -EIO;
} else {
if (!(val & 0x80)) {
if (val & (MS_INT_ERR | MS_INT_CMDNK))
return -EIO;
}
}
return -ETIMEDOUT;
}
ptr = rtsx_pci_get_cmd_data(pcr) + 1;
for (i = 0; i < cnt; i++)
data[i] = *ptr++;
if (int_reg)
*int_reg = *ptr & 0x0F;
return 0;
}
static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host)
{
struct memstick_request *req = host->req;
int err = 0;
u8 cfg = 0, int_reg;
dev_dbg(ms_dev(host), "%s\n", __func__);
if (req->need_card_int) {
if (host->ifmode != MEMSTICK_SERIAL)
cfg = WAIT_INT;
}
if (req->long_data) {
err = ms_transfer_data(host, req->data_dir,
req->tpc, cfg, &(req->sg));
} else {
if (req->data_dir == READ) {
err = ms_read_bytes(host, req->tpc, cfg,
req->data_len, req->data, &int_reg);
} else {
err = ms_write_bytes(host, req->tpc, cfg,
req->data_len, req->data, &int_reg);
}
}
if (err < 0)
return err;
if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) {
err = ms_read_bytes(host, MS_TPC_GET_INT,
NO_WAIT_INT, 1, &int_reg, NULL);
if (err < 0)
return err;
}
if (req->need_card_int) {
dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg);
if (int_reg & MS_INT_CMDNK)
req->int_reg |= MEMSTICK_INT_CMDNAK;
if (int_reg & MS_INT_BREQ)
req->int_reg |= MEMSTICK_INT_BREQ;
if (int_reg & MS_INT_ERR)
req->int_reg |= MEMSTICK_INT_ERR;
if (int_reg & MS_INT_CED)
req->int_reg |= MEMSTICK_INT_CED;
}
return 0;
}
static void rtsx_pci_ms_handle_req(struct work_struct *work)
{
struct realtek_pci_ms *host = container_of(work,
struct realtek_pci_ms, handle_req);
struct rtsx_pcr *pcr = host->pcr;
struct memstick_host *msh = host->msh;
int rc;
mutex_lock(&pcr->pcr_mutex);
rtsx_pci_start_run(pcr);
rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth,
false, true, false);
rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL);
rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
CARD_SHARE_MASK, CARD_SHARE_48_MS);
if (!host->req) {
do {
rc = memstick_next_req(msh, &host->req);
dev_dbg(ms_dev(host), "next req %d\n", rc);
if (!rc)
host->req->error = rtsx_pci_ms_issue_cmd(host);
} while (!rc);
}
mutex_unlock(&pcr->pcr_mutex);
}
static void rtsx_pci_ms_request(struct memstick_host *msh)
{
struct realtek_pci_ms *host = memstick_priv(msh);
dev_dbg(ms_dev(host), "--> %s\n", __func__);
schedule_work(&host->handle_req);
}
static int rtsx_pci_ms_set_param(struct memstick_host *msh,
enum memstick_param param, int value)
{
struct realtek_pci_ms *host = memstick_priv(msh);
struct rtsx_pcr *pcr = host->pcr;
unsigned int clock = 0;
u8 ssc_depth = 0;
int err;
dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
__func__, param, value);
switch (param) {
case MEMSTICK_POWER:
if (value == MEMSTICK_POWER_ON)
err = ms_power_on(host);
else if (value == MEMSTICK_POWER_OFF)
err = ms_power_off(host);
else
return -EINVAL;
break;
case MEMSTICK_INTERFACE:
if (value == MEMSTICK_SERIAL) {
clock = 19000000;
ssc_depth = RTSX_SSC_DEPTH_500K;
err = rtsx_pci_write_register(pcr, MS_CFG,
0x18, MS_BUS_WIDTH_1);
if (err < 0)
return err;
} else if (value == MEMSTICK_PAR4) {
clock = 39000000;
ssc_depth = RTSX_SSC_DEPTH_1M;
err = rtsx_pci_write_register(pcr, MS_CFG,
0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
if (err < 0)
return err;
} else {
return -EINVAL;
}
err = rtsx_pci_switch_clock(pcr, clock,
ssc_depth, false, true, false);
if (err < 0)
return err;
host->ssc_depth = ssc_depth;
host->clock = clock;
host->ifmode = value;
break;
}
return 0;
}
#ifdef CONFIG_PM
static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
{
struct realtek_pci_ms *host = platform_get_drvdata(pdev);
struct memstick_host *msh = host->msh;
dev_dbg(ms_dev(host), "--> %s\n", __func__);
memstick_suspend_host(msh);
return 0;
}
static int rtsx_pci_ms_resume(struct platform_device *pdev)
{
struct realtek_pci_ms *host = platform_get_drvdata(pdev);
struct memstick_host *msh = host->msh;
dev_dbg(ms_dev(host), "--> %s\n", __func__);
memstick_resume_host(msh);
return 0;
}
#else /* CONFIG_PM */
#define rtsx_pci_ms_suspend NULL
#define rtsx_pci_ms_resume NULL
#endif /* CONFIG_PM */
static void rtsx_pci_ms_card_event(struct platform_device *pdev)
{
struct realtek_pci_ms *host = platform_get_drvdata(pdev);
memstick_detect_change(host->msh);
}
static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
{
struct memstick_host *msh;
struct realtek_pci_ms *host;
struct rtsx_pcr *pcr;
struct pcr_handle *handle = pdev->dev.platform_data;
int rc;
if (!handle)
return -ENXIO;
pcr = handle->pcr;
if (!pcr)
return -ENXIO;
dev_dbg(&(pdev->dev),
": Realtek PCI-E Memstick controller found\n");
msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
if (!msh)
return -ENOMEM;
host = memstick_priv(msh);
host->pcr = pcr;
host->msh = msh;
host->pdev = pdev;
platform_set_drvdata(pdev, host);
pcr->slots[RTSX_MS_CARD].p_dev = pdev;
pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
mutex_init(&host->host_mutex);
INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
msh->request = rtsx_pci_ms_request;
msh->set_param = rtsx_pci_ms_set_param;
msh->caps = MEMSTICK_CAP_PAR4;
rc = memstick_add_host(msh);
if (rc) {
memstick_free_host(msh);
return rc;
}
return 0;
}
static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
{
struct realtek_pci_ms *host = platform_get_drvdata(pdev);
struct rtsx_pcr *pcr;
struct memstick_host *msh;
int rc;
if (!host)
return 0;
pcr = host->pcr;
pcr->slots[RTSX_MS_CARD].p_dev = NULL;
pcr->slots[RTSX_MS_CARD].card_event = NULL;
msh = host->msh;
host->eject = true;
mutex_lock(&host->host_mutex);
if (host->req) {
dev_dbg(&(pdev->dev),
"%s: Controller removed during transfer\n",
dev_name(&msh->dev));
rtsx_pci_complete_unfinished_transfer(pcr);
host->req->error = -ENOMEDIUM;
do {
rc = memstick_next_req(msh, &host->req);
if (!rc)
host->req->error = -ENOMEDIUM;
} while (!rc);
}
mutex_unlock(&host->host_mutex);
memstick_remove_host(msh);
memstick_free_host(msh);
platform_set_drvdata(pdev, NULL);
dev_dbg(&(pdev->dev),
": Realtek PCI-E Memstick controller has been removed\n");
return 0;
}
static struct platform_device_id rtsx_pci_ms_ids[] = {
{
.name = DRV_NAME_RTSX_PCI_MS,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
static struct platform_driver rtsx_pci_ms_driver = {
.probe = rtsx_pci_ms_drv_probe,
.remove = rtsx_pci_ms_drv_remove,
.id_table = rtsx_pci_ms_ids,
.suspend = rtsx_pci_ms_suspend,
.resume = rtsx_pci_ms_resume,
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME_RTSX_PCI_MS,
},
};
module_platform_driver(rtsx_pci_ms_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");

View File

@ -63,6 +63,16 @@ config MFD_SM501_GPIO
lines on the SM501. The platform data is used to supply the
base number for the first GPIO line to register.
config MFD_RTSX_PCI
tristate "Support for Realtek PCI-E card reader"
depends on PCI
select MFD_CORE
help
This supports for Realtek PCI-Express card reader including rts5209,
rts5229, rtl8411, etc. Realtek card reader supports access to many
types of memory cards, such as Memory Stick, Memory Stick Pro,
Secure Digital and MultiMediaCard.
config MFD_ASIC3
bool "Support for Compaq ASIC3"
depends on GENERIC_HARDIRQS && GPIOLIB && ARM

View File

@ -9,6 +9,9 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o

251
drivers/mfd/rtl8411.c Normal file
View File

@ -0,0 +1,251 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Wei WANG <wei_wang@realsil.com.cn>
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/mfd/rtsx_pci.h>
#include "rtsx_pcr.h"
static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
{
u8 val;
rtsx_pci_read_register(pcr, SYS_VER, &val);
return val & 0x0F;
}
static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CD_PAD_CTL,
CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
}
static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
}
static int rtl8411_turn_off_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
}
static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
}
static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
}
static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card)
{
int err;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL,
BPP_LDO_POWB, BPP_LDO_SUSPEND);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
/* To avoid too large in-rush current */
udelay(150);
err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON);
if (err < 0)
return err;
udelay(150);
err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON);
if (err < 0)
return err;
udelay(150);
err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_ON);
if (err < 0)
return err;
return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON);
}
static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
{
int err;
err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_OFF);
if (err < 0)
return err;
return rtsx_pci_write_register(pcr, LDO_CTL,
BPP_LDO_POWB, BPP_LDO_SUSPEND);
}
static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
{
unsigned int card_exist;
card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
card_exist &= CARD_EXIST;
if (!card_exist) {
/* Enable card CD */
rtsx_pci_write_register(pcr, CD_PAD_CTL,
CD_DISABLE_MASK, CD_ENABLE);
/* Enable card interrupt */
rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00);
return 0;
}
if (hweight32(card_exist) > 1) {
rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
msleep(100);
card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
if (card_exist & MS_EXIST)
card_exist = MS_EXIST;
else if (card_exist & SD_EXIST)
card_exist = SD_EXIST;
else
card_exist = 0;
rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_OFF);
dev_dbg(&(pcr->pci->dev),
"After CD deglitch, card_exist = 0x%x\n",
card_exist);
}
if (card_exist & MS_EXIST) {
/* Disable SD interrupt */
rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40);
rtsx_pci_write_register(pcr, CD_PAD_CTL,
CD_DISABLE_MASK, MS_CD_EN_ONLY);
} else if (card_exist & SD_EXIST) {
/* Disable MS interrupt */
rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80);
rtsx_pci_write_register(pcr, CD_PAD_CTL,
CD_DISABLE_MASK, SD_CD_EN_ONLY);
}
return card_exist;
}
static const struct pcr_ops rtl8411_pcr_ops = {
.extra_init_hw = rtl8411_extra_init_hw,
.optimize_phy = NULL,
.turn_on_led = rtl8411_turn_on_led,
.turn_off_led = rtl8411_turn_off_led,
.enable_auto_blink = rtl8411_enable_auto_blink,
.disable_auto_blink = rtl8411_disable_auto_blink,
.card_power_on = rtl8411_card_power_on,
.card_power_off = rtl8411_card_power_off,
.cd_deglitch = rtl8411_cd_deglitch,
};
/* SD Pull Control Enable:
* SD_DAT[3:0] ==> pull up
* SD_CD ==> pull up
* SD_WP ==> pull up
* SD_CMD ==> pull up
* SD_CLK ==> pull down
*/
static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
0,
};
/* SD Pull Control Disable:
* SD_DAT[3:0] ==> pull down
* SD_CD ==> pull up
* SD_WP ==> pull down
* SD_CMD ==> pull down
* SD_CLK ==> pull down
*/
static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
0,
};
/* MS Pull Control Enable:
* MS CD ==> pull up
* others ==> pull down
*/
static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
0,
};
/* MS Pull Control Disable:
* MS CD ==> pull up
* others ==> pull down
*/
static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
0,
};
void rtl8411_init_params(struct rtsx_pcr *pcr)
{
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
pcr->num_slots = 2;
pcr->ops = &rtl8411_pcr_ops;
pcr->ic_version = rtl8411_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
}

223
drivers/mfd/rts5209.c Normal file
View File

@ -0,0 +1,223 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Wei WANG <wei_wang@realsil.com.cn>
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mfd/rtsx_pci.h>
#include "rtsx_pcr.h"
static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
{
u8 val;
val = rtsx_pci_readb(pcr, 0x1C);
return val & 0x0F;
}
static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr)
{
u32 val;
rtsx_pci_read_config_dword(pcr, 0x724, &val);
dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val);
if (!(val & 0x80)) {
if (val & 0x08)
pcr->ms_pmos = false;
else
pcr->ms_pmos = true;
}
}
static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
{
rtsx_pci_init_cmd(pcr);
/* Turn off LED */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
/* Configure GPIO as output */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
return rtsx_pci_send_cmd(pcr, 100);
}
static int rts5209_optimize_phy(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966);
}
static int rts5209_turn_on_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
}
static int rts5209_turn_off_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
}
static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
}
static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
}
static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
{
int err;
u8 pwr_mask, partial_pwr_on, pwr_on;
pwr_mask = SD_POWER_MASK;
partial_pwr_on = SD_PARTIAL_POWER_ON;
pwr_on = SD_POWER_ON;
if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
pwr_mask = MS_POWER_MASK;
partial_pwr_on = MS_PARTIAL_POWER_ON;
pwr_on = MS_POWER_ON;
}
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
pwr_mask, partial_pwr_on);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x04);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
/* To avoid too large in-rush current */
udelay(150);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x00);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
}
static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
{
u8 pwr_mask, pwr_off;
pwr_mask = SD_POWER_MASK;
pwr_off = SD_POWER_OFF;
if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
pwr_mask = MS_POWER_MASK;
pwr_off = MS_POWER_OFF;
}
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0X06);
return rtsx_pci_send_cmd(pcr, 100);
}
static const struct pcr_ops rts5209_pcr_ops = {
.extra_init_hw = rts5209_extra_init_hw,
.optimize_phy = rts5209_optimize_phy,
.turn_on_led = rts5209_turn_on_led,
.turn_off_led = rts5209_turn_off_led,
.enable_auto_blink = rts5209_enable_auto_blink,
.disable_auto_blink = rts5209_disable_auto_blink,
.card_power_on = rts5209_card_power_on,
.card_power_off = rts5209_card_power_off,
.cd_deglitch = NULL,
};
/* SD Pull Control Enable:
* SD_DAT[3:0] ==> pull up
* SD_CD ==> pull up
* SD_WP ==> pull up
* SD_CMD ==> pull up
* SD_CLK ==> pull down
*/
static const u32 rts5209_sd_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
0,
};
/* SD Pull Control Disable:
* SD_DAT[3:0] ==> pull down
* SD_CD ==> pull up
* SD_WP ==> pull down
* SD_CMD ==> pull down
* SD_CLK ==> pull down
*/
static const u32 rts5209_sd_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
0,
};
/* MS Pull Control Enable:
* MS CD ==> pull up
* others ==> pull down
*/
static const u32 rts5209_ms_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
0,
};
/* MS Pull Control Disable:
* MS CD ==> pull up
* others ==> pull down
*/
static const u32 rts5209_ms_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
0,
};
void rts5209_init_params(struct rtsx_pcr *pcr)
{
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 |
EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT;
pcr->num_slots = 2;
pcr->ops = &rts5209_pcr_ops;
rts5209_init_vendor_cfg(pcr);
pcr->ic_version = rts5209_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl;
}

205
drivers/mfd/rts5229.c Normal file
View File

@ -0,0 +1,205 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Wei WANG <wei_wang@realsil.com.cn>
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mfd/rtsx_pci.h>
#include "rtsx_pcr.h"
static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
{
u8 val;
rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
return val & 0x0F;
}
static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
{
rtsx_pci_init_cmd(pcr);
/* Configure GPIO as output */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
/* Switch LDO3318 source from DV33 to card_3v3 */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
/* LED shine disabled, set initial shine cycle period */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
return rtsx_pci_send_cmd(pcr, 100);
}
static int rts5229_optimize_phy(struct rtsx_pcr *pcr)
{
/* Optimize RX sensitivity */
return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
}
static int rts5229_turn_on_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
}
static int rts5229_turn_off_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
}
static int rts5229_enable_auto_blink(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
}
static int rts5229_disable_auto_blink(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
}
static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
{
int err;
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
SD_POWER_MASK, SD_PARTIAL_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x02);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
/* To avoid too large in-rush current */
udelay(150);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
SD_POWER_MASK, SD_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06);
err = rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
}
static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
{
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
SD_POWER_MASK | PMOS_STRG_MASK,
SD_POWER_OFF | PMOS_STRG_400mA);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0X00);
return rtsx_pci_send_cmd(pcr, 100);
}
static const struct pcr_ops rts5229_pcr_ops = {
.extra_init_hw = rts5229_extra_init_hw,
.optimize_phy = rts5229_optimize_phy,
.turn_on_led = rts5229_turn_on_led,
.turn_off_led = rts5229_turn_off_led,
.enable_auto_blink = rts5229_enable_auto_blink,
.disable_auto_blink = rts5229_disable_auto_blink,
.card_power_on = rts5229_card_power_on,
.card_power_off = rts5229_card_power_off,
.cd_deglitch = NULL,
};
/* SD Pull Control Enable:
* SD_DAT[3:0] ==> pull up
* SD_CD ==> pull up
* SD_WP ==> pull up
* SD_CMD ==> pull up
* SD_CLK ==> pull down
*/
static const u32 rts5229_sd_pull_ctl_enable_tbl1[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
0,
};
/* For RTS5229 version C */
static const u32 rts5229_sd_pull_ctl_enable_tbl2[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD9),
0,
};
/* SD Pull Control Disable:
* SD_DAT[3:0] ==> pull down
* SD_CD ==> pull up
* SD_WP ==> pull down
* SD_CMD ==> pull down
* SD_CLK ==> pull down
*/
static const u32 rts5229_sd_pull_ctl_disable_tbl1[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
0,
};
/* For RTS5229 version C */
static const u32 rts5229_sd_pull_ctl_disable_tbl2[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE5),
0,
};
/* MS Pull Control Enable:
* MS CD ==> pull up
* others ==> pull down
*/
static const u32 rts5229_ms_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
0,
};
/* MS Pull Control Disable:
* MS CD ==> pull up
* others ==> pull down
*/
static const u32 rts5229_ms_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
0,
};
void rts5229_init_params(struct rtsx_pcr *pcr)
{
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
pcr->num_slots = 2;
pcr->ops = &rts5229_pcr_ops;
pcr->ic_version = rts5229_get_ic_version(pcr);
if (pcr->ic_version == IC_VER_C) {
pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl2;
} else {
pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl1;
pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl1;
}
pcr->ms_pull_ctl_enable_tbl = rts5229_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl = rts5229_ms_pull_ctl_disable_tbl;
}

1251
drivers/mfd/rtsx_pcr.c Normal file

File diff suppressed because it is too large Load Diff

32
drivers/mfd/rtsx_pcr.h Normal file
View File

@ -0,0 +1,32 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Wei WANG <wei_wang@realsil.com.cn>
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __RTSX_PCR_H
#define __RTSX_PCR_H
#include <linux/mfd/rtsx_pci.h>
void rts5209_init_params(struct rtsx_pcr *pcr);
void rts5229_init_params(struct rtsx_pcr *pcr);
void rtl8411_init_params(struct rtsx_pcr *pcr);
#endif

View File

@ -51,7 +51,7 @@ static const struct ad_dpot_bus_ops bops = {
.write_r8d16 = write_r8d16,
};
static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
static int ad_dpot_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ad_dpot_bus_data bdata = {
@ -68,7 +68,7 @@ static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name);
}
static int __devexit ad_dpot_i2c_remove(struct i2c_client *client)
static int ad_dpot_i2c_remove(struct i2c_client *client)
{
return ad_dpot_remove(&client->dev);
}
@ -109,7 +109,7 @@ static struct i2c_driver ad_dpot_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ad_dpot_i2c_probe,
.remove = __devexit_p(ad_dpot_i2c_remove),
.remove = ad_dpot_i2c_remove,
.id_table = ad_dpot_id,
};

View File

@ -75,7 +75,7 @@ static const struct ad_dpot_bus_ops bops = {
.write_r8d8 = write16,
.write_r8d16 = write24,
};
static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
static int ad_dpot_spi_probe(struct spi_device *spi)
{
struct ad_dpot_bus_data bdata = {
.client = spi,
@ -87,7 +87,7 @@ static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
spi_get_device_id(spi)->name);
}
static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
static int ad_dpot_spi_remove(struct spi_device *spi)
{
return ad_dpot_remove(&spi->dev);
}
@ -131,7 +131,7 @@ static struct spi_driver ad_dpot_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ad_dpot_spi_probe,
.remove = __devexit_p(ad_dpot_spi_remove),
.remove = ad_dpot_spi_remove,
.id_table = ad_dpot_spi_id,
};

View File

@ -641,7 +641,7 @@ static const struct attribute_group ad525x_group_commands = {
.attrs = ad525x_attributes_commands,
};
__devinit int ad_dpot_add_files(struct device *dev,
int ad_dpot_add_files(struct device *dev,
unsigned features, unsigned rdac)
{
int err = sysfs_create_file(&dev->kobj,
@ -685,7 +685,7 @@ inline void ad_dpot_remove_files(struct device *dev,
}
}
int __devinit ad_dpot_probe(struct device *dev,
int ad_dpot_probe(struct device *dev,
struct ad_dpot_bus_data *bdata, unsigned long devid,
const char *name)
{

View File

@ -68,7 +68,7 @@ static int als_wait_for_data_ready(struct device *dev)
ret = i2c_smbus_read_byte_data(client, 0x86);
} while (!(ret & 0x80) && retry--);
if (!retry) {
if (retry < 0) {
dev_warn(dev, "timeout waiting for data ready\n");
return -ETIMEDOUT;
}
@ -254,7 +254,7 @@ als_error1:
return res;
}
static int __devexit apds9802als_remove(struct i2c_client *client)
static int apds9802als_remove(struct i2c_client *client)
{
struct als_data *data = i2c_get_clientdata(client);
@ -326,7 +326,7 @@ static struct i2c_driver apds9802als_driver = {
.pm = APDS9802ALS_PM_OPS,
},
.probe = apds9802als_probe,
.remove = __devexit_p(apds9802als_remove),
.remove = apds9802als_remove,
.suspend = apds9802als_suspend,
.resume = apds9802als_resume,
.id_table = apds9802als_id,

View File

@ -1047,7 +1047,7 @@ static struct attribute_group apds990x_attribute_group[] = {
{.attrs = sysfs_attrs_ctrl },
};
static int __devinit apds990x_probe(struct i2c_client *client,
static int apds990x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct apds990x_chip *chip;
@ -1181,7 +1181,7 @@ fail1:
return err;
}
static int __devexit apds990x_remove(struct i2c_client *client)
static int apds990x_remove(struct i2c_client *client)
{
struct apds990x_chip *chip = i2c_get_clientdata(client);
@ -1275,7 +1275,7 @@ static struct i2c_driver apds990x_driver = {
.pm = &apds990x_pm_ops,
},
.probe = apds990x_probe,
.remove = __devexit_p(apds990x_remove),
.remove = apds990x_remove,
.id_table = apds990x_id,
};

View File

@ -137,7 +137,7 @@ out:
return retval;
}
static int __devexit ssc_remove(struct platform_device *pdev)
static int ssc_remove(struct platform_device *pdev)
{
struct ssc_device *ssc = platform_get_drvdata(pdev);
@ -152,7 +152,7 @@ static int __devexit ssc_remove(struct platform_device *pdev)
}
static struct platform_driver ssc_driver = {
.remove = __devexit_p(ssc_remove),
.remove = ssc_remove,
.driver = {
.name = "ssc",
.owner = THIS_MODULE,

View File

@ -1162,7 +1162,7 @@ static struct attribute_group bh1770_attribute_group = {
.attrs = sysfs_attrs
};
static int __devinit bh1770_probe(struct i2c_client *client,
static int bh1770_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct bh1770_chip *chip;
@ -1285,7 +1285,7 @@ fail1:
return err;
}
static int __devexit bh1770_remove(struct i2c_client *client)
static int bh1770_remove(struct i2c_client *client)
{
struct bh1770_chip *chip = i2c_get_clientdata(client);
@ -1395,7 +1395,7 @@ static struct i2c_driver bh1770_driver = {
.pm = &bh1770_pm_ops,
},
.probe = bh1770_probe,
.remove = __devexit_p(bh1770_remove),
.remove = bh1770_remove,
.id_table = bh1770_id,
};

View File

@ -144,7 +144,7 @@ static const struct attribute_group bh1780_attr_group = {
.attrs = bh1780_attributes,
};
static int __devinit bh1780_probe(struct i2c_client *client,
static int bh1780_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
@ -185,7 +185,7 @@ err_op_failed:
return ret;
}
static int __devexit bh1780_remove(struct i2c_client *client)
static int bh1780_remove(struct i2c_client *client)
{
struct bh1780_data *ddata;
@ -248,7 +248,7 @@ static const struct i2c_device_id bh1780_id[] = {
static struct i2c_driver bh1780_driver = {
.probe = bh1780_probe,
.remove = __devexit_p(bh1780_remove),
.remove = bh1780_remove,
.id_table = bh1780_id,
.driver = {
.name = "bh1780",

View File

@ -36,7 +36,7 @@ static int bmp085_i2c_detect(struct i2c_client *client,
return bmp085_detect(&client->dev);
}
static int __devinit bmp085_i2c_probe(struct i2c_client *client,
static int bmp085_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err;
@ -71,7 +71,7 @@ static struct i2c_driver bmp085_i2c_driver = {
},
.id_table = bmp085_id,
.probe = bmp085_i2c_probe,
.remove = __devexit_p(bmp085_i2c_remove),
.remove = bmp085_i2c_remove,
.detect = bmp085_i2c_detect,
.address_list = normal_i2c

View File

@ -22,7 +22,7 @@
#include <linux/err.h>
#include "bmp085.h"
static int __devinit bmp085_spi_probe(struct spi_device *client)
static int bmp085_spi_probe(struct spi_device *client)
{
int err;
struct regmap *regmap;
@ -70,7 +70,7 @@ static struct spi_driver bmp085_spi_driver = {
},
.id_table = bmp085_id,
.probe = bmp085_spi_probe,
.remove = __devexit_p(bmp085_spi_remove)
.remove = bmp085_spi_remove
};
module_spi_driver(bmp085_spi_driver);

View File

@ -420,7 +420,7 @@ struct regmap_config bmp085_regmap_config = {
};
EXPORT_SYMBOL_GPL(bmp085_regmap_config);
__devinit int bmp085_probe(struct device *dev, struct regmap *regmap)
int bmp085_probe(struct device *dev, struct regmap *regmap)
{
struct bmp085_data *data;
int err = 0;

View File

@ -30,7 +30,7 @@ void cb710_pci_update_config_reg(struct pci_dev *pdev,
EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
/* Some magic writes based on Windows driver init code */
static int __devinit cb710_pci_configure(struct pci_dev *pdev)
static int cb710_pci_configure(struct pci_dev *pdev)
{
unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
struct pci_dev *pdev0;
@ -96,7 +96,7 @@ static void cb710_release_slot(struct device *dev)
#endif
}
static int __devinit cb710_register_slot(struct cb710_chip *chip,
static int cb710_register_slot(struct cb710_chip *chip,
unsigned slot_mask, unsigned io_offset, const char *name)
{
int nr = chip->slots;
@ -201,7 +201,7 @@ static int cb710_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
static int __devinit cb710_probe(struct pci_dev *pdev,
static int cb710_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct cb710_chip *chip;
@ -305,7 +305,7 @@ unreg_mmc:
return err;
}
static void __devexit cb710_remove_one(struct pci_dev *pdev)
static void cb710_remove_one(struct pci_dev *pdev)
{
struct cb710_chip *chip = pci_get_drvdata(pdev);
unsigned long flags;
@ -332,7 +332,7 @@ static struct pci_driver cb710_driver = {
.name = KBUILD_MODNAME,
.id_table = cb710_pci_tbl,
.probe = cb710_probe,
.remove = __devexit_p(cb710_remove_one),
.remove = cb710_remove_one,
#ifdef CONFIG_PM
.suspend = cb710_suspend,
.resume = cb710_resume,

View File

@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(cs5535_mfgpt_write);
* Jordan tells me that he and Mitch once played w/ it, but it's unclear
* what the results of that were (and they experienced some instability).
*/
static void __devinit reset_all_timers(void)
static void reset_all_timers(void)
{
uint32_t val, dummy;
@ -262,7 +262,7 @@ static void __devinit reset_all_timers(void)
* In other cases (such as with VSAless OpenFirmware), the system firmware
* leaves timers available for us to use.
*/
static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
static int scan_timers(struct cs5535_mfgpt_chip *mfgpt)
{
struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
unsigned long flags;
@ -289,7 +289,7 @@ static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
return timers;
}
static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev)
static int cs5535_mfgpt_probe(struct platform_device *pdev)
{
struct resource *res;
int err = -EIO, t;

View File

@ -656,7 +656,7 @@ err_out:
return err;
}
static int __devexit at24_remove(struct i2c_client *client)
static int at24_remove(struct i2c_client *client)
{
struct at24_data *at24;
int i;
@ -680,7 +680,7 @@ static struct i2c_driver at24_driver = {
.owner = THIS_MODULE,
},
.probe = at24_probe,
.remove = __devexit_p(at24_remove),
.remove = at24_remove,
.id_table = at24_ids,
};

View File

@ -459,7 +459,7 @@ fail:
return err;
}
static int __devexit at25_remove(struct spi_device *spi)
static int at25_remove(struct spi_device *spi)
{
struct at25_data *at25;
@ -477,7 +477,7 @@ static struct spi_driver at25_driver = {
.owner = THIS_MODULE,
},
.probe = at25_probe,
.remove = __devexit_p(at25_remove),
.remove = at25_remove,
};
module_spi_driver(at25_driver);

View File

@ -309,7 +309,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev,
}
static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
static int eeprom_93xx46_probe(struct spi_device *spi)
{
struct eeprom_93xx46_platform_data *pd;
struct eeprom_93xx46_dev *edev;
@ -370,7 +370,7 @@ fail:
return err;
}
static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
static int eeprom_93xx46_remove(struct spi_device *spi)
{
struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
@ -389,7 +389,7 @@ static struct spi_driver eeprom_93xx46_driver = {
.owner = THIS_MODULE,
},
.probe = eeprom_93xx46_probe,
.remove = __devexit_p(eeprom_93xx46_remove),
.remove = eeprom_93xx46_remove,
};
module_spi_driver(eeprom_93xx46_driver);

View File

@ -407,7 +407,7 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
return 0;
}
static int __devinit fsa9480_probe(struct i2c_client *client,
static int fsa9480_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@ -462,7 +462,7 @@ fail1:
return ret;
}
static int __devexit fsa9480_remove(struct i2c_client *client)
static int fsa9480_remove(struct i2c_client *client)
{
struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
if (client->irq)
@ -533,7 +533,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
.name = "fsa9480",
},
.probe = fsa9480_probe,
.remove = __devexit_p(fsa9480_remove),
.remove = fsa9480_remove,
.resume = fsa9480_resume,
.suspend = fsa9480_suspend,
.id_table = fsa9480_id,

View File

@ -30,7 +30,7 @@
static struct class *ilo_class;
static unsigned int ilo_major;
static unsigned int max_ccb = MIN_CCB;
static unsigned int max_ccb = 16;
static char ilo_hwdev[MAX_ILO_DEV];
static inline int get_entry_id(int entry)
@ -686,7 +686,7 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
pci_iounmap(pdev, hw->mmio_vaddr);
}
static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
{
int error = -ENOMEM;
@ -725,6 +725,9 @@ static void ilo_remove(struct pci_dev *pdev)
int i, minor;
struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev);
if (!ilo_hw)
return;
clear_device(ilo_hw);
minor = MINOR(ilo_hw->cdev.dev);
@ -748,12 +751,16 @@ static void ilo_remove(struct pci_dev *pdev)
ilo_hwdev[(minor / max_ccb)] = 0;
}
static int __devinit ilo_probe(struct pci_dev *pdev,
static int ilo_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int devnum, minor, start, error;
int devnum, minor, start, error = 0;
struct ilo_hwinfo *ilo_hw;
/* Ignore subsystem_device = 0x1979 (set by BIOS) */
if (pdev->subsystem_device == 0x1979)
goto out;
if (max_ccb > MAX_CCB)
max_ccb = MAX_CCB;
else if (max_ccb < MIN_CCB)
@ -852,7 +859,7 @@ static struct pci_driver ilo_driver = {
.name = ILO_NAME,
.id_table = ilo_devices,
.probe = ilo_probe,
.remove = __devexit_p(ilo_remove),
.remove = ilo_remove,
};
static int __init ilo_init(void)
@ -892,14 +899,14 @@ static void __exit ilo_exit(void)
class_destroy(ilo_class);
}
MODULE_VERSION("1.3");
MODULE_VERSION("1.4");
MODULE_ALIAS(ILO_NAME);
MODULE_DESCRIPTION(ILO_NAME);
MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
MODULE_LICENSE("GPL v2");
module_param(max_ccb, uint, 0444);
MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8)");
MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (16)");
module_init(ilo_init);
module_exit(ilo_exit);

View File

@ -62,7 +62,7 @@ module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
int result;
struct service_processor *sp;
@ -163,7 +163,7 @@ error_resources:
return result;
}
static void __devexit ibmasm_remove_one(struct pci_dev *pdev)
static void ibmasm_remove_one(struct pci_dev *pdev)
{
struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
@ -198,7 +198,7 @@ static struct pci_driver ibmasm_driver = {
.name = DRIVER_NAME,
.id_table = ibmasm_pci_table,
.probe = ibmasm_init_one,
.remove = __devexit_p(ibmasm_remove_one),
.remove = ibmasm_remove_one,
};
static void __exit ibmasm_exit (void)

View File

@ -139,7 +139,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
* even though the following code utilizes external interrupt registers
* to perform the speed calculation.
*/
static void __devinit
static void
ioc4_clock_calibrate(struct ioc4_driver_data *idd)
{
union ioc4_int_out int_out;
@ -231,7 +231,7 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
* on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
* If neither is present, it's a PCI-RT.
*/
static unsigned int __devinit
static unsigned int
ioc4_variant(struct ioc4_driver_data *idd)
{
struct pci_dev *pdev = NULL;
@ -279,7 +279,7 @@ ioc4_load_modules(struct work_struct *work)
static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
/* Adds a new instance of an IOC4 card */
static int __devinit
static int
ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
{
struct ioc4_driver_data *idd;
@ -415,7 +415,7 @@ out:
}
/* Removes a particular instance of an IOC4 card. */
static void __devexit
static void
ioc4_remove(struct pci_dev *pdev)
{
struct ioc4_submodule *is;
@ -466,7 +466,7 @@ static struct pci_driver ioc4_driver = {
.name = "IOC4",
.id_table = ioc4_id_table,
.probe = ioc4_probe,
.remove = __devexit_p(ioc4_remove),
.remove = ioc4_remove,
};
MODULE_DEVICE_TABLE(pci, ioc4_id_table);

View File

@ -365,7 +365,7 @@ static int isl29003_init_client(struct i2c_client *client)
* I2C layer
*/
static int __devinit isl29003_probe(struct i2c_client *client,
static int isl29003_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@ -401,7 +401,7 @@ exit_kfree:
return err;
}
static int __devexit isl29003_remove(struct i2c_client *client)
static int isl29003_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group);
isl29003_set_power_state(client, 0);
@ -451,7 +451,7 @@ static struct i2c_driver isl29003_driver = {
.suspend = isl29003_suspend,
.resume = isl29003_resume,
.probe = isl29003_probe,
.remove = __devexit_p(isl29003_remove),
.remove = isl29003_remove,
.id_table = isl29003_id,
};

View File

@ -114,7 +114,7 @@ static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
#endif
static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
static int lis3lv02d_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
@ -191,7 +191,7 @@ fail:
return ret;
}
static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
static int lis3lv02d_i2c_remove(struct i2c_client *client)
{
struct lis3lv02d *lis3 = i2c_get_clientdata(client);
struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
@ -280,7 +280,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
},
.probe = lis3lv02d_i2c_probe,
.remove = __devexit_p(lis3lv02d_i2c_remove),
.remove = lis3lv02d_i2c_remove,
.id_table = lis3lv02d_id,
};

View File

@ -69,7 +69,7 @@ static struct of_device_id lis302dl_spi_dt_ids[] = {
MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
#endif
static int __devinit lis302dl_spi_probe(struct spi_device *spi)
static int lis302dl_spi_probe(struct spi_device *spi)
{
int ret;
@ -100,7 +100,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
return lis3lv02d_init_device(&lis3_dev);
}
static int __devexit lis302dl_spi_remove(struct spi_device *spi)
static int lis302dl_spi_remove(struct spi_device *spi)
{
struct lis3lv02d *lis3 = spi_get_drvdata(spi);
lis3lv02d_joystick_disable(lis3);
@ -144,7 +144,7 @@ static struct spi_driver lis302dl_spi_driver = {
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
},
.probe = lis302dl_spi_probe,
.remove = __devexit_p(lis302dl_spi_remove),
.remove = lis302dl_spi_remove,
};
module_spi_driver(lis302dl_spi_driver);

View File

@ -8,4 +8,5 @@ mei-objs += interrupt.o
mei-objs += interface.o
mei-objs += iorw.o
mei-objs += main.o
mei-objs += amthif.o
mei-objs += wd.o

722
drivers/misc/mei/amthif.c Normal file
View File

@ -0,0 +1,722 @@
/*
*
* Intel Management Engine Interface (Intel MEI) Linux driver
* Copyright (c) 2003-2012, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/aio.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/uuid.h>
#include <linux/jiffies.h>
#include <linux/uaccess.h>
#include "mei_dev.h"
#include "hw.h"
#include <linux/mei.h>
#include "interface.h"
const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
0xa8, 0x46, 0xe0, 0xff, 0x65,
0x81, 0x4c);
/**
* mei_amthif_reset_params - initializes mei device iamthif
*
* @dev: the device structure
*/
void mei_amthif_reset_params(struct mei_device *dev)
{
/* reset iamthif parameters. */
dev->iamthif_current_cb = NULL;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_canceled = false;
dev->iamthif_ioctl = false;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
}
/**
* mei_amthif_host_init_ - mei initialization amthif client.
*
* @dev: the device structure
*
*/
void mei_amthif_host_init(struct mei_device *dev)
{
int i;
unsigned char *msg_buf;
mei_cl_init(&dev->iamthif_cl, dev);
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
/* find ME amthi client */
i = mei_me_cl_link(dev, &dev->iamthif_cl,
&mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
if (i < 0) {
dev_info(&dev->pdev->dev, "failed to find iamthif client.\n");
return;
}
/* Assign iamthif_mtu to the value received from ME */
dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
dev->me_clients[i].props.max_msg_length);
kfree(dev->iamthif_msg_buf);
dev->iamthif_msg_buf = NULL;
/* allocate storage for ME message buffer */
msg_buf = kcalloc(dev->iamthif_mtu,
sizeof(unsigned char), GFP_KERNEL);
if (!msg_buf) {
dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
return;
}
dev->iamthif_msg_buf = msg_buf;
if (mei_connect(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
dev->iamthif_cl.host_client_id = 0;
} else {
dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT;
}
}
/**
* mei_amthif_find_read_list_entry - finds a amthilist entry for current file
*
* @dev: the device structure
* @file: pointer to file object
*
* returns returned a list entry on success, NULL on failure.
*/
struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
struct file *file)
{
struct mei_cl_cb *pos = NULL;
struct mei_cl_cb *next = NULL;
list_for_each_entry_safe(pos, next,
&dev->amthif_rd_complete_list.list, list) {
if (pos->cl && pos->cl == &dev->iamthif_cl &&
pos->file_object == file)
return pos;
}
return NULL;
}
/**
* mei_amthif_read - read data from AMTHIF client
*
* @dev: the device structure
* @if_num: minor number
* @file: pointer to file object
* @*ubuf: pointer to user data in user space
* @length: data length to read
* @offset: data read offset
*
* Locking: called under "dev->device_lock" lock
*
* returns
* returned data length on success,
* zero if no data to read,
* negative on failure.
*/
int mei_amthif_read(struct mei_device *dev, struct file *file,
char __user *ubuf, size_t length, loff_t *offset)
{
int rets;
int wait_ret;
struct mei_cl_cb *cb = NULL;
struct mei_cl *cl = file->private_data;
unsigned long timeout;
int i;
/* Only Posible if we are in timeout */
if (!cl || cl != &dev->iamthif_cl) {
dev_dbg(&dev->pdev->dev, "bad file ext.\n");
return -ETIMEDOUT;
}
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
if (i < 0) {
dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
return -ENODEV;
}
dev_dbg(&dev->pdev->dev, "checking amthi data\n");
cb = mei_amthif_find_read_list_entry(dev, file);
/* Check for if we can block or not*/
if (cb == NULL && file->f_flags & O_NONBLOCK)
return -EAGAIN;
dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
while (cb == NULL) {
/* unlock the Mutex */
mutex_unlock(&dev->device_lock);
wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
(cb = mei_amthif_find_read_list_entry(dev, file)));
if (wait_ret)
return -ERESTARTSYS;
dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
/* Locking again the Mutex */
mutex_lock(&dev->device_lock);
}
dev_dbg(&dev->pdev->dev, "Got amthi data\n");
dev->iamthif_timer = 0;
if (cb) {
timeout = cb->read_time +
mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
timeout);
if (time_after(jiffies, timeout)) {
dev_dbg(&dev->pdev->dev, "amthi Time out\n");
/* 15 sec for the message has expired */
list_del(&cb->list);
rets = -ETIMEDOUT;
goto free;
}
}
/* if the whole message will fit remove it from the list */
if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
list_del(&cb->list);
else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
/* end of the message has been reached */
list_del(&cb->list);
rets = 0;
goto free;
}
/* else means that not full buffer will be read and do not
* remove message from deletion list
*/
dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
cb->response_buffer.size);
dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx);
/* length is being turncated to PAGE_SIZE, however,
* the buf_idx may point beyond */
length = min_t(size_t, length, (cb->buf_idx - *offset));
if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
rets = -EFAULT;
else {
rets = length;
if ((*offset + length) < cb->buf_idx) {
*offset += length;
goto out;
}
}
free:
dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
*offset = 0;
mei_io_cb_free(cb);
out:
return rets;
}
/**
* mei_amthif_send_cmd - send amthif command to the ME
*
* @dev: the device structure
* @cb: mei call back struct
*
* returns 0 on success, <0 on failure.
*
*/
static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
{
struct mei_msg_hdr mei_hdr;
int ret;
if (!dev || !cb)
return -ENODEV;
dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
dev->iamthif_state = MEI_IAMTHIF_WRITING;
dev->iamthif_current_cb = cb;
dev->iamthif_file_object = cb->file_object;
dev->iamthif_canceled = false;
dev->iamthif_ioctl = true;
dev->iamthif_msg_buf_size = cb->request_buffer.size;
memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
cb->request_buffer.size);
ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
if (ret < 0)
return ret;
if (ret && dev->mei_host_buffer_is_empty) {
ret = 0;
dev->mei_host_buffer_is_empty = false;
if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
mei_hdr.length = mei_hbuf_max_data(dev);
mei_hdr.msg_complete = 0;
} else {
mei_hdr.length = cb->request_buffer.size;
mei_hdr.msg_complete = 1;
}
mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
mei_hdr.reserved = 0;
dev->iamthif_msg_buf_index += mei_hdr.length;
if (mei_write_message(dev, &mei_hdr,
(unsigned char *)(dev->iamthif_msg_buf),
mei_hdr.length))
return -ENODEV;
if (mei_hdr.msg_complete) {
if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
return -ENODEV;
dev->iamthif_flow_control_pending = true;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
dev->iamthif_current_cb = cb;
dev->iamthif_file_object = cb->file_object;
list_add_tail(&cb->list, &dev->write_waiting_list.list);
} else {
dev_dbg(&dev->pdev->dev, "message does not complete, so add amthi cb to write list.\n");
list_add_tail(&cb->list, &dev->write_list.list);
}
} else {
if (!(dev->mei_host_buffer_is_empty))
dev_dbg(&dev->pdev->dev, "host buffer is not empty");
dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
list_add_tail(&cb->list, &dev->write_list.list);
}
return 0;
}
/**
* mei_amthif_write - write amthif data to amthif client
*
* @dev: the device structure
* @cb: mei call back struct
*
* returns 0 on success, <0 on failure.
*
*/
int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
{
int ret;
if (!dev || !cb)
return -ENODEV;
ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
if (ret)
return ret;
cb->fop_type = MEI_FOP_IOCTL;
if (!list_empty(&dev->amthif_cmd_list.list) ||
dev->iamthif_state != MEI_IAMTHIF_IDLE) {
dev_dbg(&dev->pdev->dev,
"amthif state = %d\n", dev->iamthif_state);
dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
return 0;
}
return mei_amthif_send_cmd(dev, cb);
}
/**
* mei_amthif_run_next_cmd
*
* @dev: the device structure
*
* returns 0 on success, <0 on failure.
*/
void mei_amthif_run_next_cmd(struct mei_device *dev)
{
struct mei_cl_cb *pos = NULL;
struct mei_cl_cb *next = NULL;
int status;
if (!dev)
return;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_canceled = false;
dev->iamthif_ioctl = true;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
dev->iamthif_file_object = NULL;
dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
list_del(&pos->list);
if (pos->cl && pos->cl == &dev->iamthif_cl) {
status = mei_amthif_send_cmd(dev, pos);
if (status) {
dev_dbg(&dev->pdev->dev,
"amthi write failed status = %d\n",
status);
return;
}
break;
}
}
}
unsigned int mei_amthif_poll(struct mei_device *dev,
struct file *file, poll_table *wait)
{
unsigned int mask = 0;
mutex_unlock(&dev->device_lock);
poll_wait(file, &dev->iamthif_cl.wait, wait);
mutex_lock(&dev->device_lock);
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
dev->iamthif_file_object == file) {
mask |= (POLLIN | POLLRDNORM);
dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
mei_amthif_run_next_cmd(dev);
}
return mask;
}
/**
* mei_amthif_irq_process_completed - processes completed iamthif operation.
*
* @dev: the device structure.
* @slots: free slots.
* @cb_pos: callback block.
* @cl: private data of the file object.
* @cmpl_list: complete list.
*
* returns 0, OK; otherwise, error.
*/
int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
{
struct mei_msg_hdr *mei_hdr;
struct mei_cl *cl = cb->cl;
size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
size_t msg_slots = mei_data2slots(len);
mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
mei_hdr->host_addr = cl->host_client_id;
mei_hdr->me_addr = cl->me_client_id;
mei_hdr->reserved = 0;
if (*slots >= msg_slots) {
mei_hdr->length = len;
mei_hdr->msg_complete = 1;
/* Split the message only if we can write the whole host buffer */
} else if (*slots == dev->hbuf_depth) {
msg_slots = *slots;
len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
mei_hdr->length = len;
mei_hdr->msg_complete = 0;
} else {
/* wait for next time the host buffer is empty */
return 0;
}
dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
mei_hdr->length, mei_hdr->msg_complete);
*slots -= msg_slots;
if (mei_write_message(dev, mei_hdr,
dev->iamthif_msg_buf + dev->iamthif_msg_buf_index,
mei_hdr->length)) {
dev->iamthif_state = MEI_IAMTHIF_IDLE;
cl->status = -ENODEV;
list_del(&cb->list);
return -ENODEV;
}
if (mei_flow_ctrl_reduce(dev, cl))
return -ENODEV;
dev->iamthif_msg_buf_index += mei_hdr->length;
cl->status = 0;
if (mei_hdr->msg_complete) {
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev->iamthif_flow_control_pending = true;
/* save iamthif cb sent to amthi client */
cb->buf_idx = dev->iamthif_msg_buf_index;
dev->iamthif_current_cb = cb;
list_move_tail(&cb->list, &dev->write_waiting_list.list);
}
return 0;
}
/**
* mei_amthif_irq_read_message - read routine after ISR to
* handle the read amthi message
*
* @complete_list: An instance of our list structure
* @dev: the device structure
* @mei_hdr: header of amthi message
*
* returns 0 on success, <0 on failure.
*/
int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
struct mei_device *dev, struct mei_msg_hdr *mei_hdr)
{
struct mei_cl_cb *cb;
unsigned char *buffer;
BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
mei_read_slots(dev, buffer, mei_hdr->length);
dev->iamthif_msg_buf_index += mei_hdr->length;
if (!mei_hdr->msg_complete)
return 0;
dev_dbg(&dev->pdev->dev,
"amthi_message_buffer_index =%d\n",
mei_hdr->length);
dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
if (!dev->iamthif_current_cb)
return -ENODEV;
cb = dev->iamthif_current_cb;
dev->iamthif_current_cb = NULL;
if (!cb->cl)
return -ENODEV;
dev->iamthif_stall_timer = 0;
cb->buf_idx = dev->iamthif_msg_buf_index;
cb->read_time = jiffies;
if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
/* found the iamthif cb */
dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
list_add_tail(&cb->list, &complete_list->list);
}
return 0;
}
/**
* mei_amthif_irq_read - prepares to read amthif data.
*
* @dev: the device structure.
* @slots: free slots.
*
* returns 0, OK; otherwise, error.
*/
int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
{
if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
+ sizeof(struct hbm_flow_control))) {
return -EMSGSIZE;
}
*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
return -EIO;
}
dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
dev->iamthif_state = MEI_IAMTHIF_READING;
dev->iamthif_flow_control_pending = false;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
return 0;
}
/**
* mei_amthif_complete - complete amthif callback.
*
* @dev: the device structure.
* @cb_pos: callback block.
*/
void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
{
if (dev->iamthif_canceled != 1) {
dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
dev->iamthif_stall_timer = 0;
memcpy(cb->response_buffer.data,
dev->iamthif_msg_buf,
dev->iamthif_msg_buf_index);
list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
dev_dbg(&dev->pdev->dev, "amthi read completed\n");
dev->iamthif_timer = jiffies;
dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
dev->iamthif_timer);
} else {
mei_amthif_run_next_cmd(dev);
}
dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
wake_up_interruptible(&dev->iamthif_cl.wait);
}
/**
* mei_clear_list - removes all callbacks associated with file
* from mei_cb_list
*
* @dev: device structure.
* @file: file structure
* @mei_cb_list: callbacks list
*
* mei_clear_list is called to clear resources associated with file
* when application calls close function or Ctrl-C was pressed
*
* returns true if callback removed from the list, false otherwise
*/
static bool mei_clear_list(struct mei_device *dev,
const struct file *file, struct list_head *mei_cb_list)
{
struct mei_cl_cb *cb_pos = NULL;
struct mei_cl_cb *cb_next = NULL;
bool removed = false;
/* list all list member */
list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
/* check if list member associated with a file */
if (file == cb_pos->file_object) {
/* remove member from the list */
list_del(&cb_pos->list);
/* check if cb equal to current iamthif cb */
if (dev->iamthif_current_cb == cb_pos) {
dev->iamthif_current_cb = NULL;
/* send flow control to iamthif client */
mei_send_flow_control(dev, &dev->iamthif_cl);
}
/* free all allocated buffers */
mei_io_cb_free(cb_pos);
cb_pos = NULL;
removed = true;
}
}
return removed;
}
/**
* mei_clear_lists - removes all callbacks associated with file
*
* @dev: device structure
* @file: file structure
*
* mei_clear_lists is called to clear resources associated with file
* when application calls close function or Ctrl-C was pressed
*
* returns true if callback removed from the list, false otherwise
*/
static bool mei_clear_lists(struct mei_device *dev, struct file *file)
{
bool removed = false;
/* remove callbacks associated with a file */
mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list))
removed = true;
mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
removed = true;
if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
removed = true;
if (mei_clear_list(dev, file, &dev->write_list.list))
removed = true;
/* check if iamthif_current_cb not NULL */
if (dev->iamthif_current_cb && !removed) {
/* check file and iamthif current cb association */
if (dev->iamthif_current_cb->file_object == file) {
/* remove cb */
mei_io_cb_free(dev->iamthif_current_cb);
dev->iamthif_current_cb = NULL;
removed = true;
}
}
return removed;
}
/**
* mei_amthif_release - the release function
*
* @inode: pointer to inode structure
* @file: pointer to file structure
*
* returns 0 on success, <0 on error
*/
int mei_amthif_release(struct mei_device *dev, struct file *file)
{
if (dev->open_handle_count > 0)
dev->open_handle_count--;
if (dev->iamthif_file_object == file &&
dev->iamthif_state != MEI_IAMTHIF_IDLE) {
dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
dev->iamthif_state);
dev->iamthif_canceled = true;
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
mei_amthif_run_next_cmd(dev);
}
}
if (mei_clear_lists(dev, file))
dev->iamthif_state = MEI_IAMTHIF_IDLE;
return 0;
}

View File

@ -20,16 +20,16 @@
#include <linux/uuid.h>
/*
* Timeouts
* Timeouts in Seconds
*/
#define MEI_INTEROP_TIMEOUT (HZ * 7)
#define MEI_CONNECT_TIMEOUT 3 /* at least 2 seconds */
#define MEI_INTEROP_TIMEOUT 7 /* Timeout on ready message */
#define MEI_CONNECT_TIMEOUT 3 /* HPS: at least 2 seconds */
#define CONNECT_TIMEOUT 15 /* HPS definition */
#define INIT_CLIENTS_TIMEOUT 15 /* HPS definition */
#define MEI_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */
#define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */
#define IAMTHIF_STALL_TIMER 12 /* seconds */
#define IAMTHIF_READ_TIMER 10000 /* ms */
#define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */
#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */
/*
* Internal Clients Number
@ -293,6 +293,14 @@ struct hbm_props_response {
struct mei_client_properties client_properties;
} __packed;
/**
* struct hbm_client_connect_request - connect/disconnect request
*
* @hbm_cmd - bus message command header
* @me_addr - address of the client in ME
* @host_addr - address of the client in the driver
* @reserved
*/
struct hbm_client_connect_request {
u8 hbm_cmd;
u8 me_addr;
@ -300,6 +308,14 @@ struct hbm_client_connect_request {
u8 reserved;
} __packed;
/**
* struct hbm_client_connect_response - connect/disconnect response
*
* @hbm_cmd - bus message command header
* @me_addr - address of the client in ME
* @host_addr - address of the client in the driver
* @status - status of the request
*/
struct hbm_client_connect_response {
u8 hbm_cmd;
u8 me_addr;
@ -307,12 +323,6 @@ struct hbm_client_connect_response {
u8 status;
} __packed;
struct hbm_client_disconnect_request {
u8 hbm_cmd;
u8 me_addr;
u8 host_addr;
u8 reserved[1];
} __packed;
#define MEI_FC_MESSAGE_RESERVED_LENGTH 5

View File

@ -43,21 +43,6 @@ const char *mei_dev_state_str(int state)
}
const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
0xa8, 0x46, 0xe0, 0xff, 0x65,
0x81, 0x4c);
/**
* mei_io_list_init - Sets up a queue list.
*
* @list: An instance io list structure
* @dev: the device structure
*/
void mei_io_list_init(struct mei_io_list *list)
{
/* initialize our queue list */
INIT_LIST_HEAD(&list->mei_cb.cb_list);
}
/**
* mei_io_list_flush - removes list entry belonging to cl.
@ -65,17 +50,15 @@ void mei_io_list_init(struct mei_io_list *list)
* @list: An instance of our list structure
* @cl: private data of the file object
*/
void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
{
struct mei_cl_cb *pos;
struct mei_cl_cb *next;
list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
if (pos->file_private) {
struct mei_cl *cl_tmp;
cl_tmp = (struct mei_cl *)pos->file_private;
if (mei_cl_cmp_id(cl, cl_tmp))
list_del(&pos->cb_list);
list_for_each_entry_safe(pos, next, &list->list, list) {
if (pos->cl) {
if (mei_cl_cmp_id(cl, pos->cl))
list_del(&pos->list);
}
}
}
@ -96,30 +79,13 @@ int mei_cl_flush_queues(struct mei_cl *cl)
mei_io_list_flush(&cl->dev->write_waiting_list, cl);
mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
return 0;
}
/**
* mei_reset_iamthif_params - initializes mei device iamthif
*
* @dev: the device structure
*/
static void mei_reset_iamthif_params(struct mei_device *dev)
{
/* reset iamthif parameters. */
dev->iamthif_current_cb = NULL;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_canceled = false;
dev->iamthif_ioctl = false;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
}
/**
* init_mei_device - allocates and initializes the mei device structure
*
@ -144,16 +110,14 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
init_waitqueue_head(&dev->wait_stop_wd);
dev->dev_state = MEI_DEV_INITIALIZING;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->wd_interface_reg = false;
mei_io_list_init(&dev->read_list);
mei_io_list_init(&dev->write_list);
mei_io_list_init(&dev->write_waiting_list);
mei_io_list_init(&dev->ctrl_wr_list);
mei_io_list_init(&dev->ctrl_rd_list);
mei_io_list_init(&dev->amthi_cmd_list);
mei_io_list_init(&dev->amthi_read_complete_list);
mei_io_list_init(&dev->amthif_cmd_list);
mei_io_list_init(&dev->amthif_rd_complete_list);
dev->pdev = pdev;
return dev;
}
@ -196,7 +160,8 @@ int mei_hw_init(struct mei_device *dev)
if (!dev->recvd_msg) {
mutex_unlock(&dev->device_lock);
err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
dev->recvd_msg, MEI_INTEROP_TIMEOUT);
dev->recvd_msg,
mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
mutex_lock(&dev->device_lock);
}
@ -317,15 +282,13 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
cl_pos->timer_count = 0;
}
/* remove entry if already in list */
dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n");
mei_remove_client_from_file_list(dev,
dev->wd_cl.host_client_id);
dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
mei_me_cl_unlink(dev, &dev->wd_cl);
mei_remove_client_from_file_list(dev,
dev->iamthif_cl.host_client_id);
mei_me_cl_unlink(dev, &dev->iamthif_cl);
mei_reset_iamthif_params(dev);
dev->extra_write_index = 0;
mei_amthif_reset_params(dev);
memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
}
dev->me_clients_num = 0;
@ -351,10 +314,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
}
}
/* remove all waiting requests */
list_for_each_entry_safe(cb_pos, cb_next,
&dev->write_list.mei_cb.cb_list, cb_list) {
list_del(&cb_pos->cb_list);
mei_free_cb_private(cb_pos);
list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) {
list_del(&cb_pos->list);
mei_io_cb_free(cb_pos);
}
}
@ -370,31 +332,26 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
void mei_host_start_message(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_host_version_request *host_start_req;
struct hbm_host_version_request *start_req;
const size_t len = sizeof(struct hbm_host_version_request);
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
/* host start message */
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
mei_hdr->host_addr = 0;
mei_hdr->me_addr = 0;
mei_hdr->length = sizeof(struct hbm_host_version_request);
mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0;
start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1];
memset(start_req, 0, len);
start_req->hbm_cmd = HOST_START_REQ_CMD;
start_req->host_version.major_version = HBM_MAJOR_VERSION;
start_req->host_version.minor_version = HBM_MINOR_VERSION;
host_start_req =
(struct hbm_host_version_request *) &dev->wr_msg_buf[1];
memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
host_start_req->hbm_cmd = HOST_START_REQ_CMD;
host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
dev->recvd_msg = false;
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
mei_hdr->length)) {
if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) {
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
dev->dev_state = MEI_DEV_RESETING;
mei_reset(dev, 1);
}
dev->init_clients_state = MEI_START_MESSAGE;
dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
return ;
}
@ -408,26 +365,22 @@ void mei_host_start_message(struct mei_device *dev)
void mei_host_enum_clients_message(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_host_enum_request *host_enum_req;
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
struct hbm_host_enum_request *enum_req;
const size_t len = sizeof(struct hbm_host_enum_request);
/* enumerate clients */
mei_hdr->host_addr = 0;
mei_hdr->me_addr = 0;
mei_hdr->length = sizeof(struct hbm_host_enum_request);
mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0;
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
mei_hdr->length)) {
enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
memset(enum_req, 0, sizeof(struct hbm_host_enum_request));
enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) {
dev->dev_state = MEI_DEV_RESETING;
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
mei_reset(dev, 1);
}
dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
return;
}
@ -470,56 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
dev->me_clients = clients;
return ;
}
/**
* host_client_properties - reads properties for client
*
* @dev: the device structure
*
* returns:
* < 0 - Error.
* = 0 - no more clients.
* = 1 - still have clients to send properties request.
*/
int mei_host_client_properties(struct mei_device *dev)
void mei_host_client_init(struct work_struct *work)
{
struct mei_msg_hdr *mei_header;
struct hbm_props_request *host_cli_req;
int b;
u8 client_num = dev->me_client_presentation_num;
struct mei_device *dev = container_of(work,
struct mei_device, init_work);
struct mei_client_properties *client_props;
int i;
b = dev->me_client_index;
b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
if (b < MEI_CLIENTS_MAX) {
dev->me_clients[client_num].client_id = b;
dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
mei_header->host_addr = 0;
mei_header->me_addr = 0;
mei_header->length = sizeof(struct hbm_props_request);
mei_header->msg_complete = 1;
mei_header->reserved = 0;
mutex_lock(&dev->device_lock);
host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
dev->open_handle_count = 0;
memset(host_cli_req, 0, sizeof(struct hbm_props_request));
/*
* Reserving the first three client IDs
* 0: Reserved for MEI Bus Message communications
* 1: Reserved for Watchdog
* 2: Reserved for AMTHI
*/
bitmap_set(dev->host_clients_map, 0, 3);
host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
host_cli_req->address = b;
for (i = 0; i < dev->me_clients_num; i++) {
client_props = &dev->me_clients[i].props;
if (mei_write_message(dev, mei_header,
(unsigned char *)host_cli_req,
mei_header->length)) {
dev->dev_state = MEI_DEV_RESETING;
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
mei_reset(dev, 1);
return -EIO;
}
dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
dev->me_client_index = b;
return 1;
if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
mei_amthif_host_init(dev);
else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
mei_wd_host_init(dev);
}
dev->dev_state = MEI_DEV_ENABLED;
mutex_unlock(&dev->device_lock);
}
int mei_host_client_enumerate(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_props_request *prop_req;
const size_t len = sizeof(struct hbm_props_request);
unsigned long next_client_index;
u8 client_num;
client_num = dev->me_client_presentation_num;
next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
dev->me_client_index);
/* We got all client properties */
if (next_client_index == MEI_CLIENTS_MAX) {
schedule_work(&dev->init_work);
return 0;
}
dev->me_clients[client_num].client_id = next_client_index;
dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
memset(prop_req, 0, sizeof(struct hbm_props_request));
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req->address = next_client_index;
if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
mei_hdr->length)) {
dev->dev_state = MEI_DEV_RESETING;
dev_err(&dev->pdev->dev, "Properties request command failed\n");
mei_reset(dev, 1);
return -EIO;
}
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
dev->me_client_index = next_client_index;
return 0;
}
@ -557,17 +541,20 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid)
/**
* mei_me_cl_update_filext - searches for ME client guid
* sets client_id in mei_file_private if found
* @dev: the device structure
* @cl: private file structure to set client_id in
* @cuuid: searched uuid of ME client
* @client_id: id of host client to be set in file private structure
* mei_me_cl_link - create link between host and me clinet and add
* me_cl to the list
*
* returns ME client index
* @dev: the device structure
* @cl: link between me and host client assocated with opened file descriptor
* @cuuid: uuid of ME client
* @client_id: id of the host client
*
* returns ME client index if ME client
* -EINVAL on incorrect values
* -ENONET if client not found
*/
int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
const uuid_le *cuuid, u8 host_cl_id)
int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
const uuid_le *cuuid, u8 host_cl_id)
{
int i;
@ -587,54 +574,22 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
return -ENOENT;
}
/**
* host_init_iamthif - mei initialization iamthif client.
* mei_me_cl_unlink - remove me_cl from the list
*
* @dev: the device structure
*
* @host_client_id: host client id to be removed
*/
void mei_host_init_iamthif(struct mei_device *dev)
void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl)
{
int i;
unsigned char *msg_buf;
mei_cl_init(&dev->iamthif_cl, dev);
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
/* find ME amthi client */
i = mei_me_cl_update_filext(dev, &dev->iamthif_cl,
&mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
if (i < 0) {
dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
return;
}
/* Assign iamthif_mtu to the value received from ME */
dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
dev->me_clients[i].props.max_msg_length);
kfree(dev->iamthif_msg_buf);
dev->iamthif_msg_buf = NULL;
/* allocate storage for ME message buffer */
msg_buf = kcalloc(dev->iamthif_mtu,
sizeof(unsigned char), GFP_KERNEL);
if (!msg_buf) {
dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
return;
}
dev->iamthif_msg_buf = msg_buf;
if (mei_connect(dev, &dev->iamthif_cl)) {
dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
dev->iamthif_cl.host_client_id = 0;
} else {
dev->iamthif_cl.timer_count = CONNECT_TIMEOUT;
struct mei_cl *pos, *next;
list_for_each_entry_safe(pos, next, &dev->file_list, link) {
if (cl->host_client_id == pos->host_client_id) {
dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
pos->host_client_id, pos->me_client_id);
list_del_init(&pos->link);
break;
}
}
}
@ -671,9 +626,8 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
*/
int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
{
int rets, err;
long timeout = 15; /* 15 seconds */
struct mei_cl_cb *cb;
int rets, err;
if (!dev || !cl)
return -ENODEV;
@ -681,13 +635,11 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
if (cl->state != MEI_FILE_DISCONNECTING)
return 0;
cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
cb = mei_io_cb_init(cl, NULL);
if (!cb)
return -ENOMEM;
INIT_LIST_HEAD(&cb->cb_list);
cb->file_private = cl;
cb->major_file_operations = MEI_CLOSE;
cb->fop_type = MEI_FOP_CLOSE;
if (dev->mei_host_buffer_is_empty) {
dev->mei_host_buffer_is_empty = false;
if (mei_disconnect(dev, cl)) {
@ -696,17 +648,17 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
goto free;
}
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
} else {
dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
list_add_tail(&cb->cb_list,
&dev->ctrl_wr_list.mei_cb.cb_list);
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
mutex_unlock(&dev->device_lock);
err = wait_event_timeout(dev->wait_recvd_msg,
(MEI_FILE_DISCONNECTED == cl->state),
timeout * HZ);
MEI_FILE_DISCONNECTED == cl->state,
mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(&dev->device_lock);
if (MEI_FILE_DISCONNECTED == cl->state) {
@ -728,29 +680,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
mei_io_list_flush(&dev->ctrl_rd_list, cl);
mei_io_list_flush(&dev->ctrl_wr_list, cl);
free:
mei_free_cb_private(cb);
mei_io_cb_free(cb);
return rets;
}
/**
* mei_remove_client_from_file_list -
* removes file private data from device file list
*
* @dev: the device structure
* @host_client_id: host client id to be removed
*/
void mei_remove_client_from_file_list(struct mei_device *dev,
u8 host_client_id)
{
struct mei_cl *cl_pos = NULL;
struct mei_cl *cl_next = NULL;
list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
if (host_client_id == cl_pos->host_client_id) {
dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
cl_pos->host_client_id,
cl_pos->me_client_id);
list_del_init(&cl_pos->link);
break;
}
}
}

View File

@ -292,28 +292,23 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_flow_control *mei_flow_control;
struct hbm_flow_control *flow_ctrl;
const size_t len = sizeof(struct hbm_flow_control);
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
mei_hdr->host_addr = 0;
mei_hdr->me_addr = 0;
mei_hdr->length = sizeof(struct hbm_flow_control);
mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0;
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
memset(mei_flow_control, 0, sizeof(*mei_flow_control));
mei_flow_control->host_addr = cl->host_client_id;
mei_flow_control->me_addr = cl->me_client_id;
mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD;
memset(mei_flow_control->reserved, 0,
sizeof(mei_flow_control->reserved));
flow_ctrl = (struct hbm_flow_control *)&dev->wr_msg_buf[1];
memset(flow_ctrl, 0, len);
flow_ctrl->hbm_cmd = MEI_FLOW_CONTROL_CMD;
flow_ctrl->host_addr = cl->host_client_id;
flow_ctrl->me_addr = cl->me_client_id;
/* FIXME: reserved !? */
memset(flow_ctrl->reserved, 0, sizeof(flow_ctrl->reserved));
dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
return mei_write_message(dev, mei_hdr,
(unsigned char *) mei_flow_control,
sizeof(struct hbm_flow_control));
(unsigned char *) flow_ctrl, len);
}
/**
@ -352,26 +347,19 @@ int mei_other_client_is_connecting(struct mei_device *dev,
int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_client_disconnect_request *mei_cli_disconnect;
struct hbm_client_connect_request *req;
const size_t len = sizeof(struct hbm_client_connect_request);
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
mei_hdr->host_addr = 0;
mei_hdr->me_addr = 0;
mei_hdr->length = sizeof(struct hbm_client_disconnect_request);
mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0;
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
mei_cli_disconnect =
(struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
mei_cli_disconnect->host_addr = cl->host_client_id;
mei_cli_disconnect->me_addr = cl->me_client_id;
mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
mei_cli_disconnect->reserved[0] = 0;
req = (struct hbm_client_connect_request *)&dev->wr_msg_buf[1];
memset(req, 0, len);
req->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
req->host_addr = cl->host_client_id;
req->me_addr = cl->me_client_id;
req->reserved = 0;
return mei_write_message(dev, mei_hdr,
(unsigned char *) mei_cli_disconnect,
sizeof(struct hbm_client_disconnect_request));
return mei_write_message(dev, mei_hdr, (unsigned char *)req, len);
}
/**
@ -385,23 +373,16 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
int mei_connect(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_msg_hdr *mei_hdr;
struct hbm_client_connect_request *mei_cli_connect;
struct hbm_client_connect_request *req;
const size_t len = sizeof(struct hbm_client_connect_request);
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
mei_hdr->host_addr = 0;
mei_hdr->me_addr = 0;
mei_hdr->length = sizeof(struct hbm_client_connect_request);
mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0;
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
mei_cli_connect =
(struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
mei_cli_connect->host_addr = cl->host_client_id;
mei_cli_connect->me_addr = cl->me_client_id;
mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
mei_cli_connect->reserved = 0;
req = (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
req->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
req->host_addr = cl->host_client_id;
req->me_addr = cl->me_client_id;
req->reserved = 0;
return mei_write_message(dev, mei_hdr,
(unsigned char *) mei_cli_connect,
sizeof(struct hbm_client_connect_request));
return mei_write_message(dev, mei_hdr, (unsigned char *) req, len);
}

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,95 @@
#include <linux/mei.h>
#include "interface.h"
/**
* mei_io_cb_free - free mei_cb_private related memory
*
* @cb: mei callback struct
*/
void mei_io_cb_free(struct mei_cl_cb *cb)
{
if (cb == NULL)
return;
kfree(cb->request_buffer.data);
kfree(cb->response_buffer.data);
kfree(cb);
}
/**
* mei_io_cb_init - allocate and initialize io callback
*
* @cl - mei client
* @file: pointer to file structure
*
* returns mei_cl_cb pointer or NULL;
*/
struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
{
struct mei_cl_cb *cb;
cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
if (!cb)
return NULL;
mei_io_list_init(cb);
cb->file_object = fp;
cb->cl = cl;
cb->buf_idx = 0;
return cb;
}
/**
* mei_io_cb_alloc_req_buf - allocate request buffer
*
* @cb - io callback structure
* @size: size of the buffer
*
* returns 0 on success
* -EINVAL if cb is NULL
* -ENOMEM if allocation failed
*/
int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
{
if (!cb)
return -EINVAL;
if (length == 0)
return 0;
cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
if (!cb->request_buffer.data)
return -ENOMEM;
cb->request_buffer.size = length;
return 0;
}
/**
* mei_io_cb_alloc_req_buf - allocate respose buffer
*
* @cb - io callback structure
* @size: size of the buffer
*
* returns 0 on success
* -EINVAL if cb is NULL
* -ENOMEM if allocation failed
*/
int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
{
if (!cb)
return -EINVAL;
if (length == 0)
return 0;
cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
if (!cb->response_buffer.data)
return -ENOMEM;
cb->response_buffer.size = length;
return 0;
}
/**
* mei_me_cl_by_id return index to me_clients for client_id
*
@ -82,9 +171,7 @@ int mei_ioctl_connect_client(struct file *file,
struct mei_cl_cb *cb;
struct mei_client *client;
struct mei_cl *cl;
struct mei_cl *cl_pos = NULL;
struct mei_cl *cl_next = NULL;
long timeout = CONNECT_TIMEOUT;
long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
int i;
int err;
int rets;
@ -97,16 +184,14 @@ int mei_ioctl_connect_client(struct file *file,
dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
/* buffered ioctl cb */
cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
cb = mei_io_cb_init(cl, file);
if (!cb) {
rets = -ENOMEM;
goto end;
}
INIT_LIST_HEAD(&cb->cb_list);
cb->major_file_operations = MEI_IOCTL;
cb->fop_type = MEI_FOP_IOCTL;
if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV;
@ -142,21 +227,9 @@ int mei_ioctl_connect_client(struct file *file,
goto end;
}
clear_bit(cl->host_client_id, dev->host_clients_map);
list_for_each_entry_safe(cl_pos, cl_next,
&dev->file_list, link) {
if (mei_cl_cmp_id(cl, cl_pos)) {
dev_dbg(&dev->pdev->dev,
"remove file private data node host"
" client = %d, ME client = %d.\n",
cl_pos->host_client_id,
cl_pos->me_client_id);
list_del(&cl_pos->link);
}
mei_me_cl_unlink(dev, cl);
}
dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
kfree(cl);
cl = NULL;
file->private_data = &dev->iamthif_cl;
@ -192,25 +265,19 @@ int mei_ioctl_connect_client(struct file *file,
} else {
dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
cl->timer_count = MEI_CONNECT_TIMEOUT;
cb->file_private = cl;
list_add_tail(&cb->cb_list,
&dev->ctrl_rd_list.mei_cb.
cb_list);
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
}
} else {
dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
cb->file_private = cl;
dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
list_add_tail(&cb->cb_list,
&dev->ctrl_wr_list.mei_cb.cb_list);
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
mutex_unlock(&dev->device_lock);
err = wait_event_timeout(dev->wait_recvd_msg,
(MEI_FILE_CONNECTED == cl->state ||
MEI_FILE_DISCONNECTED == cl->state),
timeout * HZ);
MEI_FILE_DISCONNECTED == cl->state), timeout);
mutex_lock(&dev->device_lock);
if (MEI_FILE_CONNECTED == cl->state) {
@ -234,153 +301,7 @@ int mei_ioctl_connect_client(struct file *file,
rets = 0;
end:
dev_dbg(&dev->pdev->dev, "free connect cb memory.");
kfree(cb);
return rets;
}
/**
* find_amthi_read_list_entry - finds a amthilist entry for current file
*
* @dev: the device structure
* @file: pointer to file object
*
* returns returned a list entry on success, NULL on failure.
*/
struct mei_cl_cb *find_amthi_read_list_entry(
struct mei_device *dev,
struct file *file)
{
struct mei_cl *cl_temp;
struct mei_cl_cb *pos = NULL;
struct mei_cl_cb *next = NULL;
list_for_each_entry_safe(pos, next,
&dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
cl_temp = (struct mei_cl *)pos->file_private;
if (cl_temp && cl_temp == &dev->iamthif_cl &&
pos->file_object == file)
return pos;
}
return NULL;
}
/**
* amthi_read - read data from AMTHI client
*
* @dev: the device structure
* @if_num: minor number
* @file: pointer to file object
* @*ubuf: pointer to user data in user space
* @length: data length to read
* @offset: data read offset
*
* Locking: called under "dev->device_lock" lock
*
* returns
* returned data length on success,
* zero if no data to read,
* negative on failure.
*/
int amthi_read(struct mei_device *dev, struct file *file,
char __user *ubuf, size_t length, loff_t *offset)
{
int rets;
int wait_ret;
struct mei_cl_cb *cb = NULL;
struct mei_cl *cl = file->private_data;
unsigned long timeout;
int i;
/* Only Posible if we are in timeout */
if (!cl || cl != &dev->iamthif_cl) {
dev_dbg(&dev->pdev->dev, "bad file ext.\n");
return -ETIMEDOUT;
}
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
if (i < 0) {
dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
return -ENODEV;
}
dev_dbg(&dev->pdev->dev, "checking amthi data\n");
cb = find_amthi_read_list_entry(dev, file);
/* Check for if we can block or not*/
if (cb == NULL && file->f_flags & O_NONBLOCK)
return -EAGAIN;
dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
while (cb == NULL) {
/* unlock the Mutex */
mutex_unlock(&dev->device_lock);
wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
(cb = find_amthi_read_list_entry(dev, file)));
if (wait_ret)
return -ERESTARTSYS;
dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
/* Locking again the Mutex */
mutex_lock(&dev->device_lock);
}
dev_dbg(&dev->pdev->dev, "Got amthi data\n");
dev->iamthif_timer = 0;
if (cb) {
timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER);
dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
timeout);
if (time_after(jiffies, timeout)) {
dev_dbg(&dev->pdev->dev, "amthi Time out\n");
/* 15 sec for the message has expired */
list_del(&cb->cb_list);
rets = -ETIMEDOUT;
goto free;
}
}
/* if the whole message will fit remove it from the list */
if (cb->information >= *offset && length >= (cb->information - *offset))
list_del(&cb->cb_list);
else if (cb->information > 0 && cb->information <= *offset) {
/* end of the message has been reached */
list_del(&cb->cb_list);
rets = 0;
goto free;
}
/* else means that not full buffer will be read and do not
* remove message from deletion list
*/
dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
cb->response_buffer.size);
dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
cb->information);
/* length is being turncated to PAGE_SIZE, however,
* the information may be longer */
length = min_t(size_t, length, (cb->information - *offset));
if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
rets = -EFAULT;
else {
rets = length;
if ((*offset + length) < cb->information) {
*offset += length;
goto out;
}
}
free:
dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
*offset = 0;
mei_free_cb_private(cb);
out:
mei_io_cb_free(cb);
return rets;
}
@ -396,7 +317,7 @@ out:
int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_cl_cb *cb;
int rets = 0;
int rets;
int i;
if (cl->state != MEI_FILE_CONNECTED)
@ -405,187 +326,41 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
if (dev->dev_state != MEI_DEV_ENABLED)
return -ENODEV;
dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
if (cl->read_pending || cl->read_cb) {
dev_dbg(&dev->pdev->dev, "read is pending.\n");
return -EBUSY;
}
i = mei_me_cl_by_id(dev, cl->me_client_id);
if (i < 0) {
dev_err(&dev->pdev->dev, "no such me client %d\n",
cl->me_client_id);
return -ENODEV;
}
cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
cb = mei_io_cb_init(cl, NULL);
if (!cb)
return -ENOMEM;
dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
i = mei_me_cl_by_id(dev, cl->me_client_id);
if (i < 0) {
rets = -ENODEV;
goto unlock;
}
rets = mei_io_cb_alloc_resp_buf(cb,
dev->me_clients[i].props.max_msg_length);
if (rets)
goto err;
cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
cb->response_buffer.data =
kmalloc(cb->response_buffer.size, GFP_KERNEL);
if (!cb->response_buffer.data) {
rets = -ENOMEM;
goto unlock;
}
dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
cb->major_file_operations = MEI_READ;
/* make sure information is zero before we start */
cb->information = 0;
cb->file_private = (void *) cl;
cb->fop_type = MEI_FOP_READ;
cl->read_cb = cb;
if (dev->mei_host_buffer_is_empty) {
dev->mei_host_buffer_is_empty = false;
if (mei_send_flow_control(dev, cl)) {
rets = -ENODEV;
goto unlock;
goto err;
}
list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
list_add_tail(&cb->list, &dev->read_list.list);
} else {
list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
return rets;
unlock:
mei_free_cb_private(cb);
err:
mei_io_cb_free(cb);
return rets;
}
/**
* amthi_write - write iamthif data to amthi client
*
* @dev: the device structure
* @cb: mei call back struct
*
* returns 0 on success, <0 on failure.
*/
int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
{
struct mei_msg_hdr mei_hdr;
int ret;
if (!dev || !cb)
return -ENODEV;
dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
dev->iamthif_state = MEI_IAMTHIF_WRITING;
dev->iamthif_current_cb = cb;
dev->iamthif_file_object = cb->file_object;
dev->iamthif_canceled = false;
dev->iamthif_ioctl = true;
dev->iamthif_msg_buf_size = cb->request_buffer.size;
memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
cb->request_buffer.size);
ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
if (ret < 0)
return ret;
if (ret && dev->mei_host_buffer_is_empty) {
ret = 0;
dev->mei_host_buffer_is_empty = false;
if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
mei_hdr.length = mei_hbuf_max_data(dev);
mei_hdr.msg_complete = 0;
} else {
mei_hdr.length = cb->request_buffer.size;
mei_hdr.msg_complete = 1;
}
mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
mei_hdr.reserved = 0;
dev->iamthif_msg_buf_index += mei_hdr.length;
if (mei_write_message(dev, &mei_hdr,
(unsigned char *)(dev->iamthif_msg_buf),
mei_hdr.length))
return -ENODEV;
if (mei_hdr.msg_complete) {
if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
return -ENODEV;
dev->iamthif_flow_control_pending = true;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
dev->iamthif_current_cb = cb;
dev->iamthif_file_object = cb->file_object;
list_add_tail(&cb->cb_list,
&dev->write_waiting_list.mei_cb.cb_list);
} else {
dev_dbg(&dev->pdev->dev, "message does not complete, "
"so add amthi cb to write list.\n");
list_add_tail(&cb->cb_list,
&dev->write_list.mei_cb.cb_list);
}
} else {
if (!(dev->mei_host_buffer_is_empty))
dev_dbg(&dev->pdev->dev, "host buffer is not empty");
dev_dbg(&dev->pdev->dev, "No flow control credentials, "
"so add iamthif cb to write list.\n");
list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
}
return 0;
}
/**
* iamthif_ioctl_send_msg - send cmd data to amthi client
*
* @dev: the device structure
*
* returns 0 on success, <0 on failure.
*/
void mei_run_next_iamthif_cmd(struct mei_device *dev)
{
struct mei_cl *cl_tmp;
struct mei_cl_cb *pos = NULL;
struct mei_cl_cb *next = NULL;
int status;
if (!dev)
return;
dev->iamthif_msg_buf_size = 0;
dev->iamthif_msg_buf_index = 0;
dev->iamthif_canceled = false;
dev->iamthif_ioctl = true;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
dev->iamthif_file_object = NULL;
dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
list_for_each_entry_safe(pos, next,
&dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
list_del(&pos->cb_list);
cl_tmp = (struct mei_cl *)pos->file_private;
if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
status = amthi_write(dev, pos);
if (status) {
dev_dbg(&dev->pdev->dev,
"amthi write failed status = %d\n",
status);
return;
}
break;
}
}
}
/**
* mei_free_cb_private - free mei_cb_private related memory
*
* @cb: mei callback struct
*/
void mei_free_cb_private(struct mei_cl_cb *cb)
{
if (cb == NULL)
return;
kfree(cb->request_buffer.data);
kfree(cb->response_buffer.data);
kfree(cb);
}

View File

@ -89,93 +89,6 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
static DEFINE_MUTEX(mei_mutex);
/**
* mei_clear_list - removes all callbacks associated with file
* from mei_cb_list
*
* @dev: device structure.
* @file: file structure
* @mei_cb_list: callbacks list
*
* mei_clear_list is called to clear resources associated with file
* when application calls close function or Ctrl-C was pressed
*
* returns true if callback removed from the list, false otherwise
*/
static bool mei_clear_list(struct mei_device *dev,
struct file *file, struct list_head *mei_cb_list)
{
struct mei_cl_cb *cb_pos = NULL;
struct mei_cl_cb *cb_next = NULL;
struct file *file_temp;
bool removed = false;
/* list all list member */
list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) {
file_temp = (struct file *)cb_pos->file_object;
/* check if list member associated with a file */
if (file_temp == file) {
/* remove member from the list */
list_del(&cb_pos->cb_list);
/* check if cb equal to current iamthif cb */
if (dev->iamthif_current_cb == cb_pos) {
dev->iamthif_current_cb = NULL;
/* send flow control to iamthif client */
mei_send_flow_control(dev, &dev->iamthif_cl);
}
/* free all allocated buffers */
mei_free_cb_private(cb_pos);
cb_pos = NULL;
removed = true;
}
}
return removed;
}
/**
* mei_clear_lists - removes all callbacks associated with file
*
* @dev: device structure
* @file: file structure
*
* mei_clear_lists is called to clear resources associated with file
* when application calls close function or Ctrl-C was pressed
*
* returns true if callback removed from the list, false otherwise
*/
static bool mei_clear_lists(struct mei_device *dev, struct file *file)
{
bool removed = false;
/* remove callbacks associated with a file */
mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list);
if (mei_clear_list(dev, file,
&dev->amthi_read_complete_list.mei_cb.cb_list))
removed = true;
mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list);
if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list))
removed = true;
if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list))
removed = true;
if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list))
removed = true;
/* check if iamthif_current_cb not NULL */
if (dev->iamthif_current_cb && !removed) {
/* check file and iamthif current cb association */
if (dev->iamthif_current_cb->file_object == file) {
/* remove cb */
mei_free_cb_private(dev->iamthif_current_cb);
dev->iamthif_current_cb = NULL;
removed = true;
}
}
return removed;
}
/**
* find_read_list_entry - find read list entry
*
@ -192,14 +105,9 @@ static struct mei_cl_cb *find_read_list_entry(
struct mei_cl_cb *next = NULL;
dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
list_for_each_entry_safe(pos, next,
&dev->read_list.mei_cb.cb_list, cb_list) {
struct mei_cl *cl_temp;
cl_temp = (struct mei_cl *)pos->file_private;
if (mei_cl_cmp_id(cl, cl_temp))
list_for_each_entry_safe(pos, next, &dev->read_list.list, list)
if (mei_cl_cmp_id(cl, pos->cl))
return pos;
}
return NULL;
}
@ -297,67 +205,51 @@ static int mei_release(struct inode *inode, struct file *file)
dev = cl->dev;
mutex_lock(&dev->device_lock);
if (cl != &dev->iamthif_cl) {
if (cl->state == MEI_FILE_CONNECTED) {
cl->state = MEI_FILE_DISCONNECTING;
dev_dbg(&dev->pdev->dev,
"disconnecting client host client = %d, "
"ME client = %d\n",
cl->host_client_id,
cl->me_client_id);
rets = mei_disconnect_host_client(dev, cl);
}
mei_cl_flush_queues(cl);
dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
if (cl == &dev->iamthif_cl) {
rets = mei_amthif_release(dev, file);
goto out;
}
if (cl->state == MEI_FILE_CONNECTED) {
cl->state = MEI_FILE_DISCONNECTING;
dev_dbg(&dev->pdev->dev,
"disconnecting client host client = %d, "
"ME client = %d\n",
cl->host_client_id,
cl->me_client_id);
if (dev->open_handle_count > 0) {
clear_bit(cl->host_client_id, dev->host_clients_map);
dev->open_handle_count--;
}
mei_remove_client_from_file_list(dev, cl->host_client_id);
/* free read cb */
cb = NULL;
if (cl->read_cb) {
cb = find_read_list_entry(dev, cl);
/* Remove entry from read list */
if (cb)
list_del(&cb->cb_list);
cb = cl->read_cb;
cl->read_cb = NULL;
}
file->private_data = NULL;
if (cb) {
mei_free_cb_private(cb);
cb = NULL;
}
kfree(cl);
} else {
if (dev->open_handle_count > 0)
dev->open_handle_count--;
if (dev->iamthif_file_object == file &&
dev->iamthif_state != MEI_IAMTHIF_IDLE) {
dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
dev->iamthif_state);
dev->iamthif_canceled = true;
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
mei_run_next_iamthif_cmd(dev);
}
}
if (mei_clear_lists(dev, file))
dev->iamthif_state = MEI_IAMTHIF_IDLE;
rets = mei_disconnect_host_client(dev, cl);
}
mei_cl_flush_queues(cl);
dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
cl->host_client_id,
cl->me_client_id);
if (dev->open_handle_count > 0) {
clear_bit(cl->host_client_id, dev->host_clients_map);
dev->open_handle_count--;
}
mei_me_cl_unlink(dev, cl);
/* free read cb */
cb = NULL;
if (cl->read_cb) {
cb = find_read_list_entry(dev, cl);
/* Remove entry from read list */
if (cb)
list_del(&cb->list);
cb = cl->read_cb;
cl->read_cb = NULL;
}
file->private_data = NULL;
if (cb) {
mei_io_cb_free(cb);
cb = NULL;
}
kfree(cl);
out:
mutex_unlock(&dev->device_lock);
return rets;
}
@ -411,20 +303,19 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
}
if (cl == &dev->iamthif_cl) {
rets = amthi_read(dev, file, ubuf, length, offset);
rets = mei_amthif_read(dev, file, ubuf, length, offset);
goto out;
}
if (cl->read_cb && cl->read_cb->information > *offset) {
if (cl->read_cb && cl->read_cb->buf_idx > *offset) {
cb = cl->read_cb;
goto copy_buffer;
} else if (cl->read_cb && cl->read_cb->information > 0 &&
cl->read_cb->information <= *offset) {
} else if (cl->read_cb && cl->read_cb->buf_idx > 0 &&
cl->read_cb->buf_idx <= *offset) {
cb = cl->read_cb;
rets = 0;
goto free;
} else if ((!cl->read_cb || !cl->read_cb->information) &&
*offset > 0) {
} else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) {
/*Offset needs to be cleaned for contiguous reads*/
*offset = 0;
rets = 0;
@ -481,16 +372,15 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
copy_buffer:
dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n",
cb->response_buffer.size);
dev_dbg(&dev->pdev->dev, "cb->information - %lu\n",
cb->information);
if (length == 0 || ubuf == NULL || *offset > cb->information) {
dev_dbg(&dev->pdev->dev, "cb->buf_idx - %lu\n", cb->buf_idx);
if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
rets = -EMSGSIZE;
goto free;
}
/* length is being truncated to PAGE_SIZE, however, */
/* information size may be longer */
length = min_t(size_t, length, (cb->information - *offset));
/* length is being truncated to PAGE_SIZE,
* however buf_idx may point beyond that */
length = min_t(size_t, length, cb->buf_idx - *offset);
if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
rets = -EFAULT;
@ -499,15 +389,15 @@ copy_buffer:
rets = length;
*offset += length;
if ((unsigned long)*offset < cb->information)
if ((unsigned long)*offset < cb->buf_idx)
goto out;
free:
cb_pos = find_read_list_entry(dev, cl);
/* Remove entry from read list */
if (cb_pos)
list_del(&cb_pos->cb_list);
mei_free_cb_private(cb);
list_del(&cb_pos->list);
mei_io_cb_free(cb);
cl->reading_state = MEI_IDLE;
cl->read_cb = NULL;
cl->read_pending = 0;
@ -516,7 +406,6 @@ out:
mutex_unlock(&dev->device_lock);
return rets;
}
/**
* mei_write - the write function.
*
@ -546,23 +435,39 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
mutex_lock(&dev->device_lock);
if (dev->dev_state != MEI_DEV_ENABLED) {
mutex_unlock(&dev->device_lock);
return -ENODEV;
rets = -ENODEV;
goto err;
}
i = mei_me_cl_by_id(dev, cl->me_client_id);
if (i < 0) {
rets = -ENODEV;
goto err;
}
if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
rets = -EMSGSIZE;
goto err;
}
if (cl->state != MEI_FILE_CONNECTED) {
rets = -ENODEV;
dev_err(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
cl->host_client_id, cl->me_client_id);
goto err;
}
if (cl == &dev->iamthif_cl) {
write_cb = find_amthi_read_list_entry(dev, file);
write_cb = mei_amthif_find_read_list_entry(dev, file);
if (write_cb) {
timeout = write_cb->read_time +
msecs_to_jiffies(IAMTHIF_READ_TIMER);
mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
if (time_after(jiffies, timeout) ||
cl->reading_state == MEI_READ_COMPLETE) {
*offset = 0;
list_del(&write_cb->cb_list);
mei_free_cb_private(write_cb);
write_cb = NULL;
cl->reading_state == MEI_READ_COMPLETE) {
*offset = 0;
list_del(&write_cb->list);
mei_io_cb_free(write_cb);
write_cb = NULL;
}
}
}
@ -572,8 +477,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
*offset = 0;
write_cb = find_read_list_entry(dev, cl);
if (write_cb) {
list_del(&write_cb->cb_list);
mei_free_cb_private(write_cb);
list_del(&write_cb->list);
mei_io_cb_free(write_cb);
write_cb = NULL;
cl->reading_state = MEI_IDLE;
cl->read_cb = NULL;
@ -583,24 +488,21 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
*offset = 0;
write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
write_cb = mei_io_cb_init(cl, file);
if (!write_cb) {
mutex_unlock(&dev->device_lock);
return -ENOMEM;
dev_err(&dev->pdev->dev, "write cb allocation failed\n");
rets = -ENOMEM;
goto err;
}
rets = mei_io_cb_alloc_req_buf(write_cb, length);
if (rets)
goto err;
write_cb->file_object = file;
write_cb->file_private = cl;
write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
rets = -ENOMEM;
if (!write_cb->request_buffer.data)
goto unlock_dev;
dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length);
dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
rets = -EFAULT;
if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
goto unlock_dev;
rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
if (rets)
goto err;
cl->sm_state = 0;
if (length == 4 &&
@ -612,139 +514,71 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
write_cb->request_buffer.data, 4) == 0)))
cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
INIT_LIST_HEAD(&write_cb->cb_list);
if (cl == &dev->iamthif_cl) {
write_cb->response_buffer.data =
kmalloc(dev->iamthif_mtu, GFP_KERNEL);
if (!write_cb->response_buffer.data) {
rets = -ENOMEM;
goto unlock_dev;
}
if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV;
goto unlock_dev;
}
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
if (i < 0) {
rets = -ENODEV;
goto unlock_dev;
}
if (length > dev->me_clients[i].props.max_msg_length ||
length <= 0) {
rets = -EMSGSIZE;
goto unlock_dev;
}
rets = mei_amthif_write(dev, write_cb);
write_cb->response_buffer.size = dev->iamthif_mtu;
write_cb->major_file_operations = MEI_IOCTL;
write_cb->information = 0;
write_cb->request_buffer.size = length;
if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
rets = -ENODEV;
goto unlock_dev;
}
if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) ||
dev->iamthif_state != MEI_IAMTHIF_IDLE) {
dev_dbg(&dev->pdev->dev, "amthi_state = %d\n",
(int) dev->iamthif_state);
dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n");
list_add_tail(&write_cb->cb_list,
&dev->amthi_cmd_list.mei_cb.cb_list);
rets = length;
} else {
dev_dbg(&dev->pdev->dev, "call amthi write\n");
rets = amthi_write(dev, write_cb);
if (rets) {
dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n",
rets);
goto unlock_dev;
}
rets = length;
if (rets) {
dev_err(&dev->pdev->dev,
"amthi write failed with status = %d\n", rets);
goto err;
}
mutex_unlock(&dev->device_lock);
return rets;
return length;
}
write_cb->major_file_operations = MEI_WRITE;
/* make sure information is zero before we start */
write_cb->information = 0;
write_cb->request_buffer.size = length;
write_cb->fop_type = MEI_FOP_WRITE;
dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
if (cl->state != MEI_FILE_CONNECTED) {
rets = -ENODEV;
dev_dbg(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
cl->host_client_id,
cl->me_client_id);
goto unlock_dev;
}
i = mei_me_cl_by_id(dev, cl->me_client_id);
if (i < 0) {
rets = -ENODEV;
goto unlock_dev;
}
if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
rets = -EINVAL;
goto unlock_dev;
}
write_cb->file_private = cl;
rets = mei_flow_ctrl_creds(dev, cl);
if (rets < 0)
goto unlock_dev;
goto err;
if (rets && dev->mei_host_buffer_is_empty) {
rets = 0;
dev->mei_host_buffer_is_empty = false;
if (length > mei_hbuf_max_data(dev)) {
mei_hdr.length = mei_hbuf_max_data(dev);
mei_hdr.msg_complete = 0;
} else {
mei_hdr.length = length;
mei_hdr.msg_complete = 1;
}
mei_hdr.host_addr = cl->host_client_id;
mei_hdr.me_addr = cl->me_client_id;
mei_hdr.reserved = 0;
dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
*((u32 *) &mei_hdr));
if (mei_write_message(dev, &mei_hdr,
(unsigned char *) (write_cb->request_buffer.data),
mei_hdr.length)) {
rets = -ENODEV;
goto unlock_dev;
}
if (rets == 0 || dev->mei_host_buffer_is_empty == false) {
write_cb->buf_idx = 0;
mei_hdr.msg_complete = 0;
cl->writing_state = MEI_WRITING;
write_cb->information = mei_hdr.length;
if (mei_hdr.msg_complete) {
if (mei_flow_ctrl_reduce(dev, cl)) {
rets = -ENODEV;
goto unlock_dev;
}
list_add_tail(&write_cb->cb_list,
&dev->write_waiting_list.mei_cb.cb_list);
} else {
list_add_tail(&write_cb->cb_list,
&dev->write_list.mei_cb.cb_list);
}
} else {
write_cb->information = 0;
cl->writing_state = MEI_WRITING;
list_add_tail(&write_cb->cb_list,
&dev->write_list.mei_cb.cb_list);
goto out;
}
dev->mei_host_buffer_is_empty = false;
if (length > mei_hbuf_max_data(dev)) {
mei_hdr.length = mei_hbuf_max_data(dev);
mei_hdr.msg_complete = 0;
} else {
mei_hdr.length = length;
mei_hdr.msg_complete = 1;
}
mei_hdr.host_addr = cl->host_client_id;
mei_hdr.me_addr = cl->me_client_id;
mei_hdr.reserved = 0;
dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
*((u32 *) &mei_hdr));
if (mei_write_message(dev, &mei_hdr,
write_cb->request_buffer.data, mei_hdr.length)) {
rets = -ENODEV;
goto err;
}
cl->writing_state = MEI_WRITING;
write_cb->buf_idx = mei_hdr.length;
out:
if (mei_hdr.msg_complete) {
if (mei_flow_ctrl_reduce(dev, cl)) {
rets = -ENODEV;
goto err;
}
list_add_tail(&write_cb->list, &dev->write_waiting_list.list);
} else {
list_add_tail(&write_cb->list, &dev->write_list.list);
}
mutex_unlock(&dev->device_lock);
return length;
unlock_dev:
err:
mutex_unlock(&dev->device_lock);
mei_free_cb_private(write_cb);
mei_io_cb_free(write_cb);
return rets;
}
@ -860,15 +694,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
if (cl == &dev->iamthif_cl) {
mutex_unlock(&dev->device_lock);
poll_wait(file, &dev->iamthif_cl.wait, wait);
mutex_lock(&dev->device_lock);
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
dev->iamthif_file_object == file) {
mask |= (POLLIN | POLLRDNORM);
dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
mei_run_next_iamthif_cmd(dev);
}
mask = mei_amthif_poll(dev, file, wait);
goto out;
}
@ -917,7 +743,7 @@ static struct miscdevice mei_misc_device = {
*
* returns true if ME Interface is valid, false otherwise
*/
static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
static bool mei_quirk_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
u32 reg;
@ -939,7 +765,7 @@ static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
*
* returns 0 on success, <0 on failure.
*/
static int __devinit mei_probe(struct pci_dev *pdev,
static int mei_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct mei_device *dev;
@ -1003,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev,
goto disable_msi;
}
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
INIT_WORK(&dev->init_work, mei_host_client_init);
if (mei_hw_init(dev)) {
dev_err(&pdev->dev, "init hw failure.\n");
err = -ENODEV;
@ -1054,7 +882,7 @@ end:
* mei_remove is called by the PCI subsystem to alert the driver
* that it should release a PCI device.
*/
static void __devexit mei_remove(struct pci_dev *pdev)
static void mei_remove(struct pci_dev *pdev)
{
struct mei_device *dev;
@ -1087,8 +915,8 @@ static void __devexit mei_remove(struct pci_dev *pdev)
/* remove entry if already in list */
dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
mei_me_cl_unlink(dev, &dev->wd_cl);
mei_me_cl_unlink(dev, &dev->iamthif_cl);
dev->iamthif_current_cb = NULL;
dev->me_clients_num = 0;
@ -1195,8 +1023,8 @@ static struct pci_driver mei_driver = {
.name = KBUILD_MODNAME,
.id_table = mei_pci_tbl,
.probe = mei_probe,
.remove = __devexit_p(mei_remove),
.shutdown = __devexit_p(mei_remove),
.remove = mei_remove,
.shutdown = mei_remove,
.driver.pm = MEI_PM_OPS,
};

View File

@ -19,6 +19,7 @@
#include <linux/types.h>
#include <linux/watchdog.h>
#include <linux/poll.h>
#include <linux/mei.h>
#include "hw.h"
@ -125,13 +126,20 @@ enum mei_wd_states {
MEI_WD_STOPPING,
};
/* MEI CB */
enum mei_cb_major_types {
MEI_READ = 0,
MEI_WRITE,
MEI_IOCTL,
MEI_OPEN,
MEI_CLOSE
/**
* enum mei_cb_file_ops - file operation associated with the callback
* @MEI_FOP_READ - read
* @MEI_FOP_WRITE - write
* @MEI_FOP_IOCTL - ioctl
* @MEI_FOP_OPEN - open
* @MEI_FOP_CLOSE - close
*/
enum mei_cb_file_ops {
MEI_FOP_READ = 0,
MEI_FOP_WRITE,
MEI_FOP_IOCTL,
MEI_FOP_OPEN,
MEI_FOP_CLOSE
};
/*
@ -143,13 +151,21 @@ struct mei_message_data {
};
struct mei_cl;
/**
* struct mei_cl_cb - file operation callback structure
*
* @cl - file client who is running this operation
* @fop_type - file operation type
*/
struct mei_cl_cb {
struct list_head cb_list;
enum mei_cb_major_types major_file_operations;
void *file_private;
struct list_head list;
struct mei_cl *cl;
enum mei_cb_file_ops fop_type;
struct mei_message_data request_buffer;
struct mei_message_data response_buffer;
unsigned long information;
unsigned long buf_idx;
unsigned long read_time;
struct file *file_object;
};
@ -175,29 +191,23 @@ struct mei_cl {
struct mei_cl_cb *read_cb;
};
struct mei_io_list {
struct mei_cl_cb mei_cb;
};
/**
* struct mei_deive - MEI private device struct
* struct mei_device - MEI private device struct
* @hbuf_depth - depth of host(write) buffer
* @wr_ext_msg - buffer for hbm control responses (set in read cycle)
*/
struct mei_device {
struct pci_dev *pdev; /* pointer to pci device struct */
/*
* lists of queues
*/
/* array of pointers to aio lists */
struct mei_io_list read_list; /* driver read queue */
struct mei_io_list write_list; /* driver write queue */
struct mei_io_list write_waiting_list; /* write waiting queue */
struct mei_io_list ctrl_wr_list; /* managed write IOCTL list */
struct mei_io_list ctrl_rd_list; /* managed read IOCTL list */
struct mei_io_list amthi_cmd_list; /* amthi list for cmd waiting */
/* array of pointers to aio lists */
struct mei_cl_cb read_list; /* driver read queue */
struct mei_cl_cb write_list; /* driver write queue */
struct mei_cl_cb write_waiting_list; /* write waiting queue */
struct mei_cl_cb ctrl_wr_list; /* managed write IOCTL list */
struct mei_cl_cb ctrl_rd_list; /* managed read IOCTL list */
/* driver managed amthi list for reading completed amthi cmd data */
struct mei_io_list amthi_read_complete_list;
/*
* list of files
*/
@ -235,11 +245,13 @@ struct mei_device {
u16 init_clients_timer;
bool need_reset;
u32 extra_write_index;
unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */
u32 wr_msg_buf[128]; /* used for control messages */
u32 ext_msg_buf[8]; /* for control responses */
u32 rd_msg_hdr;
u32 wr_msg_buf[128]; /* used for control messages */
struct {
struct mei_msg_hdr hdr;
unsigned char data[4]; /* All HBM messages are 4 bytes */
} wr_ext_msg; /* for control responses */
struct hbm_version version;
@ -253,12 +265,15 @@ struct mei_device {
struct mei_cl wd_cl;
enum mei_wd_states wd_state;
bool wd_interface_reg;
bool wd_pending;
u16 wd_timeout;
unsigned char wd_data[MEI_WD_START_MSG_SIZE];
/* amthif list for cmd waiting */
struct mei_cl_cb amthif_cmd_list;
/* driver managed amthif list for reading completed amthif cmd data */
struct mei_cl_cb amthif_rd_complete_list;
struct file *iamthif_file_object;
struct mei_cl iamthif_cl;
struct mei_cl_cb *iamthif_current_cb;
@ -272,8 +287,15 @@ struct mei_device {
bool iamthif_flow_control_pending;
bool iamthif_ioctl;
bool iamthif_canceled;
struct work_struct init_work;
};
static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
{
return msecs_to_jiffies(sec * MSEC_PER_SEC);
}
/*
* mei init function prototypes
@ -284,21 +306,34 @@ int mei_hw_init(struct mei_device *dev);
int mei_task_initialize_clients(void *data);
int mei_initialize_clients(struct mei_device *dev);
int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
void mei_host_init_iamthif(struct mei_device *dev);
void mei_allocate_me_clients_storage(struct mei_device *dev);
int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
const uuid_le *cguid, u8 host_client_id);
void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl);
int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid);
int mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
/*
* MEI IO List Functions
* MEI IO Functions
*/
void mei_io_list_init(struct mei_io_list *list);
void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
void mei_io_cb_free(struct mei_cl_cb *priv_cb);
int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length);
int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length);
/**
* mei_io_list_init - Sets up a queue list.
*
* @list: An instance cl callback structure
*/
static inline void mei_io_list_init(struct mei_cl_cb *list)
{
INIT_LIST_HEAD(&list->list);
}
void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl);
/*
* MEI ME Client Functions
@ -330,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
*/
void mei_host_start_message(struct mei_device *dev);
void mei_host_enum_clients_message(struct mei_device *dev);
int mei_host_client_properties(struct mei_device *dev);
int mei_host_client_enumerate(struct mei_device *dev);
void mei_host_client_init(struct work_struct *work);
/*
* MEI interrupt functions prototype
@ -347,18 +383,40 @@ int mei_ioctl_connect_client(struct file *file,
int mei_start_read(struct mei_device *dev, struct mei_cl *cl);
int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
int amthi_read(struct mei_device *dev, struct file *file,
char __user *ubuf, size_t length, loff_t *offset);
/*
* AMTHIF - AMT Host Interface Functions
*/
void mei_amthif_reset_params(struct mei_device *dev);
struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
void mei_amthif_host_init(struct mei_device *dev);
int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
int mei_amthif_read(struct mei_device *dev, struct file *file,
char __user *ubuf, size_t length, loff_t *offset);
unsigned int mei_amthif_poll(struct mei_device *dev,
struct file *file, poll_table *wait);
int mei_amthif_release(struct mei_device *dev, struct file *file);
struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
struct file *file);
void mei_run_next_iamthif_cmd(struct mei_device *dev);
void mei_amthif_run_next_cmd(struct mei_device *dev);
void mei_free_cb_private(struct mei_cl_cb *priv_cb);
int mei_amthif_read_message(struct mei_cl_cb *complete_list,
struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list);
void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
/*
* Register Access Function
@ -437,4 +495,15 @@ void mei_csr_clear_his(struct mei_device *dev);
void mei_enable_interrupts(struct mei_device *dev);
void mei_disable_interrupts(struct mei_device *dev);
static inline struct mei_msg_hdr *mei_hbm_hdr(u32 *buf, size_t length)
{
struct mei_msg_hdr *hdr = (struct mei_msg_hdr *)buf;
hdr->host_addr = 0;
hdr->me_addr = 0;
hdr->length = length;
hdr->msg_complete = 1;
hdr->reserved = 0;
return hdr;
}
#endif

View File

@ -62,6 +62,7 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
*/
int mei_wd_host_init(struct mei_device *dev)
{
int id;
mei_cl_init(&dev->wd_cl, dev);
/* look for WD client and connect to it */
@ -69,12 +70,11 @@ int mei_wd_host_init(struct mei_device *dev)
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
dev->wd_state = MEI_WD_IDLE;
/* find ME WD client */
mei_me_cl_update_filext(dev, &dev->wd_cl,
/* Connect WD ME client to the host client */
id = mei_me_cl_link(dev, &dev->wd_cl,
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
dev_dbg(&dev->pdev->dev, "wd: check client\n");
if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
if (id < 0) {
dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
return -ENOENT;
}
@ -85,7 +85,7 @@ int mei_wd_host_init(struct mei_device *dev)
dev->wd_cl.host_client_id = 0;
return -EIO;
}
dev->wd_cl.timer_count = CONNECT_TIMEOUT;
dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT;
return 0;
}
@ -360,23 +360,20 @@ void mei_watchdog_register(struct mei_device *dev)
if (watchdog_register_device(&amt_wd_dev)) {
dev_err(&dev->pdev->dev,
"wd: unable to register watchdog device.\n");
dev->wd_interface_reg = false;
return;
}
dev_dbg(&dev->pdev->dev,
"wd: successfully register watchdog interface.\n");
dev->wd_interface_reg = true;
watchdog_set_drvdata(&amt_wd_dev, dev);
}
void mei_watchdog_unregister(struct mei_device *dev)
{
if (!dev->wd_interface_reg)
if (test_bit(WDOG_UNREGISTERED, &amt_wd_dev.status))
return;
watchdog_set_drvdata(&amt_wd_dev, NULL);
watchdog_unregister_device(&amt_wd_dev);
dev->wd_interface_reg = false;
}

View File

@ -666,7 +666,7 @@ static struct bin_attribute pch_bin_attr = {
.write = pch_phub_bin_write,
};
static int __devinit pch_phub_probe(struct pci_dev *pdev,
static int pch_phub_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int retval;
@ -819,7 +819,7 @@ err_pci_enable_dev:
return ret;
}
static void __devexit pch_phub_remove(struct pci_dev *pdev)
static void pch_phub_remove(struct pci_dev *pdev)
{
struct pch_phub_reg *chip = pci_get_drvdata(pdev);
@ -888,7 +888,7 @@ static struct pci_driver pch_phub_driver = {
.name = "pch_phub",
.id_table = pch_phub_pcidev_id,
.probe = pch_phub_probe,
.remove = __devexit_p(pch_phub_remove),
.remove = pch_phub_remove,
.suspend = pch_phub_suspend,
.resume = pch_phub_resume
};

View File

@ -324,7 +324,7 @@ static irqreturn_t phantom_isr(int irq, void *data)
* Init and deinit driver
*/
static unsigned int __devinit phantom_get_free(void)
static unsigned int phantom_get_free(void)
{
unsigned int i;
@ -335,7 +335,7 @@ static unsigned int __devinit phantom_get_free(void)
return i;
}
static int __devinit phantom_probe(struct pci_dev *pdev,
static int phantom_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
struct phantom_device *pht;
@ -435,7 +435,7 @@ err:
return retval;
}
static void __devexit phantom_remove(struct pci_dev *pdev)
static void phantom_remove(struct pci_dev *pdev)
{
struct phantom_device *pht = pci_get_drvdata(pdev);
unsigned int minor = MINOR(pht->cdev.dev);
@ -487,7 +487,7 @@ static int phantom_resume(struct pci_dev *pdev)
#define phantom_resume NULL
#endif
static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
static struct pci_device_id phantom_pci_tbl[] = {
{ .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
.subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
.class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
@ -499,7 +499,7 @@ static struct pci_driver phantom_pci_driver = {
.name = "phantom",
.id_table = phantom_pci_tbl,
.probe = phantom_probe,
.remove = __devexit_p(phantom_remove),
.remove = phantom_remove,
.suspend = phantom_suspend,
.resume = phantom_resume
};

View File

@ -76,7 +76,7 @@ struct pti_dev {
*/
static DEFINE_MUTEX(alloclock);
static const struct pci_device_id pci_ids[] __devinitconst = {
static const struct pci_device_id pci_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
{0}
};
@ -796,7 +796,7 @@ static const struct tty_port_operations tty_port_ops = {
* 0 for success
* otherwise, error
*/
static int __devinit pti_pci_probe(struct pci_dev *pdev,
static int pti_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
unsigned int a;
@ -879,7 +879,7 @@ err:
* PCI bus.
* @pdev: variable containing pci info of PTI.
*/
static void __devexit pti_pci_remove(struct pci_dev *pdev)
static void pti_pci_remove(struct pci_dev *pdev)
{
struct pti_dev *drv_data = pci_get_drvdata(pdev);
@ -901,7 +901,7 @@ static struct pci_driver pti_pci_driver = {
.name = PCINAME,
.id_table = pci_ids,
.probe = pti_pci_probe,
.remove = __devexit_p(pti_pci_remove),
.remove = pti_pci_remove,
};
/**

Some files were not shown because too many files have changed in this diff Show More