Commit 1071ec7b authored by Linus Torvalds's avatar Linus Torvalds

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

Pull char/misc patches from Greg KH:
 "Here's the big char/misc driver patchset for 3.13-rc1.

  Lots of stuff in here, including some new drivers for Intel's "MIC"
  co-processor devices, and a new eeprom driver.  Other things include
  the driver attribute cleanups, extcon driver updates, hyperv updates,
  and a raft of other miscellaneous driver fixes.

  All of these have been in linux-next for a while"

* tag 'char-misc-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (121 commits)
  misc: mic: Fixes for randconfig build errors and warnings.
  tifm: fix error return code in tifm_7xx1_probe()
  w1-gpio: Use devm_* functions
  w1-gpio: Detect of_gpio_error for first gpio
  uio: Pass pointers to virt_to_page(), not integers
  uio: fix memory leak
  misc/at24: avoid infinite loop on write()
  misc/93xx46: avoid infinite loop on write()
  misc: atmel_pwm: add deferred-probing support
  mei: wd: host_init propagate error codes from called functions
  mei: replace stray pr_debug with dev_dbg
  mei: bus: propagate error code returned by mei_me_cl_by_id
  mei: mei_cl_link remove duplicated check for open_handle_count
  mei: print correct device state during unexpected reset
  mei: nfc: fix memory leak in error path
  lkdtm: add tests for additional page permissions
  lkdtm: adjust recursion size to avoid warnings
  lkdtm: isolate stack corruption test
  mei: move host_clients_map cleanup to device init
  mei: me: downgrade two errors to debug level
  ...
parents c287322c 42579226
What: /sys/class/mic/
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
The mic class directory belongs to Intel MIC devices and
provides information per MIC device. An Intel MIC device is a
PCIe form factor add-in Coprocessor card based on the Intel Many
Integrated Core (MIC) architecture that runs a Linux OS.
What: /sys/class/mic/mic(x)
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
The directories /sys/class/mic/mic0, /sys/class/mic/mic1 etc.,
represent MIC devices (0,1,..etc). Each directory has
information specific to that MIC device.
What: /sys/class/mic/mic(x)/family
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
Provides information about the Coprocessor family for an Intel
MIC device. For example - "x100"
What: /sys/class/mic/mic(x)/stepping
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
Provides information about the silicon stepping for an Intel
MIC device. For example - "A0" or "B0"
What: /sys/class/mic/mic(x)/state
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
When read, this entry provides the current state of an Intel
MIC device in the context of the card OS. Possible values that
will be read are:
"offline" - The MIC device is ready to boot the card OS. On
reading this entry after an OSPM resume, a "boot" has to be
written to this entry if the card was previously shutdown
during OSPM suspend.
"online" - The MIC device has initiated booting a card OS.
"shutting_down" - The card OS is shutting down.
"reset_failed" - The MIC device has failed to reset.
"suspending" - The MIC device is currently being prepared for
suspend. On reading this entry, a "suspend" has to be written
to the state sysfs entry to ensure the card is shutdown during
OSPM suspend.
"suspended" - The MIC device has been suspended.
When written, this sysfs entry triggers different state change
operations depending upon the current state of the card OS.
Acceptable values are:
"boot" - Boot the card OS image specified by the combination
of firmware, ramdisk, cmdline and bootmode
sysfs entries.
"reset" - Initiates device reset.
"shutdown" - Initiates card OS shutdown.
"suspend" - Initiates card OS shutdown and also marks the card
as suspended.
What: /sys/class/mic/mic(x)/shutdown_status
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
An Intel MIC device runs a Linux OS during its operation. This
OS can shutdown because of various reasons. When read, this
entry provides the status on why the card OS was shutdown.
Possible values are:
"nop" - shutdown status is not applicable, when the card OS is
"online"
"crashed" - Shutdown because of a HW or SW crash.
"halted" - Shutdown because of a halt command.
"poweroff" - Shutdown because of a poweroff command.
"restart" - Shutdown because of a restart command.
What: /sys/class/mic/mic(x)/cmdline
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
An Intel MIC device runs a Linux OS during its operation. Before
booting this card OS, it is possible to pass kernel command line
options to configure various features in it, similar to
self-bootable machines. When read, this entry provides
information about the current kernel command line options set to
boot the card OS. This entry can be written to change the
existing kernel command line options. Typically, the user would
want to read the current command line options, append new ones
or modify existing ones and then write the whole kernel command
line back to this entry.
What: /sys/class/mic/mic(x)/firmware
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
When read, this sysfs entry provides the path name under
/lib/firmware/ where the firmware image to be booted on the
card can be found. The entry can be written to change the
firmware image location under /lib/firmware/.
What: /sys/class/mic/mic(x)/ramdisk
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
When read, this sysfs entry provides the path name under
/lib/firmware/ where the ramdisk image to be used during card
OS boot can be found. The entry can be written to change
the ramdisk image location under /lib/firmware/.
What: /sys/class/mic/mic(x)/bootmode
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
When read, this sysfs entry provides the current bootmode for
the card. This sysfs entry can be written with the following
valid strings:
a) linux - Boot a Linux image.
b) elf - Boot an elf image for flash updates.
What: /sys/class/mic/mic(x)/log_buf_addr
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
An Intel MIC device runs a Linux OS during its operation. For
debugging purpose and early kernel boot messages, the user can
access the card OS log buffer via debugfs. When read, this entry
provides the kernel virtual address of the buffer where the card
OS log buffer can be read. This entry is written by the host
configuration daemon to set the log buffer address. The correct
log buffer address to be written can be found in the System.map
file of the card OS.
What: /sys/class/mic/mic(x)/log_buf_len
Date: October 2013
KernelVersion: 3.13
Contact: Sudeep Dutt <sudeep.dutt@intel.com>
Description:
An Intel MIC device runs a Linux OS during its operation. For
debugging purpose and early kernel boot messages, the user can
access the card OS log buffer via debugfs. When read, this entry
provides the kernel virtual address where the card OS log buffer
length can be read. This entry is written by host configuration
daemon to set the log buffer length address. The correct log
buffer length address to be written can be found in the
System.map file of the card OS.
What: /sys/devices/*/<our-device>/eeprom
Date: August 2013
Contact: Oliver Schinagl <oliver@schinagl.nl>
Description: read-only access to the SID (Security-ID) on current
A-series SoC's from Allwinner. Currently supports A10, A10s, A13
and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
whereas the newer A20 SoC exposes 512 bytes split into sections.
Besides the 16 bytes of SID, there's also an SJTAG area,
HDMI-HDCP key and some custom keys. Below a quick overview, for
details see the user manual:
0x000 128 bit root-key (sun[457]i)
0x010 128 bit boot-key (sun7i)
0x020 64 bit security-jtag-key (sun7i)
0x028 16 bit key configuration (sun7i)
0x02b 16 bit custom-vendor-key (sun7i)
0x02c 320 bit low general key (sun7i)
0x040 32 bit read-control access (sun7i)
0x064 224 bit low general key (sun7i)
0x080 2304 bit HDCP-key (sun7i)
0x1a0 768 bit high general key (sun7i)
Users: any user space application which wants to read the SID on
Allwinner's A-series of CPU's.
Allwinner sunxi-sid
Required properties:
- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid".
- reg: Should contain registers location and length
Example for sun4i:
sid@01c23800 {
compatible = "allwinner,sun4i-sid";
reg = <0x01c23800 0x10>
};
Example for sun7i:
sid@01c23800 {
compatible = "allwinner,sun7i-a20-sid";
reg = <0x01c23800 0x200>
};
TI DAC7512 DEVICETREE BINDINGS
Required properties:
- "compatible" Must be set to "ti,dac7512"
Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
apply. In particular, "reg" and "spi-max-frequency" properties must be given.
Example:
spi_master {
dac7512: dac7512@0 {
compatible = "ti,dac7512";
reg = <0>; /* CS0 */
spi-max-frequency = <1000000>;
};
};
......@@ -25,8 +25,10 @@ MyungJoo Ham <myungjoo.ham@samsung.com>
@print_state: no change but type change (switch_dev->extcon_dev)
- switch_dev_register(sdev, dev)
=> extcon_dev_register(edev, dev)
: no change but type change (sdev->edev)
=> extcon_dev_register(edev)
: type change (sdev->edev)
: remove second param('dev'). if edev has parent device, should store
'dev' to 'edev.dev.parent' before registering extcon device
- switch_dev_unregister(sdev)
=> extcon_dev_unregister(edev)
: no change but type change (sdev->edev)
......
An Intel MIC X100 device is a PCIe form factor add-in coprocessor
card based on the Intel Many Integrated Core (MIC) architecture
that runs a Linux OS. It is a PCIe endpoint in a platform and therefore
implements the three required standard address spaces i.e. configuration,
memory and I/O. The host OS loads a device driver as is typical for
PCIe devices. The card itself runs a bootstrap after reset that
transfers control to the card OS downloaded from the host driver. The
host driver supports OSPM suspend and resume operations. It shuts down
the card during suspend and reboots the card OS during resume.
The card OS as shipped by Intel is a Linux kernel with modifications
for the X100 devices.
Since it is a PCIe card, it does not have the ability to host hardware
devices for networking, storage and console. We provide these devices
on X100 coprocessors thus enabling a self-bootable equivalent environment
for applications. A key benefit of our solution is that it leverages
the standard virtio framework for network, disk and console devices,
though in our case the virtio framework is used across a PCIe bus.
Here is a block diagram of the various components described above. The
virtio backends are situated on the host rather than the card given better
single threaded performance for the host compared to MIC, the ability of
the host to initiate DMA's to/from the card using the MIC DMA engine and
the fact that the virtio block storage backend can only be on the host.
|
+----------+ | +----------+
| Card OS | | | Host OS |
+----------+ | +----------+
|
+-------+ +--------+ +------+ | +---------+ +--------+ +--------+
| Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio |
| Net | |Console | |Block | | |Net | |Console | |Block |
| Driver| |Driver | |Driver| | |backend | |backend | |backend |
+-------+ +--------+ +------+ | +---------+ +--------+ +--------+
| | | | | | |
| | | |User | | |
| | | |------|------------|---------|-------
+-------------------+ |Kernel +--------------------------+
| | | Virtio over PCIe IOCTLs |
| | +--------------------------+
+--------------+ | |
|Intel MIC | | +---------------+
|Card Driver | | |Intel MIC |
+--------------+ | |Host Driver |
| | +---------------+
| | |
+-------------------------------------------------------------+
| |
| PCIe Bus |
+-------------------------------------------------------------+
#
# Makefile - Intel MIC User Space Tools.
# Copyright(c) 2013, Intel Corporation.
#
ifdef DEBUG
CFLAGS += $(USERWARNFLAGS) -I. -g -Wall -DDEBUG=$(DEBUG)
else
CFLAGS += $(USERWARNFLAGS) -I. -g -Wall
endif
mpssd: mpssd.o sysfs.o
$(CC) $(CFLAGS) -o $@ $^ -lpthread
install:
install mpssd /usr/sbin/mpssd
install micctrl /usr/sbin/micctrl
clean:
rm -f mpssd *.o
#!/bin/bash
# Intel MIC Platform Software Stack (MPSS)
#
# Copyright(c) 2013 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# 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.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
#
# Intel MIC User Space Tools.
#
# micctrl - Controls MIC boot/start/stop.
#
# chkconfig: 2345 95 05
# description: start MPSS stack processing.
#
### BEGIN INIT INFO
# Provides: micctrl
### END INIT INFO
# Source function library.
. /etc/init.d/functions
sysfs="/sys/class/mic"
_status()
{
f=$sysfs/$1
echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`"
}
status()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_status $1
return $?
fi
for f in $sysfs/*
do
_status `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_reset()
{
f=$sysfs/$1
echo reset > $f/state
}
reset()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_reset $1
return $?
fi
for f in $sysfs/*
do
_reset `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_boot()
{
f=$sysfs/$1
echo "linux" > $f/bootmode
echo "mic/uos.img" > $f/firmware
echo "mic/$1.image" > $f/ramdisk
echo "boot" > $f/state
}
boot()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_boot $1
return $?
fi
for f in $sysfs/*
do
_boot `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_shutdown()
{
f=$sysfs/$1
echo shutdown > $f/state
}
shutdown()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_shutdown $1
return $?
fi
for f in $sysfs/*
do
_shutdown `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_wait()
{
f=$sysfs/$1
while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ]
do
sleep 1
echo -e "Waiting for $1 to go offline"
done
}
wait()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_wait $1
return $?
fi
# Wait for the cards to go offline
for f in $sysfs/*
do
_wait `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
if [ ! -d "$sysfs" ]; then
echo -e $"Module unloaded "
exit 3
fi
case $1 in
-s)
status $2
;;
-r)
reset $2
;;
-b)
boot $2
;;
-S)
shutdown $2
;;
-w)
wait $2
;;
*)
echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}"
exit 2
esac
exit $?
#!/bin/bash
# Intel MIC Platform Software Stack (MPSS)
#
# Copyright(c) 2013 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# 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.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
#
# Intel MIC User Space Tools.
#
# mpss Start mpssd.
#
# chkconfig: 2345 95 05
# description: start MPSS stack processing.
#
### BEGIN INIT INFO
# Provides: mpss
# Required-Start:
# Required-Stop:
# Short-Description: MPSS stack control
# Description: MPSS stack control
### END INIT INFO
# Source function library.
. /etc/init.d/functions
exec=/usr/sbin/mpssd
sysfs="/sys/class/mic"
start()
{
[ -x $exec ] || exit 5
if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then
echo -e $"MPSSD already running! "
success
echo
return 0
fi
echo -e $"Starting MPSS Stack"
echo -e $"Loading MIC_HOST Module"
# Ensure the driver is loaded
if [ ! -d "$sysfs" ]; then
modprobe mic_host
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
failure
echo
return $RETVAL
fi
fi
# Start the daemon
echo -n $"Starting MPSSD "
$exec
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
failure
echo
return $RETVAL
fi
success
echo
sleep 5
# Boot the cards
micctrl -b
# Wait till ping works
for f in $sysfs/*
do
count=100
ipaddr=`cat $f/cmdline`
ipaddr=${ipaddr#*address,}
ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1`
while [ $count -ge 0 ]
do
echo -e "Pinging "`basename $f`" "
ping -c 1 $ipaddr &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
success
break
fi
sleep 1
count=`expr $count - 1`
done
[ $RETVAL -ne 0 ] && failure || success
echo
done
return $RETVAL
}
stop()
{
echo -e $"Shutting down MPSS Stack: "
# Bail out if module is unloaded
if [ ! -d "$sysfs" ]; then
echo -n $"Module unloaded "
success
echo
return 0
fi
# Shut down the cards.
micctrl -S
# Wait for the cards to go offline
for f in $sysfs/*
do
while [ "`cat $f/state`" != "offline" ]
do
sleep 1
echo -e "Waiting for "`basename $f`" to go offline"
done
done
# Display the status of the cards
micctrl -s
# Kill MPSSD now
echo -n $"Killing MPSSD"
killall -9 mpssd 2>/dev/null
RETVAL=$?
[ $RETVAL -ne 0 ] && failure || success
echo
return $RETVAL
}
restart()
{
stop
sleep 5
start
}
status()
{
micctrl -s
if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then
echo "mpssd is running"
else
echo "mpssd is stopped"
fi
return 0
}
unload()
{
if [ ! -d "$sysfs" ]; then
echo -n $"No MIC_HOST Module: "
success
echo
return
fi
stop
sleep 5
echo -n $"Removing MIC_HOST Module: "
modprobe -r mic_host
RETVAL=$?
[ $RETVAL -ne 0 ] && failure || success
echo
return $RETVAL
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
unload)
unload
;;
*)
echo $"Usage: $0 {start|stop|restart|status|unload}"
exit 2
esac
exit $?
This diff is collapsed.
/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* 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.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Intel MIC User Space Tools.
*/
#ifndef _MPSSD_H_
#define _MPSSD_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <libgen.h>
#include <pthread.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include <sys/dir.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#include <limits.h>
#include <syslog.h>
#include <getopt.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <linux/if_tun.h>
#include <linux/virtio_ids.h>
#define MICSYSFSDIR "/sys/class/mic"
#define LOGFILE_NAME "/var/log/mpssd"
#define PAGE_SIZE 4096
struct mic_console_info {
pthread_t console_thread;
int virtio_console_fd;
void *console_dp;
};
struct mic_net_info {
pthread_t net_thread;
int virtio_net_fd;
int tap_fd;
void *net_dp;
};
struct mic_virtblk_info {
pthread_t block_thread;
int virtio_block_fd;
void *block_dp;
volatile sig_atomic_t signaled;
char *backend_file;
int backend;
void *backend_addr;
long backend_size;
};
struct mic_info {
int id;
char *name;
pthread_t config_thread;
pid_t pid;
struct mic_console_info mic_console;
struct mic_net_info mic_net;
struct mic_virtblk_info mic_virtblk;
int restart;
int boot_on_resume;
struct mic_info *next;
};
__attribute__((format(printf, 1, 2)))
void mpsslog(char *format, ...);
char *readsysfs(char *dir, char *entry);
int setsysfs(char *dir, char *entry, char *value);
#endif
/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* 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.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Intel MIC User Space Tools.
*/
#include "mpssd.h"
#define PAGE_SIZE 4096
char *
readsysfs(char *dir, char *entry)
{
char filename[PATH_MAX];
char value[PAGE_SIZE];
char *string = NULL;
int fd;
int len;
if (dir == NULL)
snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
else
snprintf(filename, PATH_MAX,
"%s/%s/%s", MICSYSFSDIR, dir, entry);
fd = open(filename, O_RDONLY);
if (fd < 0) {
mpsslog("Failed to open sysfs entry '%s': %s\n",
filename, strerror(errno));
return NULL;
}
len = read(fd, value, sizeof(value));
if (len < 0) {
mpsslog("Failed to read sysfs entry '%s': %s\n",
filename, strerror(errno));
goto readsys_ret;
}
if (len == 0)
goto readsys_ret;
value[len - 1] = '\0';
string = malloc(strlen(value) + 1);
if (string)
strcpy(string, value);
readsys_ret:
close(fd);
return string;
}
int
setsysfs(char *dir, char *entry, char *value)
{
char filename[PATH_MAX];
char *oldvalue;
int fd, ret = 0;
if (dir == NULL)
snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
else
snprintf(filename, PATH_MAX, "%s/%s/%s",
MICSYSFSDIR, dir, entry);
oldvalue = readsysfs(dir, entry);
fd = open(filename, O_RDWR);
if (fd < 0) {
ret = errno;
mpsslog("Failed to open sysfs entry '%s': %s\n",
filename, strerror(errno));
goto done;
}
if (!oldvalue || strcmp(value, oldvalue)) {
if (write(fd, value, strlen(value)) < 0) {
ret = errno;
mpsslog("Failed to write new sysfs entry '%s': %s\n",
filename, strerror(errno));
}
}
close(fd);
done:
if (oldvalue)
free(oldvalue);
return ret;
}
......@@ -486,8 +486,7 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
}
sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
irq_flags = devp->hd_flags & HPET_SHARED_IRQ
? IRQF_SHARED : IRQF_DISABLED;
irq_flags = devp->hd_flags & HPET_SHARED_IRQ ? IRQF_SHARED : 0;
if (request_irq(irq, hpet_interrupt, irq_flags,
devp->hd_name, (void *)devp)) {
printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
......@@ -971,8 +970,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
struct acpi_resource_fixed_memory32 *fixmem32;
fixmem32 = &res->data.fixed_memory32;
if (!fixmem32)
return AE_NO_MEMORY;
hdp->hd_phys_address = fixmem32->address;
hdp->hd_address = ioremap(fixmem32->address,
......
......@@ -193,8 +193,8 @@ int misc_register(struct miscdevice * misc)
if (misc->minor == MISC_DYNAMIC_MINOR) {
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
if (i >= DYNAMIC_MINORS) {
mutex_unlock(&misc_mtx);
return -EBUSY;
err = -EBUSY;
goto out;
}
misc->minor = DYNAMIC_MINORS - i - 1;
set_bit(i, misc_minors);
......@@ -203,8 +203,8 @@ int misc_register(struct miscdevice * misc)
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
mutex_unlock(&misc_mtx);
return -EBUSY;
err = -EBUSY;
goto out;
}
}
}
......
......@@ -220,7 +220,7 @@ static int __init nwbutton_init(void)
return -EBUSY;
}
if (request_irq (IRQ_NETWINDER_BUTTON, button_handler, IRQF_DISABLED,
if (request_irq (IRQ_NETWINDER_BUTTON, button_handler, 0,
"nwbutton", NULL)) {
printk (KERN_WARNING "nwbutton: IRQ %d is not free.\n",
IRQ_NETWINDER_BUTTON);
......
......@@ -227,7 +227,7 @@ static inline unsigned char rtc_is_updating(void)
#ifdef RTC_IRQ
/*
* A very tiny interrupt handler. It runs with IRQF_DISABLED set,
* A very tiny interrupt handler. It runs with interrupts disabled,
* but there is possibility of conflicting with the set_rtc_mmss()
* call (the rtc irq and the timer irq can easily run at the same
* time in two different CPUs). So we need to serialize
......@@ -1040,8 +1040,7 @@ static int __init rtc_init(void)
rtc_int_handler_ptr = rtc_interrupt;
}
if (request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED,
"rtc", NULL)) {
if (request_irq(RTC_IRQ, rtc_int_handler_ptr, 0, "rtc", NULL)) {
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
......
......@@ -108,8 +108,7 @@ scdrv_open(struct inode *inode, struct file *file)
/* hook this subchannel up to the system controller interrupt */
mutex_lock(&scdrv_mutex);
rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
IRQF_SHARED | IRQF_DISABLED,
SYSCTL_BASENAME, sd);
IRQF_SHARED, SYSCTL_BASENAME, sd);
if (rv) {
ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
kfree(sd);
......
......@@ -292,8 +292,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
/* hook event subchannel up to the system controller interrupt */
rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt,
IRQF_SHARED | IRQF_DISABLED,
"system controller events", event_sd);
IRQF_SHARED, "system controller events", event_sd);
if (rv) {
printk(KERN_WARNING "%s: irq request failed (%d)\n",
__func__, rv);
......
......@@ -222,7 +222,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
/* This device is wired through the FPGA IO space of the ATCA blade
* we can't share this IRQ */
result = request_irq(telclk_interrupt, &tlclk_interrupt,
IRQF_DISABLED, "telco_clock", tlclk_interrupt);
0, "telco_clock", tlclk_interrupt);
if (result == -EBUSY)
printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
else
......
......@@ -721,7 +721,7 @@ static int hwicap_remove(struct device *dev)
{
struct hwicap_drvdata *drvdata;
drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);
drvdata = dev_get_drvdata(dev);
if (!drvdata)
return 0;
......@@ -731,7 +731,6 @@ static int hwicap_remove(struct device *dev)
iounmap(drvdata->base_address);
release_mem_region(drvdata->mem_start, drvdata->mem_size);
kfree(drvdata);
dev_set_drvdata(dev, NULL);
mutex_lock(&icap_sem);
probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
......
......@@ -27,16 +27,16 @@
/**
* struct adc_jack_data - internal data for adc_jack device driver
* @edev - extcon device.
* @cable_names - list of supported cables.
* @num_cables - size of cable_names.
* @adc_conditions - list of adc value conditions.
* @num_conditions - size of adc_conditions.
* @irq - irq number of attach/detach event (0 if not exist).
* @handling_delay - interrupt handler will schedule extcon event
* @edev: extcon device.
* @cable_names: list of supported cables.
* @num_cables: size of cable_names.
* @adc_conditions: list of adc value conditions.
* @num_conditions: size of adc_conditions.
* @irq: irq number of attach/detach event (0 if not exist).
* @handling_delay: interrupt handler will schedule extcon event
* handling at handling_delay jiffies.
* @handler - extcon event handler called by interrupt handler.
* @chan - iio channel being queried.
* @handler: extcon event handler called by interrupt handler.
* @chan: iio channel being queried.
*/
struct adc_jack_data {
struct extcon_dev edev;
......@@ -64,7 +64,7 @@ static void adc_jack_handler(struct work_struct *work)
ret = iio_read_channel_raw(data->chan, &adc_val);
if (ret < 0) {
dev_err(data->edev.dev, "read channel() error: %d\n", ret);
dev_err(&data->edev.dev, "read channel() error: %d\n", ret);
return;
}
......@@ -95,7 +95,7 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
static int adc_jack_probe(struct platform_device *pdev)
{
struct adc_jack_data *data;
struct adc_jack_pdata *pdata = pdev->dev.platform_data;
struct adc_jack_pdata *pdata = dev_get_platdata(&pdev->dev);
int i, err = 0;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
......@@ -110,6 +110,7 @@ static int adc_jack_probe(struct platform_device *pdev)
goto out;
}
data->edev.dev.parent = &pdev->dev;
data->edev.supported_cable = pdata->cable_names;
/* Check the length of array and set num_cables */
......@@ -148,7 +149,7 @@ static int adc_jack_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
err = extcon_dev_register(&data->edev, &pdev->dev);
err = extcon_dev_register(&data->edev);
if (err)
goto out;
......
......@@ -86,8 +86,8 @@ struct arizona_extcon_info {
};
static const struct arizona_micd_config micd_default_modes[] = {
{ ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
{ 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
{ ARIZONA_ACCDET_SRC, 1, 0 },
{ 0, 2, 1 },
};
static const struct arizona_micd_range micd_default_ranges[] = {
......@@ -182,7 +182,8 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
info->micd_modes[mode].gpio);
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_BIAS_SRC_MASK,
info->micd_modes[mode].bias);
info->micd_modes[mode].bias <<
ARIZONA_MICD_BIAS_SRC_SHIFT);
regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
......@@ -193,7 +194,7 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
{
switch (info->micd_modes[0].bias >> ARIZONA_MICD_BIAS_SRC_SHIFT) {
switch (info->micd_modes[0].bias) {
case 1:
return "MICBIAS1";
case 2:
......@@ -388,7 +389,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
>> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
(val < 100 || val > 0x3fb)) {
(val < 100 || val >= 0x3fb)) {
range++;
dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
range);
......@@ -401,7 +402,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
}
/* If we go out of range report top of range */
if (val < 100 || val > 0x3fb) {
if (val < 100 || val >= 0x3fb) {
dev_dbg(arizona->dev, "Measurement out of range\n");
return ARIZONA_HPDET_MAX;
}
......@@ -514,7 +515,7 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
}
/*
* If we measure the mic as
* If we measure the mic as high impedance
*/
if (!id_gpio || info->hpdet_res[1] > 50) {
dev_dbg(arizona->dev, "Detected mic\n");
......@@ -564,11 +565,10 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
}
ret = arizona_hpdet_read(info);
if (ret == -EAGAIN) {
if (ret == -EAGAIN)
goto out;
} else if (ret < 0) {
else if (ret < 0)
goto done;
}
reading = ret;
/* Reset back to starting range */
......@@ -578,11 +578,10 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
0);
ret = arizona_hpdet_do_id(info, &reading, &mic);
if (ret == -EAGAIN) {
if (ret == -EAGAIN)
goto out;
} else if (ret < 0) {
else if (ret < 0)
goto done;
}
/* Report high impedence cables as line outputs */
if (reading >= 5000)
......@@ -769,7 +768,8 @@ static void arizona_micd_detect(struct work_struct *work)
for (i = 0; i < 10 && !(val & 0x7fc); i++) {
ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
dev_err(arizona->dev,
"Failed to read MICDET: %d\n", ret);
mutex_unlock(&info->lock);
return;
}
......@@ -777,7 +777,8 @@ static void arizona_micd_detect(struct work_struct *work)
dev_dbg(arizona->dev, "MICDET: %x\n", val);
if (!(val & ARIZONA_MICD_VALID)) {
dev_warn(arizona->dev, "Microphone detection state invalid\n");
dev_warn(arizona->dev,
"Microphone detection state invalid\n");
mutex_unlock(&info->lock);
return;
}
......@@ -973,10 +974,13 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
&info->hpdet_work,
msecs_to_jiffies(HPDET_DEBOUNCE));
if (cancelled_mic)
if (cancelled_mic) {
int micd_timeout = info->micd_timeout;
queue_delayed_work(system_power_efficient_wq,
&info->micd_timeout_work,
msecs_to_jiffies(info->micd_timeout));
msecs_to_jiffies(micd_timeout));
}
goto out;
}
......@@ -1039,6 +1043,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
else
info->micd_timeout = DEFAULT_MICD_TIMEOUT;
out:
/* Clear trig_sts to make sure DCVDD is not forced up */
regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
......@@ -1046,7 +1051,6 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
ARIZONA_JD1_FALL_TRIG_STS |
ARIZONA_JD1_RISE_TRIG_STS);
out:
mutex_unlock(&info->lock);
pm_runtime_mark_last_busy(info->dev);
......@@ -1129,9 +1133,10 @@ static int arizona_extcon_probe(struct platform_device *pdev)
}
info->edev.name = "Headset Jack";
info->edev.dev.parent = arizona->dev;
info->edev.supported_cable = arizona_cable;
ret = extcon_dev_register(&info->edev, arizona->dev);
ret = extcon_dev_register(&info->edev);
if (ret < 0) {
dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
ret);
......
......@@ -105,7 +105,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int i, count = 0;
struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
struct extcon_dev *edev = dev_get_drvdata(dev);
if (edev->print_state) {
int ret = edev->print_state(edev, buf);
......@@ -129,13 +129,12 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
return count;
}
int extcon_set_state(struct extcon_dev *edev, u32 state);
static ssize_t state_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
u32 state;
ssize_t ret = 0;
struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
struct extcon_dev *edev = dev_get_drvdata(dev);
ret = sscanf(buf, "0x%x", &state);
if (ret == 0)
......@@ -153,7 +152,7 @@ static DEVICE_ATTR_RW(state);
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
struct extcon_dev *edev = dev_get_drvdata(dev);
/* Optional callback given by the user */
if (edev->print_name) {
......@@ -162,7 +161,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
return ret;
}
return sprintf(buf, "%s\n", dev_name(edev->dev));
return sprintf(buf, "%s\n", dev_name(&edev->dev));
}
static DEVICE_ATTR_RO(name);
......@@ -227,11 +226,10 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
edev->state |= state & mask;
raw_notifier_call_chain(&edev->nh, old_state, edev);
/* This could be in interrupt handler */
prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
if (prop_buf) {
length = name_show(edev->dev, NULL, prop_buf);
length = name_show(&edev->dev, NULL, prop_buf);
if (length > 0) {
if (prop_buf[length - 1] == '\n')
prop_buf[length - 1] = 0;
......@@ -239,7 +237,7 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
"NAME=%s", prop_buf);
envp[env_offset++] = name_buf;
}
length = state_show(edev->dev, NULL, prop_buf);
length = state_show(&edev->dev, NULL, prop_buf);
if (length > 0) {
if (prop_buf[length - 1] == '\n')
prop_buf[length - 1] = 0;
......@@ -251,14 +249,14 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
/* Unlock early before uevent */
spin_unlock_irqrestore(&edev->lock, flags);
kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp);
kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
free_page((unsigned long)prop_buf);
} else {
/* Unlock early before uevent */
spin_unlock_irqrestore(&edev->lock, flags);
dev_err(edev->dev, "out of memory in extcon_set_state\n");
kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE);
dev_err(&edev->dev, "out of memory in extcon_set_state\n");
kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
}
} else {
/* No changes */
......@@ -340,7 +338,8 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state);
/**
* extcon_set_cable_state_() - Set the status of a specific cable.
* @edev: the extcon device that has the cable.
* @index: cable index that can be retrieved by extcon_find_cable_index().
* @index: cable index that can be retrieved by
* extcon_find_cable_index().
* @cable_state: the new cable status. The default semantics is
* true: attached / false: detached.
*/
......@@ -452,7 +451,8 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
if (!obj->edev)
return -ENODEV;
obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
obj->cable_index = extcon_find_cable_index(obj->edev,
cable_name);
if (obj->cable_index < 0)
return obj->cable_index;
......@@ -460,7 +460,8 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
obj->internal_nb.notifier_call = _call_per_cable;
return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
return raw_notifier_chain_register(&obj->edev->nh,
&obj->internal_nb);
} else {
struct class_dev_iter iter;
struct extcon_dev *extd;
......@@ -470,7 +471,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
return -ENODEV;
class_dev_iter_init(&iter, extcon_class, NULL, NULL);
while ((dev = class_dev_iter_next(&iter))) {
extd = (struct extcon_dev *)dev_get_drvdata(dev);
extd = dev_get_drvdata(dev);
if (extcon_find_cable_index(extd, cable_name) < 0)
continue;
......@@ -556,7 +557,6 @@ static int create_extcon_class(void)
static void extcon_dev_release(struct device *dev)
{
kfree(dev);
}
static const char *muex_name = "mutually_exclusive";
......@@ -567,14 +567,13 @@ static void dummy_sysfs_dev_release(struct device *dev)
/**
* extcon_dev_register() - Register a new extcon device
* @edev : the new extcon device (should be allocated before calling)
* @dev : the parent device for this extcon device.
*
* Among the members of edev struct, please set the "user initializing data"
* in any case and set the "optional callbacks" if required. However, please
* do not set the values of "internal data", which are initialized by
* this function.
*/
int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
int extcon_dev_register(struct extcon_dev *edev)
{
int ret, index = 0;
......@@ -594,19 +593,20 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
}
if (index > SUPPORTED_CABLE_MAX) {
dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n");
dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n");
return -EINVAL;
}
edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (!edev->dev)
return -ENOMEM;
edev->dev->parent = dev;
edev->dev->class = extcon_class;
edev->dev->release = extcon_dev_release;
edev->dev.class = extcon_class;
edev->dev.release = extcon_dev_release;
edev->name = edev->name ? edev->name : dev_name(dev);
dev_set_name(edev->dev, "%s", edev->name);
edev->name = edev->name ? edev->name : dev_name(edev->dev.parent);
if (IS_ERR_OR_NULL(edev->name)) {
dev_err(&edev->dev,
"extcon device name is null\n");
return -EINVAL;
}
dev_set_name(&edev->dev, "%s", edev->name);
if (edev->max_supported) {
char buf[10];
......@@ -714,7 +714,7 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
goto err_alloc_groups;
}
edev->extcon_dev_type.name = dev_name(edev->dev);
edev->extcon_dev_type.name = dev_name(&edev->dev);
edev->extcon_dev_type.release = dummy_sysfs_dev_release;
for (index = 0; index < edev->max_supported; index++)
......@@ -724,25 +724,24 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
edev->extcon_dev_type.groups[index] =
&edev->attr_g_muex;
edev->dev->type = &edev->extcon_dev_type;
edev->dev.type = &edev->extcon_dev_type;
}
ret = device_register(edev->dev);
ret = device_register(&edev->dev);
if (ret) {
put_device(edev->dev);
put_device(&edev->dev);
goto err_dev;
}
#if defined(CONFIG_ANDROID)
if (switch_class)
ret = class_compat_create_link(switch_class, edev->dev,
NULL);
ret = class_compat_create_link(switch_class, &edev->dev, NULL);
#endif /* CONFIG_ANDROID */
spin_lock_init(&edev->lock);
RAW_INIT_NOTIFIER_HEAD(&edev->nh);
dev_set_drvdata(edev->dev, edev);
dev_set_drvdata(&edev->dev, edev);
edev->state = 0;
mutex_lock(&extcon_dev_list_lock);
......@@ -768,7 +767,6 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
if (edev->max_supported)
kfree(edev->cables);
err_sysfs_alloc:
kfree(edev->dev);
return ret;
}
EXPORT_SYMBOL_GPL(extcon_dev_register);
......@@ -788,9 +786,9 @@ void extcon_dev_unregister(struct extcon_dev *edev)
list_del(&edev->entry);
mutex_unlock(&extcon_dev_list_lock);
if (IS_ERR_OR_NULL(get_device(edev->dev))) {
dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
dev_name(edev->dev));
if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
dev_name(&edev->dev));
return;
}
......@@ -812,10 +810,10 @@ void extcon_dev_unregister(struct extcon_dev *edev)
#if defined(CONFIG_ANDROID)
if (switch_class)
class_compat_remove_link(switch_class, edev->dev, NULL);
class_compat_remove_link(switch_class, &edev->dev, NULL);
#endif
device_unregister(edev->dev);
put_device(edev->dev);
device_unregister(&edev->dev);
put_device(&edev->dev);
}
EXPORT_SYMBOL_GPL(extcon_dev_unregister);
......
......@@ -34,6 +34,7 @@
struct gpio_extcon_data {
struct extcon_dev edev;
unsigned gpio;
bool gpio_active_low;
const char *state_on;
const char *state_off;
int irq;
......@@ -49,6 +50,8 @@ static void gpio_extcon_work(struct work_struct *work)
work);
state = gpio_get_value(data->gpio);
if (data->gpio_active_low)
state = !state;
extcon_set_state(&data->edev, state);
}
......@@ -78,9 +81,9 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_extcon_data *extcon_data;
int ret = 0;
int ret;
if (!pdata)
return -EBUSY;
......@@ -95,14 +98,22 @@ static int gpio_extcon_probe(struct platform_device *pdev)
return -ENOMEM;
extcon_data->edev.name = pdata->name;
extcon_data->edev.dev.parent = &pdev->dev;
extcon_data->gpio = pdata->gpio;
extcon_data->gpio_active_low = pdata->gpio_active_low;
extcon_data->state_on = pdata->state_on;
extcon_data->state_off = pdata->state_off;
if (pdata->state_on && pdata->state_off)
extcon_data->edev.print_state = extcon_gpio_print_state;
extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce);
if (pdata->debounce) {
ret = gpio_set_debounce(extcon_data->gpio,
pdata->debounce * 1000);
if (ret < 0)
extcon_data->debounce_jiffies =
msecs_to_jiffies(pdata->debounce);
}
ret = extcon_dev_register(&extcon_data->edev, &pdev->dev);
ret = extcon_dev_register(&extcon_data->edev);
if (ret < 0)
return ret;
......
......@@ -189,14 +189,17 @@ enum max77693_muic_acc_type {
/* The below accessories have same ADC value so ADCLow and
ADC1K bit is used to separate specific accessory */
MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, VBVolot:0, ADCLow:0, ADC1K:0 */
MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* ADC:0x0, VBVolot:1, ADCLow:0, ADC1K:0 */
MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:0 */
MAX77693_MUIC_GND_MHL = 0x103, /* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:1 */
MAX77693_MUIC_GND_MHL_VB = 0x107, /* ADC:0x0, VBVolot:1, ADCLow:1, ADC1K:1 */
/* ADC|VBVolot|ADCLow|ADC1K| */
MAX77693_MUIC_GND_USB_OTG = 0x100, /* 0x0| 0| 0| 0| */
MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* 0x0| 1| 0| 0| */
MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */
MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */
MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */
};
/* MAX77693 MUIC device support below list of accessories(external connector) */
/*
* MAX77693 MUIC device support below list of accessories(external connector)
*/
enum {
EXTCON_CABLE_USB = 0,
EXTCON_CABLE_USB_HOST,
......@@ -395,12 +398,12 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
vbvolt >>= STATUS2_VBVOLT_SHIFT;
/**
* [0x1][VBVolt][ADCLow][ADC1K]
* [0x1 0 0 0 ] : USB_OTG
* [0x1 1 0 0 ] : USB_OTG_VB
* [0x1 0 1 0 ] : Audio Video Cable with load
* [0x1 0 1 1 ] : MHL without charging connector
* [0x1 1 1 1 ] : MHL with charging connector
* [0x1|VBVolt|ADCLow|ADC1K]
* [0x1| 0| 0| 0] USB_OTG
* [0x1| 1| 0| 0] USB_OTG_VB
* [0x1| 0| 1| 0] Audio Video cable with load
* [0x1| 0| 1| 1] MHL without charging cable
* [0x1| 1| 1| 1] MHL with charging cable
*/
cable_type = ((0x1 << 8)
| (vbvolt << 2)
......@@ -815,19 +818,21 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_GND_MHL_VB:
/*
* MHL cable with MHL_TA(USB/TA) cable
* - MHL cable include two port(HDMI line and separate micro-
* usb port. When the target connect MHL cable, extcon driver
* check whether MHL_TA(USB/TA) cable is connected. If MHL_TA
* cable is connected, extcon driver notify state to notifiee
* for charging battery.
* - MHL cable include two port(HDMI line and separate
* micro-usb port. When the target connect MHL cable,
* extcon driver check whether MHL_TA(USB/TA) cable is
* connected. If MHL_TA cable is connected, extcon
* driver notify state to notifiee for charging battery.
*
* Features of 'MHL_TA(USB/TA) with MHL cable'
* - Support MHL
* - Support charging through micro-usb port without data connection
* - Support charging through micro-usb port without
* data connection
*/
extcon_set_cable_state(info->edev, "MHL_TA", attached);
if (!cable_attached)
extcon_set_cable_state(info->edev, "MHL", cable_attached);
extcon_set_cable_state(info->edev,
"MHL", cable_attached);
break;
}
......@@ -839,47 +844,51 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */
/*
* Dock-Audio device with USB/TA cable
* - Dock device include two port(Dock-Audio and micro-usb
* port). When the target connect Dock-Audio device, extcon
* driver check whether USB/TA cable is connected. If USB/TA
* cable is connected, extcon driver notify state to notifiee
* for charging battery.
* - Dock device include two port(Dock-Audio and micro-
* usb port). When the target connect Dock-Audio device,
* extcon driver check whether USB/TA cable is connected
* or not. If USB/TA cable is connected, extcon driver
* notify state to notifiee for charging battery.
*
* Features of 'USB/TA cable with Dock-Audio device'
* - Support external output feature of audio.
* - Support charging through micro-usb port without data
* connection.
* - Support charging through micro-usb port without
* data connection.
*/
extcon_set_cable_state(info->edev, "USB", attached);
if (!cable_attached)
extcon_set_cable_state(info->edev, "Dock-Audio", cable_attached);
extcon_set_cable_state(info->edev, "Dock-Audio",
cable_attached);
break;
case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */
/*
* Dock-Smart device with USB/TA cable
* - Dock-Desk device include three type of cable which
* are HDMI, USB for mouse/keyboard and micro-usb port
* for USB/TA cable. Dock-Smart device need always exteranl
* power supply(USB/TA cable through micro-usb cable). Dock-
* Smart device support screen output of target to separate
* monitor and mouse/keyboard for desktop mode.
* for USB/TA cable. Dock-Smart device need always
* exteranl power supply(USB/TA cable through micro-usb
* cable). Dock-Smart device support screen output of
* target to separate monitor and mouse/keyboard for
* desktop mode.
*
* Features of 'USB/TA cable with Dock-Smart device'
* - Support MHL
* - Support external output feature of audio
* - Support charging through micro-usb port without data
* connection if TA cable is connected to target.
* - Support charging and data connection through micro-usb port
* if USB cable is connected between target and host
* device.
* - Support charging through micro-usb port without
* data connection if TA cable is connected to target.
* - Support charging and data connection through micro-
* usb port if USB cable is connected between target
* and host device
* - Support OTG device (Mouse/Keyboard)
*/
ret = max77693_muic_set_path(info, info->path_usb, attached);
ret = max77693_muic_set_path(info, info->path_usb,
attached);
if (ret < 0)
return ret;
extcon_set_cable_state(info->edev, "Dock-Smart", attached);
extcon_set_cable_state(info->edev, "Dock-Smart",
attached);
extcon_set_cable_state(info->edev, "MHL", attached);
break;
......@@ -889,25 +898,28 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
switch (chg_type) {
case MAX77693_CHARGER_TYPE_NONE:
/*
* When MHL(with USB/TA cable) or Dock-Audio with USB/TA cable
* is attached, muic device happen below two interrupt.
* - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting MHL/Dock-Audio.
* - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting USB/TA cable
* connected to MHL or Dock-Audio.
* Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC interrupt
* than MAX77693_MUIC_IRQ_INT2_CHGTYP interrupt.
* When MHL(with USB/TA cable) or Dock-Audio with USB/TA
* cable is attached, muic device happen below two irq.
* - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting
* MHL/Dock-Audio.
* - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting
* USB/TA cable connected to MHL or Dock-Audio.
* Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC
* irq than MAX77693_MUIC_IRQ_INT2_CHGTYP irq.
*
* If user attach MHL (with USB/TA cable and immediately detach
* MHL with USB/TA cable before MAX77693_MUIC_IRQ_INT2_CHGTYP
* interrupt is happened, USB/TA cable remain connected state to
* target. But USB/TA cable isn't connected to target. The user
* be face with unusual action. So, driver should check this
* situation in spite of, that previous charger type is N/A.
* If user attach MHL (with USB/TA cable and immediately
* detach MHL with USB/TA cable before MAX77693_MUIC_IRQ
* _INT2_CHGTYP irq is happened, USB/TA cable remain
* connected state to target. But USB/TA cable isn't
* connected to target. The user be face with unusual
* action. So, driver should check this situation in
* spite of, that previous charger type is N/A.
*/
break;
case MAX77693_CHARGER_TYPE_USB:
/* Only USB cable, PATH:AP_USB */
ret = max77693_muic_set_path(info, info->path_usb, attached);
ret = max77693_muic_set_path(info, info->path_usb,
attached);
if (ret < 0)
return ret;
......@@ -953,7 +965,7 @@ static void max77693_muic_irq_work(struct work_struct *work)
mutex_lock(&info->mutex);
for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
if (info->irq == muic_irqs[i].virq)
irq_type = muic_irqs[i].irq;
......@@ -1171,8 +1183,9 @@ static int max77693_muic_probe(struct platform_device *pdev)
goto err_irq;
}
info->edev->name = DEV_NAME;
info->edev->dev.parent = &pdev->dev;
info->edev->supported_cable = max77693_extcon_cable;
ret = extcon_dev_register(info->edev, NULL);
ret = extcon_dev_register(info->edev);
if (ret) {
dev_err(&pdev->dev, "failed to register extcon device\n");
goto err_irq;
......@@ -1188,7 +1201,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
num_init_data = ARRAY_SIZE(default_init_data);
}
for (i = 0 ; i < num_init_data ; i++) {
for (i = 0; i < num_init_data; i++) {
enum max77693_irq_source irq_src
= MAX77693_IRQ_GROUP_NR;
......@@ -1214,7 +1227,8 @@ static int max77693_muic_probe(struct platform_device *pdev)
}
if (pdata->muic_data) {
struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
struct max77693_muic_platform_data *muic_pdata
= pdata->muic_data;
/*
* Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
......
......@@ -426,7 +426,8 @@ static int max8997_muic_adc_handler(struct max8997_muic_info *info)
break;
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, attached);
ret = max8997_muic_handle_usb(info,
MAX8997_USB_DEVICE, attached);
if (ret < 0)
return ret;
break;
......@@ -504,7 +505,8 @@ static int max8997_muic_chg_handler(struct max8997_muic_info *info)
}
break;
case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
extcon_set_cable_state(info->edev, "Charge-downstream", attached);
extcon_set_cable_state(info->edev,
"Charge-downstream", attached);
break;
case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
extcon_set_cable_state(info->edev, "TA", attached);
......@@ -537,7 +539,7 @@ static void max8997_muic_irq_work(struct work_struct *work)
mutex_lock(&info->mutex);
for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
if (info->irq == muic_irqs[i].virq)
irq_type = muic_irqs[i].irq;
......@@ -705,8 +707,9 @@ static int max8997_muic_probe(struct platform_device *pdev)
goto err_irq;
}
info->edev->name = DEV_NAME;
info->edev->dev.parent = &pdev->dev;
info->edev->supported_cable = max8997_extcon_cable;
ret = extcon_dev_register(info->edev, NULL);
ret = extcon_dev_register(info->edev);
if (ret) {
dev_err(&pdev->dev, "failed to register extcon device\n");
goto err_irq;
......
......@@ -135,7 +135,7 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb)
static int palmas_usb_probe(struct platform_device *pdev)
{
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct palmas_usb_platform_data *pdata = pdev->dev.platform_data;
struct palmas_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct device_node *node = pdev->dev.of_node;
struct palmas_usb *palmas_usb;
int status;
......@@ -178,9 +178,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, palmas_usb);
palmas_usb->edev.supported_cable = palmas_extcon_cable;
palmas_usb->edev.dev.parent = palmas_usb->dev;
palmas_usb->edev.mutually_exclusive = mutually_exclusive;
status = extcon_dev_register(&palmas_usb->edev, palmas_usb->dev);
status = extcon_dev_register(&palmas_usb->edev);
if (status) {
dev_err(&pdev->dev, "failed to register extcon device\n");
return status;
......
......@@ -47,8 +47,8 @@ static void vmbus_setevent(struct vmbus_channel *channel)
(unsigned long *) vmbus_connection.send_int_page +
(channel->offermsg.child_relid >> 5));
monitorpage = vmbus_connection.monitor_pages;
monitorpage++; /* Get the child to parent monitor page */
/* Get the child to parent monitor page */
monitorpage = vmbus_connection.monitor_pages[1];
sync_set_bit(channel->monitor_bit,
(unsigned long *)&monitorpage->trigger_group
......@@ -59,50 +59,6 @@ static void vmbus_setevent(struct vmbus_channel *channel)
}
}
/*
* vmbus_get_debug_info -Retrieve various channel debug info
*/
void vmbus_get_debug_info(struct vmbus_channel *channel,
struct vmbus_channel_debug_info *debuginfo)
{
struct hv_monitor_page *monitorpage;
u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
debuginfo->relid = channel->offermsg.child_relid;
debuginfo->state = channel->state;
memcpy(&debuginfo->interfacetype,
&channel->offermsg.offer.if_type, sizeof(uuid_le));
memcpy(&debuginfo->interface_instance,
&channel->offermsg.offer.if_instance,
sizeof(uuid_le));
monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
debuginfo->monitorid = channel->offermsg.monitorid;
debuginfo->servermonitor_pending =
monitorpage->trigger_group[monitor_group].pending;
debuginfo->servermonitor_latency =
monitorpage->latency[monitor_group][monitor_offset];
debuginfo->servermonitor_connectionid =
monitorpage->parameter[monitor_group]
[monitor_offset].connectionid.u.id;
monitorpage++;
debuginfo->clientmonitor_pending =
monitorpage->trigger_group[monitor_group].pending;
debuginfo->clientmonitor_latency =
monitorpage->latency[monitor_group][monitor_offset];
debuginfo->clientmonitor_connectionid =
monitorpage->parameter[monitor_group]
[monitor_offset].connectionid.u.id;
hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
}
/*
* vmbus_open - Open the specified channel.
*/
......@@ -855,6 +811,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
if (signal)
vmbus_setevent(channel);
return 0;
return ret;
}
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
......@@ -203,6 +203,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
struct vmbus_channel *primary_channel;
struct vmbus_channel_relid_released msg;
if (channel->device_obj)
vmbus_device_unregister(channel->device_obj);
memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
msg.child_relid = channel->offermsg.child_relid;
......@@ -216,7 +217,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
} else {
primary_channel = channel->primary_channel;
spin_lock_irqsave(&primary_channel->sc_lock, flags);
list_del(&channel->listentry);
list_del(&channel->sc_list);
spin_unlock_irqrestore(&primary_channel->sc_lock, flags);
}
free_channel(channel);
......
......@@ -76,10 +76,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
msg->vmbus_version_requested = version;
msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
msg->monitor_page2 = virt_to_phys(
(void *)((unsigned long)vmbus_connection.monitor_pages +
PAGE_SIZE));
msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
/*
* Add to list before we send the request since we may
......@@ -169,9 +167,10 @@ int vmbus_connect(void)
* Setup the monitor notification facility. The 1st page for
* parent->child and the 2nd page for child->parent
*/
vmbus_connection.monitor_pages =
(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
if (vmbus_connection.monitor_pages == NULL) {
vmbus_connection.monitor_pages[0] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
vmbus_connection.monitor_pages[1] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
if ((vmbus_connection.monitor_pages[0] == NULL) ||
(vmbus_connection.monitor_pages[1] == NULL)) {
ret = -ENOMEM;
goto cleanup;
}
......@@ -229,10 +228,10 @@ int vmbus_connect(void)
vmbus_connection.int_page = NULL;
}
if (vmbus_connection.monitor_pages) {
free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
vmbus_connection.monitor_pages = NULL;
}
free_pages((unsigned long)vmbus_connection.monitor_pages[0], 1);
free_pages((unsigned long)vmbus_connection.monitor_pages[1], 1);
vmbus_connection.monitor_pages[0] = NULL;
vmbus_connection.monitor_pages[1] = NULL;
kfree(msginfo);
......
......@@ -304,7 +304,7 @@ int hv_synic_alloc(void)
void hv_synic_free_cpu(int cpu)
{
kfree(hv_context.event_dpc[cpu]);
if (hv_context.synic_message_page[cpu])
if (hv_context.synic_event_page[cpu])
free_page((unsigned long)hv_context.synic_event_page[cpu]);
if (hv_context.synic_message_page[cpu])
free_page((unsigned long)hv_context.synic_message_page[cpu]);
......
......@@ -97,7 +97,7 @@ static void shutdown_onchannelcallback(void *context)
struct vmbus_channel *channel = context;
u32 recvlen;
u64 requestid;
u8 execute_shutdown = false;
bool execute_shutdown = false;
u8 *shut_txf_buf = util_shutdown.recv_buffer;
struct shutdown_msg_data *shutdown_msg;
......
......@@ -514,6 +514,13 @@ struct hv_context {
extern struct hv_context hv_context;
struct hv_ring_buffer_debug_info {
u32 current_interrupt_mask;
u32 current_read_index;
u32 current_write_index;
u32 bytes_avail_toread;
u32 bytes_avail_towrite;
};
/* Hv Interface */
......@@ -612,7 +619,7 @@ struct vmbus_connection {
* 2 pages - 1st page for parent->child notification and 2nd
* is child->parent notification
*/
void *monitor_pages;
struct hv_monitor_page *monitor_pages[2];
struct list_head chn_msg_list;
spinlock_t channelmsg_lock;
......
This diff is collapsed.
......@@ -537,4 +537,5 @@ source "drivers/misc/carma/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
source "drivers/misc/vmw_vmci/Kconfig"
source "drivers/misc/mic/Kconfig"
endmenu
......@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
obj-y += mic/
......@@ -297,7 +297,7 @@ static int __init charlcd_probe(struct platform_device *pdev)
lcd->irq = platform_get_irq(pdev, 0);
/* If no IRQ is supplied, we'll survive without it */
if (lcd->irq >= 0) {
if (request_irq(lcd->irq, charlcd_interrupt, IRQF_DISABLED,
if (request_irq(lcd->irq, charlcd_interrupt, 0,
DRIVERNAME, lcd)) {
ret = -EIO;
goto out_no_irq;
......
......@@ -90,8 +90,10 @@ int pwm_channel_alloc(int index, struct pwm_channel *ch)
unsigned long flags;
int status = 0;
/* insist on PWM init, with this signal pinned out */
if (!pwm || !(pwm->mask & 1 << index))
if (!pwm)
return -EPROBE_DEFER;
if (!(pwm->mask & 1 << index))
return -ENODEV;
if (index < 0 || index >= PWM_NCHAN || !ch)
......
......@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#define BH1780_REG_CONTROL 0x80
#define BH1780_REG_PARTID 0x8A
......@@ -244,6 +245,15 @@ static const struct i2c_device_id bh1780_id[] = {
{ },
};
#ifdef CONFIG_OF
static const struct of_device_id of_bh1780_match[] = {
{ .compatible = "rohm,bh1780gli", },
{},
};
MODULE_DEVICE_TABLE(of, of_bh1780_match);
#endif
static struct i2c_driver bh1780_driver = {
.probe = bh1780_probe,
.remove = bh1780_remove,
......@@ -251,6 +261,7 @@ static struct i2c_driver bh1780_driver = {
.driver = {
.name = "bh1780",
.pm = &bh1780_pm,
.of_match_table = of_match_ptr(of_bh1780_match),
},
};
......
......@@ -374,7 +374,7 @@ int bmp085_detect(struct device *dev)
}
EXPORT_SYMBOL_GPL(bmp085_detect);
static void __init bmp085_get_of_properties(struct bmp085_data *data)
static void bmp085_get_of_properties(struct bmp085_data *data)
{
#ifdef CONFIG_OF
struct device_node *np = data->dev->of_node;
......
......@@ -176,7 +176,7 @@ static int cb710_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct cb710_chip *chip = pci_get_drvdata(pdev);
free_irq(pdev->irq, chip);
devm_free_irq(&pdev->dev, pdev->irq, chip);
pci_save_state(pdev);
pci_disable_device(pdev);
if (state.event & PM_EVENT_SLEEP)
......
......@@ -96,4 +96,17 @@ config EEPROM_DIGSY_MTC_CFG
If unsure, say N.
config EEPROM_SUNXI_SID
tristate "Allwinner sunxi security ID support"
depends on ARCH_SUNXI && SYSFS
help
This is a driver for the 'security ID' available on various Allwinner
devices.
Due to the potential risks involved with changing e-fuses,
this driver is read-only.
This driver can also be built as a module. If so, the module
will be called sunxi_sid.
endmenu
......@@ -4,4 +4,5 @@ obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
obj-$(CONFIG_EEPROM_SUNXI_SID) += sunxi_sid.o
obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
......@@ -428,6 +428,9 @@ static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
{
struct at24_data *at24;
if (unlikely(off >= attr->size))
return -EFBIG;
at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
return at24_write(at24, buf, off, count);
}
......
......@@ -462,10 +462,17 @@ static int at25_remove(struct spi_device *spi)
/*-------------------------------------------------------------------------*/
static const struct of_device_id at25_of_match[] = {
{ .compatible = "atmel,at25", },
{ }
};
MODULE_DEVICE_TABLE(of, at25_of_match);
static struct spi_driver at25_driver = {
.driver = {
.name = "at25",
.owner = THIS_MODULE,
.of_match_table = at25_of_match,
},
.probe = at25_probe,
.remove = at25_remove,
......
......@@ -202,7 +202,7 @@ eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
edev = dev_get_drvdata(dev);
if (unlikely(off >= edev->bin.size))
return 0;
return -EFBIG;
if ((off + count) > edev->bin.size)
count = edev->bin.size - off;
if (unlikely(!count))
......
/*
* Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
* http://www.linux-sunxi.org
*
* 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 of the License, 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.
*
* This driver exposes the Allwinner security ID, efuses exported in byte-
* sized chunks.
*/
#include <linux/compiler.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#define DRV_NAME "sunxi-sid"
struct sunxi_sid_data {
void __iomem *reg_base;
unsigned int keysize;
};
/* We read the entire key, due to a 32 bit read alignment requirement. Since we
* want to return the requested byte, this results in somewhat slower code and
* uses 4 times more reads as needed but keeps code simpler. Since the SID is
* only very rarely probed, this is not really an issue.
*/
static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
const unsigned int offset)
{
u32 sid_key;
if (offset >= sid_data->keysize)
return 0;
sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
sid_key >>= (offset % 4) * 8;
return sid_key; /* Only return the last byte */
}
static ssize_t sid_read(struct file *fd, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t pos, size_t size)
{
struct platform_device *pdev;
struct sunxi_sid_data *sid_data;
int i;
pdev = to_platform_device(kobj_to_dev(kobj));
sid_data = platform_get_drvdata(pdev);
if (pos < 0 || pos >= sid_data->keysize)
return 0;
if (size > sid_data->keysize - pos)
size = sid_data->keysize - pos;
for (i = 0; i < size; i++)
buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
return i;
}
static struct bin_attribute sid_bin_attr = {
.attr = { .name = "eeprom", .mode = S_IRUGO, },
.read = sid_read,
};
static int sunxi_sid_remove(struct platform_device *pdev)
{
device_remove_bin_file(&pdev->dev, &sid_bin_attr);
dev_dbg(&pdev->dev, "driver unloaded\n");
return 0;
}
static const struct of_device_id sunxi_sid_of_match[] = {
{ .compatible = "allwinner,sun4i-sid", .data = (void *)16},
{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
{/* sentinel */},
};
MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
static int sunxi_sid_probe(struct platform_device *pdev)
{
struct sunxi_sid_data *sid_data;
struct resource *res;
const struct of_device_id *of_dev_id;
u8 *entropy;
unsigned int i;
sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
GFP_KERNEL);
if (!sid_data)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sid_data->reg_base))
return PTR_ERR(sid_data->reg_base);
of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
if (!of_dev_id)
return -ENODEV;
sid_data->keysize = (int)of_dev_id->data;
platform_set_drvdata(pdev, sid_data);
sid_bin_attr.size = sid_data->keysize;
if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
return -ENODEV;
entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
for (i = 0; i < sid_data->keysize; i++)
entropy[i] = sunxi_sid_read_byte(sid_data, i);
add_device_randomness(entropy, sid_data->keysize);
kfree(entropy);
dev_dbg(&pdev->dev, "loaded\n");
return 0;
}
static struct platform_driver sunxi_sid_driver = {
.probe = sunxi_sid_probe,
.remove = sunxi_sid_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = sunxi_sid_of_match,
},
};
module_platform_driver(sunxi_sid_driver);
MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
MODULE_DESCRIPTION("Allwinner sunxi security id driver");
MODULE_LICENSE("GPL");
......@@ -153,7 +153,6 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
error_heartbeat:
ibmasm_event_buffer_exit(sp);
error_eventbuffer:
pci_set_drvdata(pdev, NULL);
kfree(sp);
error_kmalloc:
pci_release_regions(pdev);
......@@ -165,7 +164,7 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static void ibmasm_remove_one(struct pci_dev *pdev)
{
struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
struct service_processor *sp = pci_get_drvdata(pdev);
dbg("Unregistering UART\n");
ibmasm_unregister_uart(sp);
......@@ -182,7 +181,6 @@ static void ibmasm_remove_one(struct pci_dev *pdev)
ibmasm_free_remote_input_dev(sp);
iounmap(sp->base_address);
ibmasm_event_buffer_exit(sp);
pci_set_drvdata(pdev, NULL);
kfree(sp);
pci_release_regions(pdev);
pci_disable_device(pdev);
......
......@@ -44,13 +44,25 @@
#include <scsi/scsi_cmnd.h>
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#ifdef CONFIG_IDE
#include <linux/ide.h>
#endif
/*
* Make sure our attempts to over run the kernel stack doesn't trigger
* a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
* recurse past the end of THREAD_SIZE by default.
*/
#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0)
#define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2)
#else
#define REC_STACK_SIZE (THREAD_SIZE / 8)
#endif
#define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2)
#define DEFAULT_COUNT 10
#define REC_NUM_DEFAULT 10
#define EXEC_SIZE 64
enum cname {
......@@ -86,6 +98,9 @@ enum ctype {
CT_EXEC_STACK,
CT_EXEC_KMALLOC,
CT_EXEC_VMALLOC,
CT_EXEC_USERSPACE,
CT_ACCESS_USERSPACE,
CT_WRITE_RO,
};
static char* cp_name[] = {
......@@ -119,6 +134,9 @@ static char* cp_type[] = {
"EXEC_STACK",
"EXEC_KMALLOC",
"EXEC_VMALLOC",
"EXEC_USERSPACE",
"ACCESS_USERSPACE",
"WRITE_RO",
};
static struct jprobe lkdtm;
......@@ -139,9 +157,10 @@ static DEFINE_SPINLOCK(lock_me_up);
static u8 data_area[EXEC_SIZE];
static const unsigned long rodata = 0xAA55AA55;
module_param(recur_count, int, 0644);
MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
"default is 10");
MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
module_param(cpoint_name, charp, 0444);
MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
module_param(cpoint_type, charp, 0444);
......@@ -280,16 +299,16 @@ static int lkdtm_parse_commandline(void)
return -EINVAL;
}
static int recursive_loop(int a)
static int recursive_loop(int remaining)
{
char buf[1024];
char buf[REC_STACK_SIZE];
memset(buf,0xFF,1024);
recur_count--;
if (!recur_count)
/* Make sure compiler does not optimize this away. */
memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE);
if (!remaining)
return 0;
else
return recursive_loop(a);
return recursive_loop(remaining - 1);
}
static void do_nothing(void)
......@@ -297,6 +316,14 @@ static void do_nothing(void)
return;
}
static noinline void corrupt_stack(void)
{
/* Use default char array length that triggers stack protection. */
char data[8];
memset((void *)data, 0, 64);
}
static void execute_location(void *dst)
{
void (*func)(void) = dst;
......@@ -305,6 +332,15 @@ static void execute_location(void *dst)
func();
}
static void execute_user_location(void *dst)
{
void (*func)(void) = dst;
if (copy_to_user(dst, do_nothing, EXEC_SIZE))
return;
func();
}
static void lkdtm_do_action(enum ctype which)
{
switch (which) {
......@@ -325,15 +361,11 @@ static void lkdtm_do_action(enum ctype which)
;
break;
case CT_OVERFLOW:
(void) recursive_loop(0);
(void) recursive_loop(recur_count);
break;
case CT_CORRUPT_STACK: {
/* Make sure the compiler creates and uses an 8 char array. */
volatile char data[8];
memset((void *)data, 0, 64);
case CT_CORRUPT_STACK:
corrupt_stack();
break;
}
case CT_UNALIGNED_LOAD_STORE_WRITE: {
static u8 data[5] __attribute__((aligned(4))) = {1, 2,
3, 4, 5};
......@@ -401,6 +433,49 @@ static void lkdtm_do_action(enum ctype which)
vfree(vmalloc_area);
break;
}
case CT_EXEC_USERSPACE: {
unsigned long user_addr;
user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
if (user_addr >= TASK_SIZE) {
pr_warn("Failed to allocate user memory\n");
return;
}
execute_user_location((void *)user_addr);
vm_munmap(user_addr, PAGE_SIZE);
break;
}
case CT_ACCESS_USERSPACE: {
unsigned long user_addr, tmp;
unsigned long *ptr;
user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
if (user_addr >= TASK_SIZE) {
pr_warn("Failed to allocate user memory\n");
return;
}
ptr = (unsigned long *)user_addr;
tmp = *ptr;
tmp += 0xc0dec0de;
*ptr = tmp;
vm_munmap(user_addr, PAGE_SIZE);
break;
}
case CT_WRITE_RO: {
unsigned long *ptr;
ptr = (unsigned long *)&rodata;
*ptr ^= 0xabcd1234;
break;
}
case CT_NONE:
default:
break;
......
......@@ -58,6 +58,7 @@ void mei_amthif_reset_params(struct mei_device *dev)
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
dev->iamthif_stall_timer = 0;
dev->iamthif_open_count = 0;
}
/**
......@@ -78,8 +79,10 @@ int mei_amthif_host_init(struct mei_device *dev)
i = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
if (i < 0) {
dev_info(&dev->pdev->dev, "amthif: failed to find the client\n");
return -ENOENT;
ret = i;
dev_info(&dev->pdev->dev,
"amthif: failed to find the client %d\n", ret);
return ret;
}
cl->me_client_id = dev->me_clients[i].client_id;
......@@ -106,8 +109,9 @@ int mei_amthif_host_init(struct mei_device *dev)
ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
if (ret < 0) {
dev_err(&dev->pdev->dev, "amthif: failed link client\n");
return -ENOENT;
dev_err(&dev->pdev->dev,
"amthif: failed link client %d\n", ret);
return ret;
}
cl->state = MEI_FILE_CONNECTING;
......@@ -313,13 +317,13 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
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))
return -ENODEV;
ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
if (ret)
return ret;
if (mei_hdr.msg_complete) {
if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
return -ENODEV;
return -EIO;
dev->iamthif_flow_control_pending = true;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev_dbg(&dev->pdev->dev, "add amthif cb to write waiting list\n");
......@@ -459,6 +463,16 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_msg_hdr mei_hdr;
size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
u32 msg_slots = mei_data2slots(len);
int rets;
rets = mei_cl_flow_ctrl_creds(cl);
if (rets < 0)
return rets;
if (rets == 0) {
cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
return 0;
}
mei_hdr.host_addr = cl->host_client_id;
mei_hdr.me_addr = cl->me_client_id;
......@@ -481,16 +495,17 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
*slots -= msg_slots;
if (mei_write_message(dev, &mei_hdr,
dev->iamthif_msg_buf + dev->iamthif_msg_buf_index)) {
rets = mei_write_message(dev, &mei_hdr,
dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
if (rets) {
dev->iamthif_state = MEI_IAMTHIF_IDLE;
cl->status = -ENODEV;
cl->status = rets;
list_del(&cb->list);
return -ENODEV;
return rets;
}
if (mei_cl_flow_ctrl_reduce(cl))
return -ENODEV;
return -EIO;
dev->iamthif_msg_buf_index += mei_hdr.length;
cl->status = 0;
......@@ -720,8 +735,8 @@ static bool mei_clear_lists(struct mei_device *dev, struct file *file)
*/
int mei_amthif_release(struct mei_device *dev, struct file *file)
{
if (dev->open_handle_count > 0)
dev->open_handle_count--;
if (dev->iamthif_open_count > 0)
dev->iamthif_open_count--;
if (dev->iamthif_file_object == file &&
dev->iamthif_state != MEI_IAMTHIF_IDLE) {
......
......@@ -245,7 +245,7 @@ static int ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
/* Check if we have an ME client device */
id = mei_me_cl_by_id(dev, cl->me_client_id);
if (id < 0)
return -ENODEV;
return id;
if (length > dev->me_clients[id].props.max_msg_length)
return -EINVAL;
......
......@@ -187,10 +187,14 @@ int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
*/
int mei_cl_flush_queues(struct mei_cl *cl)
{
struct mei_device *dev;
if (WARN_ON(!cl || !cl->dev))
return -EINVAL;
dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
dev = cl->dev;
cl_dbg(dev, cl, "remove list entry belonging to cl\n");
mei_io_list_flush(&cl->dev->read_list, cl);
mei_io_list_flush(&cl->dev->write_list, cl);
mei_io_list_flush(&cl->dev->write_waiting_list, cl);
......@@ -271,6 +275,7 @@ struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
int mei_cl_link(struct mei_cl *cl, int id)
{
struct mei_device *dev;
long open_handle_count;
if (WARN_ON(!cl || !cl->dev))
return -EINVAL;
......@@ -284,7 +289,14 @@ int mei_cl_link(struct mei_cl *cl, int id)
if (id >= MEI_CLIENTS_MAX) {
dev_err(&dev->pdev->dev, "id exceded %d", MEI_CLIENTS_MAX) ;
return -ENOENT;
return -EMFILE;
}
open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
MEI_MAX_OPEN_HANDLE_COUNT);
return -EMFILE;
}
dev->open_handle_count++;
......@@ -296,7 +308,7 @@ int mei_cl_link(struct mei_cl *cl, int id)
cl->state = MEI_FILE_INITIALIZING;
dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id);
cl_dbg(dev, cl, "link cl\n");
return 0;
}
......@@ -308,7 +320,6 @@ int mei_cl_link(struct mei_cl *cl, int id)
int mei_cl_unlink(struct mei_cl *cl)
{
struct mei_device *dev;
struct mei_cl *pos, *next;
/* don't shout on error exit path */
if (!cl)
......@@ -320,14 +331,21 @@ int mei_cl_unlink(struct mei_cl *cl)
dev = cl->dev;
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;
}
}
cl_dbg(dev, cl, "unlink client");
if (dev->open_handle_count > 0)
dev->open_handle_count--;
/* never clear the 0 bit */
if (cl->host_client_id)
clear_bit(cl->host_client_id, dev->host_clients_map);
list_del_init(&cl->link);
cl->state = MEI_FILE_INITIALIZING;
list_del_init(&cl->link);
return 0;
}
......@@ -341,17 +359,6 @@ void mei_host_client_init(struct work_struct *work)
mutex_lock(&dev->device_lock);
bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
dev->open_handle_count = 0;
/*
* 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);
for (i = 0; i < dev->me_clients_num; i++) {
client_props = &dev->me_clients[i].props;
......@@ -390,6 +397,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
dev = cl->dev;
cl_dbg(dev, cl, "disconnecting");
if (cl->state != MEI_FILE_DISCONNECTING)
return 0;
......@@ -402,13 +411,13 @@ int mei_cl_disconnect(struct mei_cl *cl)
dev->hbuf_is_ready = false;
if (mei_hbm_cl_disconnect_req(dev, cl)) {
rets = -ENODEV;
dev_err(&dev->pdev->dev, "failed to disconnect.\n");
cl_err(dev, cl, "failed to disconnect.\n");
goto free;
}
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
} else {
dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
cl_dbg(dev, cl, "add disconnect cb to control write list\n");
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
......@@ -421,18 +430,17 @@ int mei_cl_disconnect(struct mei_cl *cl)
mutex_lock(&dev->device_lock);
if (MEI_FILE_DISCONNECTED == cl->state) {
rets = 0;
dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
} else {
rets = -ENODEV;
if (MEI_FILE_DISCONNECTED != cl->state)
dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
cl_err(dev, cl, "wrong status client disconnect.\n");
if (err)
dev_dbg(&dev->pdev->dev,
"wait failed disconnect err=%08x\n",
cl_dbg(dev, cl, "wait failed disconnect err=%08x\n",
err);
dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
cl_err(dev, cl, "failed to disconnect from FW client.\n");
}
mei_io_list_flush(&dev->ctrl_rd_list, cl);
......@@ -639,13 +647,12 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
return -ENODEV;
if (cl->read_cb) {
dev_dbg(&dev->pdev->dev, "read is pending.\n");
cl_dbg(dev, cl, "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);
cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
return -ENODEV;
}
......@@ -664,6 +671,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
if (dev->hbuf_is_ready) {
dev->hbuf_is_ready = false;
if (mei_hbm_cl_flow_control_req(dev, cl)) {
cl_err(dev, cl, "flow control send failed\n");
rets = -ENODEV;
goto err;
}
......@@ -691,10 +699,32 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
s32 *slots, struct mei_cl_cb *cmpl_list)
{
struct mei_device *dev = cl->dev;
struct mei_device *dev;
struct mei_msg_data *buf;
struct mei_msg_hdr mei_hdr;
size_t len = cb->request_buffer.size - cb->buf_idx;
u32 msg_slots = mei_data2slots(len);
size_t len;
u32 msg_slots;
int rets;
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
dev = cl->dev;
buf = &cb->request_buffer;
rets = mei_cl_flow_ctrl_creds(cl);
if (rets < 0)
return rets;
if (rets == 0) {
cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
return 0;
}
len = buf->size - cb->buf_idx;
msg_slots = mei_data2slots(len);
mei_hdr.host_addr = cl->host_client_id;
mei_hdr.me_addr = cl->me_client_id;
......@@ -714,16 +744,15 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
return 0;
}
dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
cb->request_buffer.size, cb->buf_idx);
dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
*slots -= msg_slots;
if (mei_write_message(dev, &mei_hdr,
cb->request_buffer.data + cb->buf_idx)) {
cl->status = -ENODEV;
rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
if (rets) {
cl->status = rets;
list_move_tail(&cb->list, &cmpl_list->list);
return -ENODEV;
return rets;
}
cl->status = 0;
......@@ -732,7 +761,7 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
if (mei_hdr.msg_complete) {
if (mei_cl_flow_ctrl_reduce(cl))
return -ENODEV;
return -EIO;
list_move_tail(&cb->list, &dev->write_waiting_list.list);
}
......@@ -767,7 +796,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
buf = &cb->request_buffer;
dev_dbg(&dev->pdev->dev, "mei_cl_write %d\n", buf->size);
cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
cb->fop_type = MEI_FOP_WRITE;
......@@ -800,14 +829,10 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
mei_hdr.me_addr = cl->me_client_id;
mei_hdr.reserved = 0;
dev_dbg(&dev->pdev->dev, "write " MEI_HDR_FMT "\n",
MEI_HDR_PRM(&mei_hdr));
if (mei_write_message(dev, &mei_hdr, buf->data)) {
rets = -EIO;
rets = mei_write_message(dev, &mei_hdr, buf->data);
if (rets)
goto err;
}
cl->writing_state = MEI_WRITING;
cb->buf_idx = mei_hdr.length;
......@@ -898,11 +923,11 @@ void mei_cl_all_wakeup(struct mei_device *dev)
struct mei_cl *cl, *next;
list_for_each_entry_safe(cl, next, &dev->file_list, link) {
if (waitqueue_active(&cl->rx_wait)) {
dev_dbg(&dev->pdev->dev, "Waking up reading client!\n");
cl_dbg(dev, cl, "Waking up reading client!\n");
wake_up_interruptible(&cl->rx_wait);
}
if (waitqueue_active(&cl->tx_wait)) {
dev_dbg(&dev->pdev->dev, "Waking up writing client!\n");
cl_dbg(dev, cl, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait);
}
}
......
......@@ -115,4 +115,13 @@ void mei_cl_all_disconnect(struct mei_device *dev);
void mei_cl_all_wakeup(struct mei_device *dev);
void mei_cl_all_write_clear(struct mei_device *dev);
#define MEI_CL_FMT "cl:host=%02d me=%02d "
#define MEI_CL_PRM(cl) (cl)->host_client_id, (cl)->me_client_id
#define cl_dbg(dev, cl, format, arg...) \
dev_dbg(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
#define cl_err(dev, cl, format, arg...) \
dev_err(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
#endif /* _MEI_CLIENT_H_ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment