mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
misc: mic: Remove COSM functionality from the MIC host driver
Since COSM functionality is now moved into a separate COSM driver drivers, this patch removes this functionality from the base MIC host driver. The MIC host driver now implements cosm_hw_ops and registers a COSM device which allows the COSM driver to trigger boot/shutdown/reset of the MIC devices via the cosm_hw_ops. Reviewed-by: Nikhil Rao <nikhil.rao@intel.com> Reviewed-by: Sudeep Dutt <sudeep.dutt@intel.com> Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7cb46d9bff
commit
1da2b3eeef
13 changed files with 204 additions and 1145 deletions
|
@ -2,7 +2,5 @@
|
|||
# Makefile - Intel MIC Linux driver.
|
||||
# Copyright(c) 2013, Intel Corporation.
|
||||
#
|
||||
obj-$(CONFIG_INTEL_MIC_HOST) += host/
|
||||
obj-$(CONFIG_INTEL_MIC_CARD) += card/
|
||||
obj-y += bus/
|
||||
obj-$(CONFIG_SCIF) += scif/
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
|
||||
mic_host-objs := mic_main.o
|
||||
mic_host-objs += mic_x100.o
|
||||
mic_host-objs += mic_sysfs.o
|
||||
mic_host-objs += mic_smpt.o
|
||||
mic_host-objs += mic_intr.o
|
||||
mic_host-objs += mic_boot.o
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kmod.h>
|
||||
|
||||
#include <linux/mic_common.h>
|
||||
#include <linux/mic_bus.h>
|
||||
#include "../bus/scif_bus.h"
|
||||
#include "../common/mic_dev.h"
|
||||
#include "mic_device.h"
|
||||
#include "mic_smpt.h"
|
||||
|
@ -99,7 +99,7 @@ static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
|
|||
int i, j, ret;
|
||||
dma_addr_t da;
|
||||
|
||||
ret = dma_map_sg(mdev->sdev->parent, sg, nents, dir);
|
||||
ret = dma_map_sg(&mdev->pdev->dev, sg, nents, dir);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
|
@ -115,7 +115,7 @@ static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
|
|||
mic_unmap(mdev, sg_dma_address(s), s->length);
|
||||
sg_dma_address(s) = mic_to_dma_addr(mdev, sg_dma_address(s));
|
||||
}
|
||||
dma_unmap_sg(mdev->sdev->parent, sg, nents, dir);
|
||||
dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ static void __mic_dma_unmap_sg(struct device *dev,
|
|||
mic_unmap(mdev, sg_dma_address(s), s->length);
|
||||
sg_dma_address(s) = da;
|
||||
}
|
||||
dma_unmap_sg(mdev->sdev->parent, sg, nents, dir);
|
||||
dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
|
||||
}
|
||||
|
||||
static struct dma_map_ops __mic_dma_ops = {
|
||||
|
@ -270,48 +270,13 @@ static struct mbus_hw_ops mbus_hw_ops = {
|
|||
.ack_interrupt = _mic_ack_interrupt,
|
||||
};
|
||||
|
||||
/**
|
||||
* mic_reset - Reset the MIC device.
|
||||
* @mdev: pointer to mic_device instance
|
||||
*/
|
||||
static void mic_reset(struct mic_device *mdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
#define MIC_RESET_TO (45)
|
||||
|
||||
reinit_completion(&mdev->reset_wait);
|
||||
mdev->ops->reset_fw_ready(mdev);
|
||||
mdev->ops->reset(mdev);
|
||||
|
||||
for (i = 0; i < MIC_RESET_TO; i++) {
|
||||
if (mdev->ops->is_fw_ready(mdev))
|
||||
goto done;
|
||||
/*
|
||||
* Resets typically take 10s of seconds to complete.
|
||||
* Since an MMIO read is required to check if the
|
||||
* firmware is ready or not, a 1 second delay works nicely.
|
||||
*/
|
||||
msleep(1000);
|
||||
}
|
||||
mic_set_state(mdev, MIC_RESET_FAILED);
|
||||
done:
|
||||
complete_all(&mdev->reset_wait);
|
||||
}
|
||||
|
||||
/* Initialize the MIC bootparams */
|
||||
void mic_bootparam_init(struct mic_device *mdev)
|
||||
{
|
||||
struct mic_bootparam *bootparam = mdev->dp;
|
||||
|
||||
bootparam->magic = cpu_to_le32(MIC_MAGIC);
|
||||
bootparam->c2h_shutdown_db = mdev->shutdown_db;
|
||||
bootparam->h2c_shutdown_db = -1;
|
||||
bootparam->h2c_config_db = -1;
|
||||
bootparam->shutdown_status = 0;
|
||||
bootparam->shutdown_card = 0;
|
||||
/* Total nodes = number of MICs + 1 for self node */
|
||||
bootparam->tot_nodes = atomic_read(&g_num_mics) + 1;
|
||||
bootparam->node_id = mdev->id + 1;
|
||||
bootparam->scif_host_dma_addr = 0x0;
|
||||
bootparam->scif_card_dma_addr = 0x0;
|
||||
|
@ -319,6 +284,26 @@ void mic_bootparam_init(struct mic_device *mdev)
|
|||
bootparam->h2c_scif_db = -1;
|
||||
}
|
||||
|
||||
static inline struct mic_device *cosmdev_to_mdev(struct cosm_device *cdev)
|
||||
{
|
||||
return dev_get_drvdata(cdev->dev.parent);
|
||||
}
|
||||
|
||||
static void _mic_reset(struct cosm_device *cdev)
|
||||
{
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
|
||||
mdev->ops->reset_fw_ready(mdev);
|
||||
mdev->ops->reset(mdev);
|
||||
}
|
||||
|
||||
static bool _mic_ready(struct cosm_device *cdev)
|
||||
{
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
|
||||
return mdev->ops->is_fw_ready(mdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_request_dma_chans - Request DMA channels
|
||||
* @mdev: pointer to mic_device instance
|
||||
|
@ -336,14 +321,14 @@ static int mic_request_dma_chans(struct mic_device *mdev)
|
|||
|
||||
do {
|
||||
chan = dma_request_channel(mask, mdev->ops->dma_filter,
|
||||
mdev->sdev->parent);
|
||||
&mdev->pdev->dev);
|
||||
if (chan) {
|
||||
mdev->dma_ch[mdev->num_dma_ch++] = chan;
|
||||
if (mdev->num_dma_ch >= MIC_MAX_DMA_CHAN)
|
||||
break;
|
||||
}
|
||||
} while (chan);
|
||||
dev_info(mdev->sdev->parent, "DMA channels # %d\n", mdev->num_dma_ch);
|
||||
dev_info(&mdev->pdev->dev, "DMA channels # %d\n", mdev->num_dma_ch);
|
||||
return mdev->num_dma_ch;
|
||||
}
|
||||
|
||||
|
@ -365,34 +350,24 @@ static void mic_free_dma_chans(struct mic_device *mdev)
|
|||
}
|
||||
|
||||
/**
|
||||
* mic_start - Start the MIC.
|
||||
* @mdev: pointer to mic_device instance
|
||||
* @buf: buffer containing boot string including firmware/ramdisk path.
|
||||
* _mic_start - Start the MIC.
|
||||
* @cdev: pointer to cosm_device instance
|
||||
* @id: MIC device id/index provided by COSM used in other drivers like SCIF
|
||||
*
|
||||
* This function prepares an MIC for boot and initiates boot.
|
||||
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
|
||||
*
|
||||
* For all cosm_hw_ops the caller holds a mutex to ensure serialization.
|
||||
*/
|
||||
int mic_start(struct mic_device *mdev, const char *buf)
|
||||
static int _mic_start(struct cosm_device *cdev, int id)
|
||||
{
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
int rc;
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
|
||||
mic_bootparam_init(mdev);
|
||||
retry:
|
||||
if (MIC_OFFLINE != mdev->state) {
|
||||
rc = -EINVAL;
|
||||
goto unlock_ret;
|
||||
}
|
||||
if (!mdev->ops->is_fw_ready(mdev)) {
|
||||
mic_reset(mdev);
|
||||
/*
|
||||
* The state will either be MIC_OFFLINE if the reset succeeded
|
||||
* or MIC_RESET_FAILED if the firmware reset failed.
|
||||
*/
|
||||
goto retry;
|
||||
}
|
||||
mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent,
|
||||
mdev->dma_mbdev = mbus_register_device(&mdev->pdev->dev,
|
||||
MBUS_DEV_DMA_HOST, &mic_dma_ops,
|
||||
&mbus_hw_ops, mdev->mmio.va);
|
||||
&mbus_hw_ops, id, mdev->mmio.va);
|
||||
if (IS_ERR(mdev->dma_mbdev)) {
|
||||
rc = PTR_ERR(mdev->dma_mbdev);
|
||||
goto unlock_ret;
|
||||
|
@ -401,16 +376,18 @@ int mic_start(struct mic_device *mdev, const char *buf)
|
|||
rc = -ENODEV;
|
||||
goto dma_remove;
|
||||
}
|
||||
mdev->scdev = scif_register_device(mdev->sdev->parent, MIC_SCIF_DEV,
|
||||
mdev->scdev = scif_register_device(&mdev->pdev->dev, MIC_SCIF_DEV,
|
||||
&__mic_dma_ops, &scif_hw_ops,
|
||||
mdev->id + 1, 0, &mdev->mmio,
|
||||
id + 1, 0, &mdev->mmio,
|
||||
&mdev->aper, mdev->dp, NULL,
|
||||
mdev->dma_ch, mdev->num_dma_ch);
|
||||
mdev->dma_ch, mdev->num_dma_ch,
|
||||
true);
|
||||
if (IS_ERR(mdev->scdev)) {
|
||||
rc = PTR_ERR(mdev->scdev);
|
||||
goto dma_free;
|
||||
}
|
||||
rc = mdev->ops->load_mic_fw(mdev, buf);
|
||||
|
||||
rc = mdev->ops->load_mic_fw(mdev, NULL);
|
||||
if (rc)
|
||||
goto scif_remove;
|
||||
mic_smpt_restore(mdev);
|
||||
|
@ -419,7 +396,6 @@ int mic_start(struct mic_device *mdev, const char *buf)
|
|||
mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
|
||||
mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
|
||||
mdev->ops->send_firmware_intr(mdev);
|
||||
mic_set_state(mdev, MIC_ONLINE);
|
||||
goto unlock_ret;
|
||||
scif_remove:
|
||||
scif_unregister_device(mdev->scdev);
|
||||
|
@ -428,198 +404,79 @@ int mic_start(struct mic_device *mdev, const char *buf)
|
|||
dma_remove:
|
||||
mbus_unregister_device(mdev->dma_mbdev);
|
||||
unlock_ret:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_stop - Prepare the MIC for reset and trigger reset.
|
||||
* @mdev: pointer to mic_device instance
|
||||
* _mic_stop - Prepare the MIC for reset and trigger reset.
|
||||
* @cdev: pointer to cosm_device instance
|
||||
* @force: force a MIC to reset even if it is already offline.
|
||||
*
|
||||
* RETURNS: None.
|
||||
*/
|
||||
void mic_stop(struct mic_device *mdev, bool force)
|
||||
static void _mic_stop(struct cosm_device *cdev, bool force)
|
||||
{
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
if (MIC_OFFLINE != mdev->state || force) {
|
||||
scif_unregister_device(mdev->scdev);
|
||||
mic_virtio_reset_devices(mdev);
|
||||
mic_free_dma_chans(mdev);
|
||||
mbus_unregister_device(mdev->dma_mbdev);
|
||||
mic_bootparam_init(mdev);
|
||||
mic_reset(mdev);
|
||||
if (MIC_RESET_FAILED == mdev->state)
|
||||
goto unlock;
|
||||
mic_set_shutdown_status(mdev, MIC_NOP);
|
||||
if (MIC_SUSPENDED != mdev->state)
|
||||
mic_set_state(mdev, MIC_OFFLINE);
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_shutdown - Initiate MIC shutdown.
|
||||
* @mdev: pointer to mic_device instance
|
||||
*
|
||||
* RETURNS: None.
|
||||
*/
|
||||
void mic_shutdown(struct mic_device *mdev)
|
||||
{
|
||||
struct mic_bootparam *bootparam = mdev->dp;
|
||||
s8 db = bootparam->h2c_shutdown_db;
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
if (MIC_ONLINE == mdev->state && db != -1) {
|
||||
bootparam->shutdown_card = 1;
|
||||
mdev->ops->send_intr(mdev, db);
|
||||
mic_set_state(mdev, MIC_SHUTTING_DOWN);
|
||||
}
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_shutdown_work - Handle shutdown interrupt from MIC.
|
||||
* @work: The work structure.
|
||||
*
|
||||
* This work is scheduled whenever the host has received a shutdown
|
||||
* interrupt from the MIC.
|
||||
*/
|
||||
void mic_shutdown_work(struct work_struct *work)
|
||||
{
|
||||
struct mic_device *mdev = container_of(work, struct mic_device,
|
||||
shutdown_work);
|
||||
struct mic_bootparam *bootparam = mdev->dp;
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
mic_set_shutdown_status(mdev, bootparam->shutdown_status);
|
||||
bootparam->shutdown_status = 0;
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
|
||||
/*
|
||||
* if state is MIC_SUSPENDED, OSPM suspend is in progress. We do not
|
||||
* change the state here so as to prevent users from booting the card
|
||||
* during and after the suspend operation.
|
||||
* Since SCIF handles card shutdown and reset (using COSM), it will
|
||||
* will be the first to be registered and the last to be
|
||||
* unregistered.
|
||||
*/
|
||||
if (MIC_SHUTTING_DOWN != mdev->state &&
|
||||
MIC_SUSPENDED != mdev->state)
|
||||
mic_set_state(mdev, MIC_SHUTTING_DOWN);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
mic_virtio_reset_devices(mdev);
|
||||
scif_unregister_device(mdev->scdev);
|
||||
mic_free_dma_chans(mdev);
|
||||
mbus_unregister_device(mdev->dma_mbdev);
|
||||
mic_bootparam_init(mdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_reset_trigger_work - Trigger MIC reset.
|
||||
* @work: The work structure.
|
||||
*
|
||||
* This work is scheduled whenever the host wants to reset the MIC.
|
||||
*/
|
||||
void mic_reset_trigger_work(struct work_struct *work)
|
||||
static ssize_t _mic_family(struct cosm_device *cdev, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = container_of(work, struct mic_device,
|
||||
reset_trigger_work);
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
static const char *family[MIC_FAMILY_LAST] = { "x100", "Unknown" };
|
||||
|
||||
mic_stop(mdev, false);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", family[mdev->family]);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_complete_resume - Complete MIC Resume after an OSPM suspend/hibernate
|
||||
* event.
|
||||
* @mdev: pointer to mic_device instance
|
||||
*
|
||||
* RETURNS: None.
|
||||
*/
|
||||
void mic_complete_resume(struct mic_device *mdev)
|
||||
static ssize_t _mic_stepping(struct cosm_device *cdev, char *buf)
|
||||
{
|
||||
if (mdev->state != MIC_SUSPENDED) {
|
||||
dev_warn(mdev->sdev->parent, "state %d should be %d\n",
|
||||
mdev->state, MIC_SUSPENDED);
|
||||
return;
|
||||
}
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
const char *string = "??";
|
||||
|
||||
/* Make sure firmware is ready */
|
||||
if (!mdev->ops->is_fw_ready(mdev))
|
||||
mic_stop(mdev, true);
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
mic_set_state(mdev, MIC_OFFLINE);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_prepare_suspend - Handle suspend notification for the MIC device.
|
||||
* @mdev: pointer to mic_device instance
|
||||
*
|
||||
* RETURNS: None.
|
||||
*/
|
||||
void mic_prepare_suspend(struct mic_device *mdev)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
#define MIC_SUSPEND_TIMEOUT (60 * HZ)
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
switch (mdev->state) {
|
||||
case MIC_OFFLINE:
|
||||
/*
|
||||
* Card is already offline. Set state to MIC_SUSPENDED
|
||||
* to prevent users from booting the card.
|
||||
*/
|
||||
mic_set_state(mdev, MIC_SUSPENDED);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
switch (mdev->stepping) {
|
||||
case MIC_A0_STEP:
|
||||
string = "A0";
|
||||
break;
|
||||
case MIC_ONLINE:
|
||||
/*
|
||||
* Card is online. Set state to MIC_SUSPENDING and notify
|
||||
* MIC user space daemon which will issue card
|
||||
* shutdown and reset.
|
||||
*/
|
||||
mic_set_state(mdev, MIC_SUSPENDING);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
timeout = wait_for_completion_timeout(&mdev->reset_wait,
|
||||
MIC_SUSPEND_TIMEOUT);
|
||||
/* Force reset the card if the shutdown completion timed out */
|
||||
if (!timeout) {
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
mic_set_state(mdev, MIC_SUSPENDED);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
mic_stop(mdev, true);
|
||||
}
|
||||
case MIC_B0_STEP:
|
||||
string = "B0";
|
||||
break;
|
||||
case MIC_SHUTTING_DOWN:
|
||||
/*
|
||||
* Card is shutting down. Set state to MIC_SUSPENDED
|
||||
* to prevent further boot of the card.
|
||||
*/
|
||||
mic_set_state(mdev, MIC_SUSPENDED);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
timeout = wait_for_completion_timeout(&mdev->reset_wait,
|
||||
MIC_SUSPEND_TIMEOUT);
|
||||
/* Force reset the card if the shutdown completion timed out */
|
||||
if (!timeout)
|
||||
mic_stop(mdev, true);
|
||||
case MIC_B1_STEP:
|
||||
string = "B1";
|
||||
break;
|
||||
case MIC_C0_STEP:
|
||||
string = "C0";
|
||||
break;
|
||||
default:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
break;
|
||||
}
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", string);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_suspend - Initiate MIC suspend. Suspend merely issues card shutdown.
|
||||
* @mdev: pointer to mic_device instance
|
||||
*
|
||||
* RETURNS: None.
|
||||
*/
|
||||
void mic_suspend(struct mic_device *mdev)
|
||||
static struct mic_mw *_mic_aper(struct cosm_device *cdev)
|
||||
{
|
||||
struct mic_bootparam *bootparam = mdev->dp;
|
||||
s8 db = bootparam->h2c_shutdown_db;
|
||||
struct mic_device *mdev = cosmdev_to_mdev(cdev);
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
if (MIC_SUSPENDING == mdev->state && db != -1) {
|
||||
bootparam->shutdown_card = 1;
|
||||
mdev->ops->send_intr(mdev, db);
|
||||
mic_set_state(mdev, MIC_SUSPENDED);
|
||||
}
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
return &mdev->aper;
|
||||
}
|
||||
|
||||
struct cosm_hw_ops cosm_hw_ops = {
|
||||
.reset = _mic_reset,
|
||||
.force_reset = _mic_reset,
|
||||
.post_reset = NULL,
|
||||
.ready = _mic_ready,
|
||||
.start = _mic_start,
|
||||
.stop = _mic_stop,
|
||||
.family = _mic_family,
|
||||
.stepping = _mic_stepping,
|
||||
.aper = _mic_aper,
|
||||
};
|
||||
|
|
|
@ -31,71 +31,6 @@
|
|||
/* Debugfs parent dir */
|
||||
static struct dentry *mic_dbg;
|
||||
|
||||
/**
|
||||
* mic_log_buf_show - Display MIC kernel log buffer.
|
||||
*
|
||||
* log_buf addr/len is read from System.map by user space
|
||||
* and populated in sysfs entries.
|
||||
*/
|
||||
static int mic_log_buf_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
void __iomem *log_buf_va;
|
||||
int __iomem *log_buf_len_va;
|
||||
struct mic_device *mdev = s->private;
|
||||
void *kva;
|
||||
int size;
|
||||
unsigned long aper_offset;
|
||||
|
||||
if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len)
|
||||
goto done;
|
||||
/*
|
||||
* Card kernel will never be relocated and any kernel text/data mapping
|
||||
* can be translated to phys address by subtracting __START_KERNEL_map.
|
||||
*/
|
||||
aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map;
|
||||
log_buf_len_va = mdev->aper.va + aper_offset;
|
||||
aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map;
|
||||
log_buf_va = mdev->aper.va + aper_offset;
|
||||
size = ioread32(log_buf_len_va);
|
||||
|
||||
kva = kmalloc(size, GFP_KERNEL);
|
||||
if (!kva)
|
||||
goto done;
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
memcpy_fromio(kva, log_buf_va, size);
|
||||
switch (mdev->state) {
|
||||
case MIC_ONLINE:
|
||||
/* Fall through */
|
||||
case MIC_SHUTTING_DOWN:
|
||||
seq_write(s, kva, size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
kfree(kva);
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mic_log_buf_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mic_log_buf_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int mic_log_buf_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static const struct file_operations log_buf_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mic_log_buf_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = mic_log_buf_release
|
||||
};
|
||||
|
||||
static int mic_smpt_show(struct seq_file *s, void *pos)
|
||||
{
|
||||
int i;
|
||||
|
@ -138,32 +73,6 @@ static const struct file_operations smpt_file_ops = {
|
|||
.release = mic_smpt_debug_release
|
||||
};
|
||||
|
||||
static int mic_soft_reset_show(struct seq_file *s, void *pos)
|
||||
{
|
||||
struct mic_device *mdev = s->private;
|
||||
|
||||
mic_stop(mdev, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mic_soft_reset_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mic_soft_reset_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int mic_soft_reset_debug_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static const struct file_operations soft_reset_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mic_soft_reset_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = mic_soft_reset_debug_release
|
||||
};
|
||||
|
||||
static int mic_post_code_show(struct seq_file *s, void *pos)
|
||||
{
|
||||
struct mic_device *mdev = s->private;
|
||||
|
@ -204,18 +113,8 @@ static int mic_dp_show(struct seq_file *s, void *pos)
|
|||
|
||||
seq_printf(s, "Bootparam: magic 0x%x\n",
|
||||
bootparam->magic);
|
||||
seq_printf(s, "Bootparam: h2c_shutdown_db %d\n",
|
||||
bootparam->h2c_shutdown_db);
|
||||
seq_printf(s, "Bootparam: h2c_config_db %d\n",
|
||||
bootparam->h2c_config_db);
|
||||
seq_printf(s, "Bootparam: c2h_shutdown_db %d\n",
|
||||
bootparam->c2h_shutdown_db);
|
||||
seq_printf(s, "Bootparam: shutdown_status %d\n",
|
||||
bootparam->shutdown_status);
|
||||
seq_printf(s, "Bootparam: shutdown_card %d\n",
|
||||
bootparam->shutdown_card);
|
||||
seq_printf(s, "Bootparam: tot_nodes %d\n",
|
||||
bootparam->tot_nodes);
|
||||
seq_printf(s, "Bootparam: node_id %d\n",
|
||||
bootparam->node_id);
|
||||
seq_printf(s, "Bootparam: c2h_scif_db %d\n",
|
||||
|
@ -392,8 +291,7 @@ static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
|
|||
int i, j;
|
||||
u16 entry;
|
||||
u16 vector;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
|
||||
if (pci_dev_msi_enabled(pdev)) {
|
||||
for (i = 0; i < mdev->irq_info.num_vectors; i++) {
|
||||
|
@ -454,20 +352,18 @@ static const struct file_operations msi_irq_info_ops = {
|
|||
*/
|
||||
void mic_create_debug_dir(struct mic_device *mdev)
|
||||
{
|
||||
char name[16];
|
||||
|
||||
if (!mic_dbg)
|
||||
return;
|
||||
|
||||
mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg);
|
||||
scnprintf(name, sizeof(name), "mic%d", mdev->id);
|
||||
mdev->dbg_dir = debugfs_create_dir(name, mic_dbg);
|
||||
if (!mdev->dbg_dir)
|
||||
return;
|
||||
|
||||
debugfs_create_file("log_buf", 0444, mdev->dbg_dir, mdev, &log_buf_ops);
|
||||
|
||||
debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops);
|
||||
|
||||
debugfs_create_file("soft_reset", 0444, mdev->dbg_dir, mdev,
|
||||
&soft_reset_ops);
|
||||
|
||||
debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
|
||||
&post_code_ops);
|
||||
|
||||
|
|
|
@ -26,21 +26,12 @@
|
|||
#include <linux/notifier.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/mic_bus.h>
|
||||
#include "../bus/scif_bus.h"
|
||||
#include "../bus/cosm_bus.h"
|
||||
#include "mic_intr.h"
|
||||
|
||||
/* The maximum number of MIC devices supported in a single host system. */
|
||||
#define MIC_MAX_NUM_DEVS 256
|
||||
|
||||
/**
|
||||
* enum mic_hw_family - The hardware family to which a device belongs.
|
||||
*/
|
||||
enum mic_hw_family {
|
||||
MIC_FAMILY_X100 = 0,
|
||||
MIC_FAMILY_UNKNOWN
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mic_stepping - MIC stepping ids.
|
||||
*/
|
||||
|
@ -51,6 +42,8 @@ enum mic_stepping {
|
|||
MIC_C0_STEP = 0x20,
|
||||
};
|
||||
|
||||
extern struct cosm_hw_ops cosm_hw_ops;
|
||||
|
||||
/**
|
||||
* struct mic_device - MIC device information for each card.
|
||||
*
|
||||
|
@ -60,8 +53,7 @@ enum mic_stepping {
|
|||
* @ops: MIC HW specific operations.
|
||||
* @id: The unique device id for this MIC device.
|
||||
* @stepping: Stepping ID.
|
||||
* @attr_group: Pointer to list of sysfs attribute groups.
|
||||
* @sdev: Device for sysfs entries.
|
||||
* @pdev: Underlying PCI device.
|
||||
* @mic_mutex: Mutex for synchronizing access to mic_device.
|
||||
* @intr_ops: HW specific interrupt operations.
|
||||
* @smpt_ops: Hardware specific SMPT operations.
|
||||
|
@ -69,30 +61,17 @@ enum mic_stepping {
|
|||
* @intr_info: H/W specific interrupt information.
|
||||
* @irq_info: The OS specific irq information
|
||||
* @dbg_dir: debugfs directory of this MIC device.
|
||||
* @cmdline: Kernel command line.
|
||||
* @firmware: Firmware file name.
|
||||
* @ramdisk: Ramdisk file name.
|
||||
* @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
|
||||
* @bootaddr: MIC boot address.
|
||||
* @reset_trigger_work: Work for triggering reset requests.
|
||||
* @shutdown_work: Work for handling shutdown interrupts.
|
||||
* @state: MIC state.
|
||||
* @shutdown_status: MIC status reported by card for shutdown/crashes.
|
||||
* @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
|
||||
* @reset_wait: Waitqueue for sleeping while reset completes.
|
||||
* @log_buf_addr: Log buffer address for MIC.
|
||||
* @log_buf_len: Log buffer length address for MIC.
|
||||
* @dp: virtio device page
|
||||
* @dp_dma_addr: virtio device page DMA address.
|
||||
* @shutdown_db: shutdown doorbell.
|
||||
* @shutdown_cookie: shutdown cookie.
|
||||
* @cdev: Character device for MIC.
|
||||
* @name: name for the misc char device
|
||||
* @miscdev: registered misc char device
|
||||
* @vdev_list: list of virtio devices.
|
||||
* @pm_notifier: Handles PM notifications from the OS.
|
||||
* @dma_mbdev: MIC BUS DMA device.
|
||||
* @dma_ch - Array of DMA channels
|
||||
* @num_dma_ch - Number of DMA channels available
|
||||
* @scdev: SCIF device on the SCIF virtual bus.
|
||||
* @cosm_dev: COSM device
|
||||
*/
|
||||
struct mic_device {
|
||||
struct mic_mw mmio;
|
||||
|
@ -101,8 +80,7 @@ struct mic_device {
|
|||
struct mic_hw_ops *ops;
|
||||
int id;
|
||||
enum mic_stepping stepping;
|
||||
const struct attribute_group **attr_group;
|
||||
struct device *sdev;
|
||||
struct pci_dev *pdev;
|
||||
struct mutex mic_mutex;
|
||||
struct mic_hw_intr_ops *intr_ops;
|
||||
struct mic_smpt_ops *smpt_ops;
|
||||
|
@ -110,30 +88,17 @@ struct mic_device {
|
|||
struct mic_intr_info *intr_info;
|
||||
struct mic_irq_info irq_info;
|
||||
struct dentry *dbg_dir;
|
||||
char *cmdline;
|
||||
char *firmware;
|
||||
char *ramdisk;
|
||||
char *bootmode;
|
||||
u32 bootaddr;
|
||||
struct work_struct reset_trigger_work;
|
||||
struct work_struct shutdown_work;
|
||||
u8 state;
|
||||
u8 shutdown_status;
|
||||
struct kernfs_node *state_sysfs;
|
||||
struct completion reset_wait;
|
||||
void *log_buf_addr;
|
||||
int *log_buf_len;
|
||||
void *dp;
|
||||
dma_addr_t dp_dma_addr;
|
||||
int shutdown_db;
|
||||
struct mic_irq *shutdown_cookie;
|
||||
struct cdev cdev;
|
||||
char name[16];
|
||||
struct miscdevice miscdev;
|
||||
struct list_head vdev_list;
|
||||
struct notifier_block pm_notifier;
|
||||
struct mbus_device *dma_mbdev;
|
||||
struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
|
||||
int num_dma_ch;
|
||||
struct scif_hw_dev *scdev;
|
||||
struct cosm_device *cosm_dev;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -199,38 +164,9 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
|
|||
iowrite32(val, mw->va + offset);
|
||||
}
|
||||
|
||||
static inline struct dma_chan *mic_request_dma_chan(struct mic_device *mdev)
|
||||
{
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_chan *chan;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_MEMCPY, mask);
|
||||
chan = dma_request_channel(mask, mdev->ops->dma_filter,
|
||||
mdev->sdev->parent);
|
||||
if (chan)
|
||||
return chan;
|
||||
dev_err(mdev->sdev->parent, "%s %d unable to acquire channel\n",
|
||||
__func__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mic_sysfs_init(struct mic_device *mdev);
|
||||
int mic_start(struct mic_device *mdev, const char *buf);
|
||||
void mic_stop(struct mic_device *mdev, bool force);
|
||||
void mic_shutdown(struct mic_device *mdev);
|
||||
void mic_reset_delayed_work(struct work_struct *work);
|
||||
void mic_reset_trigger_work(struct work_struct *work);
|
||||
void mic_shutdown_work(struct work_struct *work);
|
||||
void mic_bootparam_init(struct mic_device *mdev);
|
||||
void mic_set_state(struct mic_device *mdev, u8 state);
|
||||
void mic_set_shutdown_status(struct mic_device *mdev, u8 status);
|
||||
void mic_create_debug_dir(struct mic_device *dev);
|
||||
void mic_delete_debug_dir(struct mic_device *dev);
|
||||
void __init mic_init_debugfs(void);
|
||||
void mic_exit_debugfs(void);
|
||||
void mic_prepare_suspend(struct mic_device *mdev);
|
||||
void mic_complete_resume(struct mic_device *mdev);
|
||||
void mic_suspend(struct mic_device *mdev);
|
||||
extern atomic_t g_num_mics;
|
||||
#endif
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
int mic_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
struct mic_vdev *mvdev;
|
||||
struct mic_device *mdev = container_of(inode->i_cdev,
|
||||
struct mic_device, cdev);
|
||||
struct mic_device *mdev = container_of(f->private_data,
|
||||
struct mic_device, miscdev);
|
||||
|
||||
mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
|
||||
if (!mvdev)
|
||||
|
|
|
@ -30,8 +30,7 @@ static irqreturn_t mic_thread_fn(int irq, void *dev)
|
|||
struct mic_intr_info *intr_info = mdev->intr_info;
|
||||
struct mic_irq_info *irq_info = &mdev->irq_info;
|
||||
struct mic_intr_cb *intr_cb;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
int i;
|
||||
|
||||
spin_lock(&irq_info->mic_thread_lock);
|
||||
|
@ -57,8 +56,7 @@ static irqreturn_t mic_interrupt(int irq, void *dev)
|
|||
struct mic_intr_info *intr_info = mdev->intr_info;
|
||||
struct mic_irq_info *irq_info = &mdev->irq_info;
|
||||
struct mic_intr_cb *intr_cb;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
u32 mask;
|
||||
int i;
|
||||
|
||||
|
@ -83,7 +81,7 @@ static irqreturn_t mic_interrupt(int irq, void *dev)
|
|||
|
||||
/* Return the interrupt offset from the index. Index is 0 based. */
|
||||
static u16 mic_map_src_to_offset(struct mic_device *mdev,
|
||||
int intr_src, enum mic_intr_type type)
|
||||
int intr_src, enum mic_intr_type type)
|
||||
{
|
||||
if (type >= MIC_NUM_INTR_TYPES)
|
||||
return MIC_NUM_OFFSETS;
|
||||
|
@ -214,7 +212,7 @@ static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
|
|||
mdev->irq_info.msix_entries[i].entry = i;
|
||||
|
||||
rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries,
|
||||
MIC_MIN_MSIX);
|
||||
MIC_MIN_MSIX);
|
||||
if (rc) {
|
||||
dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
|
||||
goto err_enable_msix;
|
||||
|
@ -229,7 +227,7 @@ static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
|
|||
goto err_nomem2;
|
||||
}
|
||||
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
|
||||
return 0;
|
||||
err_nomem2:
|
||||
|
@ -281,7 +279,6 @@ static void mic_release_callbacks(struct mic_device *mdev)
|
|||
spin_lock(&mdev->irq_info.mic_thread_lock);
|
||||
spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
|
||||
for (i = 0; i < MIC_NUM_OFFSETS; i++) {
|
||||
|
||||
if (list_empty(&mdev->irq_info.cb_list[i]))
|
||||
break;
|
||||
|
||||
|
@ -443,12 +440,11 @@ mic_request_threaded_irq(struct mic_device *mdev,
|
|||
unsigned long cookie = 0;
|
||||
u16 entry;
|
||||
struct mic_intr_cb *intr_cb;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
|
||||
offset = mic_map_src_to_offset(mdev, intr_src, type);
|
||||
if (offset >= MIC_NUM_OFFSETS) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"Error mapping index %d to a valid source id.\n",
|
||||
intr_src);
|
||||
rc = -EINVAL;
|
||||
|
@ -458,7 +454,7 @@ mic_request_threaded_irq(struct mic_device *mdev,
|
|||
if (mdev->irq_info.num_vectors > 1) {
|
||||
msix = mic_get_available_vector(mdev);
|
||||
if (!msix) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"No MSIx vectors available for use.\n");
|
||||
rc = -ENOSPC;
|
||||
goto err;
|
||||
|
@ -467,7 +463,7 @@ mic_request_threaded_irq(struct mic_device *mdev,
|
|||
rc = request_threaded_irq(msix->vector, handler, thread_fn,
|
||||
0, name, data);
|
||||
if (rc) {
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"request irq failed rc = %d\n", rc);
|
||||
goto err;
|
||||
}
|
||||
|
@ -476,13 +472,13 @@ mic_request_threaded_irq(struct mic_device *mdev,
|
|||
mdev->intr_ops->program_msi_to_src_map(mdev,
|
||||
entry, offset, true);
|
||||
cookie = MK_COOKIE(entry, offset);
|
||||
dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
|
||||
dev_dbg(&mdev->pdev->dev, "irq: %d assigned for src: %d\n",
|
||||
msix->vector, intr_src);
|
||||
} else {
|
||||
intr_cb = mic_register_intr_callback(mdev, offset, handler,
|
||||
thread_fn, data);
|
||||
if (IS_ERR(intr_cb)) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"No available callback entries for use\n");
|
||||
rc = PTR_ERR(intr_cb);
|
||||
goto err;
|
||||
|
@ -495,7 +491,7 @@ mic_request_threaded_irq(struct mic_device *mdev,
|
|||
entry, offset, true);
|
||||
}
|
||||
cookie = MK_COOKIE(entry, intr_cb->cb_id);
|
||||
dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
|
||||
dev_dbg(&mdev->pdev->dev, "callback %d registered for src: %d\n",
|
||||
intr_cb->cb_id, intr_src);
|
||||
}
|
||||
return (struct mic_irq *)cookie;
|
||||
|
@ -515,20 +511,19 @@ mic_request_threaded_irq(struct mic_device *mdev,
|
|||
* returns: none.
|
||||
*/
|
||||
void mic_free_irq(struct mic_device *mdev,
|
||||
struct mic_irq *cookie, void *data)
|
||||
struct mic_irq *cookie, void *data)
|
||||
{
|
||||
u32 offset;
|
||||
u32 entry;
|
||||
u8 src_id;
|
||||
unsigned int irq;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
|
||||
entry = GET_ENTRY((unsigned long)cookie);
|
||||
offset = GET_OFFSET((unsigned long)cookie);
|
||||
if (mdev->irq_info.num_vectors > 1) {
|
||||
if (entry >= mdev->irq_info.num_vectors) {
|
||||
dev_warn(mdev->sdev->parent,
|
||||
dev_warn(&mdev->pdev->dev,
|
||||
"entry %d should be < num_irq %d\n",
|
||||
entry, mdev->irq_info.num_vectors);
|
||||
return;
|
||||
|
@ -539,12 +534,12 @@ void mic_free_irq(struct mic_device *mdev,
|
|||
mdev->intr_ops->program_msi_to_src_map(mdev,
|
||||
entry, offset, false);
|
||||
|
||||
dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
|
||||
dev_dbg(&mdev->pdev->dev, "irq: %d freed\n", irq);
|
||||
} else {
|
||||
irq = pdev->irq;
|
||||
src_id = mic_unregister_intr_callback(mdev, offset);
|
||||
if (src_id >= MIC_NUM_OFFSETS) {
|
||||
dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
|
||||
dev_warn(&mdev->pdev->dev, "Error unregistering callback\n");
|
||||
return;
|
||||
}
|
||||
if (pci_dev_msi_enabled(pdev)) {
|
||||
|
@ -552,7 +547,7 @@ void mic_free_irq(struct mic_device *mdev,
|
|||
mdev->intr_ops->program_msi_to_src_map(mdev,
|
||||
entry, src_id, false);
|
||||
}
|
||||
dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
|
||||
dev_dbg(&mdev->pdev->dev, "callback %d unregistered for src: %d\n",
|
||||
offset, src_id);
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +574,7 @@ int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
|
|||
|
||||
rc = mic_setup_intx(mdev, pdev);
|
||||
if (rc) {
|
||||
dev_err(mdev->sdev->parent, "no usable interrupts\n");
|
||||
dev_err(&mdev->pdev->dev, "no usable interrupts\n");
|
||||
return rc;
|
||||
}
|
||||
done:
|
||||
|
@ -635,8 +630,7 @@ void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
|
|||
void mic_intr_restore(struct mic_device *mdev)
|
||||
{
|
||||
int entry, offset;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
|
||||
if (!pci_dev_msi_enabled(pdev))
|
||||
return;
|
||||
|
|
|
@ -16,17 +16,11 @@
|
|||
* the file called "COPYING".
|
||||
*
|
||||
* Intel MIC Host driver.
|
||||
*
|
||||
* Global TODO's across the driver to be added after initial base
|
||||
* patches are accepted upstream:
|
||||
* 1) Enable DMA support.
|
||||
* 2) Enable per vring interrupt support.
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <linux/mic_common.h>
|
||||
#include "../common/mic_dev.h"
|
||||
|
@ -63,12 +57,8 @@ MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
|
|||
|
||||
/* ID allocator for MIC devices */
|
||||
static struct ida g_mic_ida;
|
||||
/* Class of MIC devices for sysfs accessibility. */
|
||||
static struct class *g_mic_class;
|
||||
/* Base device node number for MIC devices */
|
||||
static dev_t g_mic_devno;
|
||||
/* Track the total number of MIC devices */
|
||||
atomic_t g_num_mics;
|
||||
|
||||
static const struct file_operations mic_fops = {
|
||||
.open = mic_open,
|
||||
|
@ -83,17 +73,14 @@ static const struct file_operations mic_fops = {
|
|||
static int mic_dp_init(struct mic_device *mdev)
|
||||
{
|
||||
mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
|
||||
if (!mdev->dp) {
|
||||
dev_err(mdev->sdev->parent, "%s %d err %d\n",
|
||||
__func__, __LINE__, -ENOMEM);
|
||||
if (!mdev->dp)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mdev->dp_dma_addr = mic_map_single(mdev,
|
||||
mdev->dp, MIC_DP_SIZE);
|
||||
if (mic_map_error(mdev->dp_dma_addr)) {
|
||||
kfree(mdev->dp);
|
||||
dev_err(mdev->sdev->parent, "%s %d err %d\n",
|
||||
dev_err(&mdev->pdev->dev, "%s %d err %d\n",
|
||||
__func__, __LINE__, -ENOMEM);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -109,30 +96,6 @@ static void mic_dp_uninit(struct mic_device *mdev)
|
|||
kfree(mdev->dp);
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_shutdown_db - Shutdown doorbell interrupt handler.
|
||||
*/
|
||||
static irqreturn_t mic_shutdown_db(int irq, void *data)
|
||||
{
|
||||
struct mic_device *mdev = data;
|
||||
struct mic_bootparam *bootparam = mdev->dp;
|
||||
|
||||
mdev->ops->intr_workarounds(mdev);
|
||||
|
||||
switch (bootparam->shutdown_status) {
|
||||
case MIC_HALTED:
|
||||
case MIC_POWER_OFF:
|
||||
case MIC_RESTART:
|
||||
/* Fall through */
|
||||
case MIC_CRASHED:
|
||||
schedule_work(&mdev->shutdown_work);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_ops_init: Initialize HW specific operation tables.
|
||||
*
|
||||
|
@ -189,43 +152,6 @@ static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
|
|||
return family;
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_pm_notifier: Notifier callback function that handles
|
||||
* PM notifications.
|
||||
*
|
||||
* @notifier_block: The notifier structure.
|
||||
* @pm_event: The event for which the driver was notified.
|
||||
* @unused: Meaningless. Always NULL.
|
||||
*
|
||||
* returns NOTIFY_DONE
|
||||
*/
|
||||
static int mic_pm_notifier(struct notifier_block *notifier,
|
||||
unsigned long pm_event, void *unused)
|
||||
{
|
||||
struct mic_device *mdev = container_of(notifier,
|
||||
struct mic_device, pm_notifier);
|
||||
|
||||
switch (pm_event) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
/* Fall through */
|
||||
case PM_SUSPEND_PREPARE:
|
||||
mic_prepare_suspend(mdev);
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
/* Fall through */
|
||||
case PM_POST_SUSPEND:
|
||||
/* Fall through */
|
||||
case PM_POST_RESTORE:
|
||||
mic_complete_resume(mdev);
|
||||
break;
|
||||
case PM_RESTORE_PREPARE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_device_init - Allocates and initializes the MIC device structure
|
||||
*
|
||||
|
@ -234,52 +160,16 @@ static int mic_pm_notifier(struct notifier_block *notifier,
|
|||
*
|
||||
* returns none.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
mdev->pdev = pdev;
|
||||
mdev->family = mic_get_family(pdev);
|
||||
mdev->stepping = pdev->revision;
|
||||
mic_ops_init(mdev);
|
||||
mic_sysfs_init(mdev);
|
||||
mutex_init(&mdev->mic_mutex);
|
||||
mdev->irq_info.next_avail_src = 0;
|
||||
INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work);
|
||||
INIT_WORK(&mdev->shutdown_work, mic_shutdown_work);
|
||||
init_completion(&mdev->reset_wait);
|
||||
INIT_LIST_HEAD(&mdev->vdev_list);
|
||||
mdev->pm_notifier.notifier_call = mic_pm_notifier;
|
||||
rc = register_pm_notifier(&mdev->pm_notifier);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "register_pm_notifier failed rc %d\n",
|
||||
rc);
|
||||
goto register_pm_notifier_fail;
|
||||
}
|
||||
return 0;
|
||||
register_pm_notifier_fail:
|
||||
flush_work(&mdev->shutdown_work);
|
||||
flush_work(&mdev->reset_trigger_work);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mic_device_uninit - Frees resources allocated during mic_device_init(..)
|
||||
*
|
||||
* @mdev: pointer to mic_device instance
|
||||
*
|
||||
* returns none
|
||||
*/
|
||||
static void mic_device_uninit(struct mic_device *mdev)
|
||||
{
|
||||
/* The cmdline sysfs entry might have allocated cmdline */
|
||||
kfree(mdev->cmdline);
|
||||
kfree(mdev->firmware);
|
||||
kfree(mdev->ramdisk);
|
||||
kfree(mdev->bootmode);
|
||||
flush_work(&mdev->reset_trigger_work);
|
||||
flush_work(&mdev->shutdown_work);
|
||||
unregister_pm_notifier(&mdev->pm_notifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,7 +181,7 @@ static void mic_device_uninit(struct mic_device *mdev)
|
|||
* returns 0 on success, < 0 on failure.
|
||||
*/
|
||||
static int mic_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
int rc;
|
||||
struct mic_device *mdev;
|
||||
|
@ -309,16 +199,12 @@ static int mic_probe(struct pci_dev *pdev,
|
|||
goto ida_fail;
|
||||
}
|
||||
|
||||
rc = mic_device_init(mdev, pdev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "mic_device_init failed rc %d\n", rc);
|
||||
goto device_init_fail;
|
||||
}
|
||||
mic_device_init(mdev, pdev);
|
||||
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "failed to enable pci device.\n");
|
||||
goto uninit_device;
|
||||
goto ida_remove;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
@ -367,62 +253,39 @@ static int mic_probe(struct pci_dev *pdev,
|
|||
|
||||
pci_set_drvdata(pdev, mdev);
|
||||
|
||||
mdev->sdev = device_create_with_groups(g_mic_class, &pdev->dev,
|
||||
MKDEV(MAJOR(g_mic_devno), mdev->id), NULL,
|
||||
mdev->attr_group, "mic%d", mdev->id);
|
||||
if (IS_ERR(mdev->sdev)) {
|
||||
rc = PTR_ERR(mdev->sdev);
|
||||
dev_err(&pdev->dev,
|
||||
"device_create_with_groups failed rc %d\n", rc);
|
||||
goto smpt_uninit;
|
||||
}
|
||||
mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd, "state");
|
||||
if (!mdev->state_sysfs) {
|
||||
rc = -ENODEV;
|
||||
dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
|
||||
goto destroy_device;
|
||||
}
|
||||
|
||||
rc = mic_dp_init(mdev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
|
||||
goto sysfs_put;
|
||||
goto smpt_uninit;
|
||||
}
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
|
||||
mdev->shutdown_db = mic_next_db(mdev);
|
||||
mdev->shutdown_cookie = mic_request_threaded_irq(mdev, mic_shutdown_db,
|
||||
NULL, "shutdown-interrupt", mdev,
|
||||
mdev->shutdown_db, MIC_INTR_DB);
|
||||
if (IS_ERR(mdev->shutdown_cookie)) {
|
||||
rc = PTR_ERR(mdev->shutdown_cookie);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
goto dp_uninit;
|
||||
}
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
mic_bootparam_init(mdev);
|
||||
|
||||
mic_create_debug_dir(mdev);
|
||||
cdev_init(&mdev->cdev, &mic_fops);
|
||||
mdev->cdev.owner = THIS_MODULE;
|
||||
rc = cdev_add(&mdev->cdev, MKDEV(MAJOR(g_mic_devno), mdev->id), 1);
|
||||
|
||||
mdev->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
snprintf(mdev->name, sizeof(mdev->name), "mic%d", mdev->id);
|
||||
mdev->miscdev.name = mdev->name;
|
||||
mdev->miscdev.fops = &mic_fops;
|
||||
mdev->miscdev.parent = &mdev->pdev->dev;
|
||||
rc = misc_register(&mdev->miscdev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "cdev_add err id %d rc %d\n", mdev->id, rc);
|
||||
dev_err(&pdev->dev, "misc_register err id %d rc %d\n",
|
||||
mdev->id, rc);
|
||||
goto cleanup_debug_dir;
|
||||
}
|
||||
atomic_inc(&g_num_mics);
|
||||
|
||||
mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops);
|
||||
if (IS_ERR(mdev->cosm_dev)) {
|
||||
rc = PTR_ERR(mdev->cosm_dev);
|
||||
dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc);
|
||||
goto misc_dereg;
|
||||
}
|
||||
return 0;
|
||||
misc_dereg:
|
||||
misc_deregister(&mdev->miscdev);
|
||||
cleanup_debug_dir:
|
||||
mic_delete_debug_dir(mdev);
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
dp_uninit:
|
||||
mic_dp_uninit(mdev);
|
||||
sysfs_put:
|
||||
sysfs_put(mdev->state_sysfs);
|
||||
destroy_device:
|
||||
device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
|
||||
smpt_uninit:
|
||||
mic_smpt_uninit(mdev);
|
||||
free_interrupts:
|
||||
|
@ -435,9 +298,7 @@ static int mic_probe(struct pci_dev *pdev,
|
|||
pci_release_regions(pdev);
|
||||
disable_device:
|
||||
pci_disable_device(pdev);
|
||||
uninit_device:
|
||||
mic_device_uninit(mdev);
|
||||
device_init_fail:
|
||||
ida_remove:
|
||||
ida_simple_remove(&g_mic_ida, mdev->id);
|
||||
ida_fail:
|
||||
kfree(mdev);
|
||||
|
@ -461,22 +322,14 @@ static void mic_remove(struct pci_dev *pdev)
|
|||
if (!mdev)
|
||||
return;
|
||||
|
||||
mic_stop(mdev, false);
|
||||
atomic_dec(&g_num_mics);
|
||||
cdev_del(&mdev->cdev);
|
||||
cosm_unregister_device(mdev->cosm_dev);
|
||||
misc_deregister(&mdev->miscdev);
|
||||
mic_delete_debug_dir(mdev);
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
flush_work(&mdev->shutdown_work);
|
||||
mic_dp_uninit(mdev);
|
||||
sysfs_put(mdev->state_sysfs);
|
||||
device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
|
||||
mic_smpt_uninit(mdev);
|
||||
mic_free_interrupts(mdev, pdev);
|
||||
iounmap(mdev->mmio.va);
|
||||
iounmap(mdev->aper.va);
|
||||
mic_device_uninit(mdev);
|
||||
iounmap(mdev->mmio.va);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
ida_simple_remove(&g_mic_ida, mdev->id);
|
||||
|
@ -495,32 +348,23 @@ static int __init mic_init(void)
|
|||
int ret;
|
||||
|
||||
ret = alloc_chrdev_region(&g_mic_devno, 0,
|
||||
MIC_MAX_NUM_DEVS, mic_driver_name);
|
||||
MIC_MAX_NUM_DEVS, mic_driver_name);
|
||||
if (ret) {
|
||||
pr_err("alloc_chrdev_region failed ret %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_mic_class = class_create(THIS_MODULE, mic_driver_name);
|
||||
if (IS_ERR(g_mic_class)) {
|
||||
ret = PTR_ERR(g_mic_class);
|
||||
pr_err("class_create failed ret %d\n", ret);
|
||||
goto cleanup_chrdev;
|
||||
}
|
||||
|
||||
mic_init_debugfs();
|
||||
ida_init(&g_mic_ida);
|
||||
ret = pci_register_driver(&mic_driver);
|
||||
if (ret) {
|
||||
pr_err("pci_register_driver failed ret %d\n", ret);
|
||||
goto cleanup_debugfs;
|
||||
goto cleanup_chrdev;
|
||||
}
|
||||
return ret;
|
||||
cleanup_debugfs:
|
||||
cleanup_chrdev:
|
||||
ida_destroy(&g_mic_ida);
|
||||
mic_exit_debugfs();
|
||||
class_destroy(g_mic_class);
|
||||
cleanup_chrdev:
|
||||
unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
|
||||
error:
|
||||
return ret;
|
||||
|
@ -531,7 +375,6 @@ static void __exit mic_exit(void)
|
|||
pci_unregister_driver(&mic_driver);
|
||||
ida_destroy(&g_mic_ida);
|
||||
mic_exit_debugfs();
|
||||
class_destroy(g_mic_class);
|
||||
unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
|
|||
|
||||
/* Populate an SMPT entry and update the reference counts. */
|
||||
static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
|
||||
int entries, struct mic_device *mdev)
|
||||
int entries, struct mic_device *mdev)
|
||||
{
|
||||
struct mic_smpt_info *smpt_info = mdev->smpt;
|
||||
int i;
|
||||
|
@ -97,7 +97,7 @@ static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
|
|||
* for a given DMA address and size.
|
||||
*/
|
||||
static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
|
||||
int entries, s64 *ref, size_t size)
|
||||
int entries, s64 *ref, size_t size)
|
||||
{
|
||||
int spt;
|
||||
int ae = 0;
|
||||
|
@ -148,7 +148,7 @@ static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
|
|||
* and the starting smpt address
|
||||
*/
|
||||
static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
|
||||
size_t size, s64 *ref, u64 *smpt_start)
|
||||
size_t size, s64 *ref, u64 *smpt_start)
|
||||
{
|
||||
u64 start = dma_addr;
|
||||
u64 end = dma_addr + size;
|
||||
|
@ -181,7 +181,7 @@ dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
|
|||
dma_addr_t dma_addr;
|
||||
|
||||
if (!mic_is_system_addr(mdev, mic_addr)) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
|
|||
return mic_addr;
|
||||
|
||||
num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
|
||||
ref, &smpt_start);
|
||||
ref, &smpt_start);
|
||||
|
||||
/* Set the smpt table appropriately and get 16G aligned mic address */
|
||||
mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
|
||||
|
@ -231,7 +231,7 @@ dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
|
|||
* else generate mic_addr by adding the 16G offset in dma_addr
|
||||
*/
|
||||
if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"mic_map failed dma_addr 0x%llx size 0x%lx\n",
|
||||
dma_addr, size);
|
||||
return mic_addr;
|
||||
|
@ -264,7 +264,7 @@ void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
|
|||
return;
|
||||
|
||||
if (!mic_is_system_addr(mdev, mic_addr)) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"invalid address: 0x%llx\n", mic_addr);
|
||||
return;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
|
|||
for (i = spt; i < spt + num_smpt; i++) {
|
||||
smpt_info->entry[i].ref_count -= ref[i - spt];
|
||||
if (smpt_info->entry[i].ref_count < 0)
|
||||
dev_warn(mdev->sdev->parent,
|
||||
dev_warn(&mdev->pdev->dev,
|
||||
"ref count for entry %d is negative\n", i);
|
||||
}
|
||||
spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
|
||||
|
@ -307,15 +307,14 @@ void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
|
|||
dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
|
||||
{
|
||||
dma_addr_t mic_addr = 0;
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
dma_addr_t dma_addr =
|
||||
pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
if (!pci_dma_mapping_error(pdev, dma_addr)) {
|
||||
mic_addr = mic_map(mdev, dma_addr, size);
|
||||
if (!mic_addr) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"mic_map failed dma_addr 0x%llx size 0x%lx\n",
|
||||
dma_addr, size);
|
||||
pci_unmap_single(pdev, dma_addr,
|
||||
|
@ -339,8 +338,7 @@ dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
|
|||
void
|
||||
mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
|
||||
{
|
||||
struct pci_dev *pdev = container_of(mdev->sdev->parent,
|
||||
struct pci_dev, dev);
|
||||
struct pci_dev *pdev = mdev->pdev;
|
||||
dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
|
||||
mic_unmap(mdev, mic_addr, size);
|
||||
pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
|
||||
|
@ -399,18 +397,18 @@ void mic_smpt_uninit(struct mic_device *mdev)
|
|||
struct mic_smpt_info *smpt_info = mdev->smpt;
|
||||
int i;
|
||||
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
|
||||
mdev->id, smpt_info->ref_count,
|
||||
smpt_info->map_count, smpt_info->unmap_count);
|
||||
|
||||
for (i = 0; i < smpt_info->info.num_reg; i++) {
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
|
||||
i, smpt_info->entry[i].dma_addr,
|
||||
smpt_info->entry[i].ref_count);
|
||||
if (smpt_info->entry[i].ref_count)
|
||||
dev_warn(mdev->sdev->parent,
|
||||
dev_warn(&mdev->pdev->dev,
|
||||
"ref count for entry %d is not zero\n", i);
|
||||
}
|
||||
kfree(smpt_info->entry);
|
||||
|
|
|
@ -1,459 +0,0 @@
|
|||
/*
|
||||
* 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 Host driver.
|
||||
*
|
||||
*/
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <linux/mic_common.h>
|
||||
#include "../common/mic_dev.h"
|
||||
#include "mic_device.h"
|
||||
|
||||
/*
|
||||
* A state-to-string lookup table, for exposing a human readable state
|
||||
* via sysfs. Always keep in sync with enum mic_states
|
||||
*/
|
||||
static const char * const mic_state_string[] = {
|
||||
[MIC_OFFLINE] = "offline",
|
||||
[MIC_ONLINE] = "online",
|
||||
[MIC_SHUTTING_DOWN] = "shutting_down",
|
||||
[MIC_RESET_FAILED] = "reset_failed",
|
||||
[MIC_SUSPENDING] = "suspending",
|
||||
[MIC_SUSPENDED] = "suspended",
|
||||
};
|
||||
|
||||
/*
|
||||
* A shutdown-status-to-string lookup table, for exposing a human
|
||||
* readable state via sysfs. Always keep in sync with enum mic_shutdown_status
|
||||
*/
|
||||
static const char * const mic_shutdown_status_string[] = {
|
||||
[MIC_NOP] = "nop",
|
||||
[MIC_CRASHED] = "crashed",
|
||||
[MIC_HALTED] = "halted",
|
||||
[MIC_POWER_OFF] = "poweroff",
|
||||
[MIC_RESTART] = "restart",
|
||||
};
|
||||
|
||||
void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status)
|
||||
{
|
||||
dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n",
|
||||
mic_shutdown_status_string[mdev->shutdown_status],
|
||||
mic_shutdown_status_string[shutdown_status]);
|
||||
mdev->shutdown_status = shutdown_status;
|
||||
}
|
||||
|
||||
void mic_set_state(struct mic_device *mdev, u8 state)
|
||||
{
|
||||
dev_dbg(mdev->sdev->parent, "State %s -> %s\n",
|
||||
mic_state_string[mdev->state],
|
||||
mic_state_string[state]);
|
||||
mdev->state = state;
|
||||
sysfs_notify_dirent(mdev->state_sysfs);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
family_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
static const char x100[] = "x100";
|
||||
static const char unknown[] = "Unknown";
|
||||
const char *card = NULL;
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mdev->family) {
|
||||
case MIC_FAMILY_X100:
|
||||
card = x100;
|
||||
break;
|
||||
default:
|
||||
card = unknown;
|
||||
break;
|
||||
}
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", card);
|
||||
}
|
||||
static DEVICE_ATTR_RO(family);
|
||||
|
||||
static ssize_t
|
||||
stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
char *string = "??";
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mdev->stepping) {
|
||||
case MIC_A0_STEP:
|
||||
string = "A0";
|
||||
break;
|
||||
case MIC_B0_STEP:
|
||||
string = "B0";
|
||||
break;
|
||||
case MIC_B1_STEP:
|
||||
string = "B1";
|
||||
break;
|
||||
case MIC_C0_STEP:
|
||||
string = "C0";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", string);
|
||||
}
|
||||
static DEVICE_ATTR_RO(stepping);
|
||||
|
||||
static ssize_t
|
||||
state_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev || mdev->state >= MIC_LAST)
|
||||
return -EINVAL;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
mic_state_string[mdev->state]);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
state_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc = 0;
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
if (sysfs_streq(buf, "boot")) {
|
||||
rc = mic_start(mdev, buf);
|
||||
if (rc) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
"mic_boot failed rc %d\n", rc);
|
||||
count = rc;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "reset")) {
|
||||
schedule_work(&mdev->reset_trigger_work);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "shutdown")) {
|
||||
mic_shutdown(mdev);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "suspend")) {
|
||||
mic_suspend(mdev);
|
||||
goto done;
|
||||
}
|
||||
|
||||
count = -EINVAL;
|
||||
done:
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(state);
|
||||
|
||||
static ssize_t shutdown_status_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST)
|
||||
return -EINVAL;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
mic_shutdown_status_string[mdev->shutdown_status]);
|
||||
}
|
||||
static DEVICE_ATTR_RO(shutdown_status);
|
||||
|
||||
static ssize_t
|
||||
cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
char *cmdline;
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
cmdline = mdev->cmdline;
|
||||
|
||||
if (cmdline)
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cmdline_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
kfree(mdev->cmdline);
|
||||
|
||||
mdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (!mdev->cmdline) {
|
||||
count = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
strncpy(mdev->cmdline, buf, count);
|
||||
|
||||
if (mdev->cmdline[count - 1] == '\n')
|
||||
mdev->cmdline[count - 1] = '\0';
|
||||
else
|
||||
mdev->cmdline[count] = '\0';
|
||||
unlock:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(cmdline);
|
||||
|
||||
static ssize_t
|
||||
firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
char *firmware;
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
firmware = mdev->firmware;
|
||||
|
||||
if (firmware)
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
firmware_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
kfree(mdev->firmware);
|
||||
|
||||
mdev->firmware = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (!mdev->firmware) {
|
||||
count = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
strncpy(mdev->firmware, buf, count);
|
||||
|
||||
if (mdev->firmware[count - 1] == '\n')
|
||||
mdev->firmware[count - 1] = '\0';
|
||||
else
|
||||
mdev->firmware[count] = '\0';
|
||||
unlock:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(firmware);
|
||||
|
||||
static ssize_t
|
||||
ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
char *ramdisk;
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
ramdisk = mdev->ramdisk;
|
||||
|
||||
if (ramdisk)
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ramdisk_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
kfree(mdev->ramdisk);
|
||||
|
||||
mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (!mdev->ramdisk) {
|
||||
count = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
strncpy(mdev->ramdisk, buf, count);
|
||||
|
||||
if (mdev->ramdisk[count - 1] == '\n')
|
||||
mdev->ramdisk[count - 1] = '\0';
|
||||
else
|
||||
mdev->ramdisk[count] = '\0';
|
||||
unlock:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(ramdisk);
|
||||
|
||||
static ssize_t
|
||||
bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
char *bootmode;
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
bootmode = mdev->bootmode;
|
||||
|
||||
if (bootmode)
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bootmode_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf"))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mdev->mic_mutex);
|
||||
kfree(mdev->bootmode);
|
||||
|
||||
mdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
|
||||
if (!mdev->bootmode) {
|
||||
count = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
strncpy(mdev->bootmode, buf, count);
|
||||
|
||||
if (mdev->bootmode[count - 1] == '\n')
|
||||
mdev->bootmode[count - 1] = '\0';
|
||||
else
|
||||
mdev->bootmode[count] = '\0';
|
||||
unlock:
|
||||
mutex_unlock(&mdev->mic_mutex);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(bootmode);
|
||||
|
||||
static ssize_t
|
||||
log_buf_addr_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
log_buf_addr_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
int ret;
|
||||
unsigned long addr;
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtoul(buf, 16, &addr);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
mdev->log_buf_addr = (void *)addr;
|
||||
ret = count;
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RW(log_buf_addr);
|
||||
|
||||
static ssize_t
|
||||
log_buf_len_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
log_buf_len_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct mic_device *mdev = dev_get_drvdata(dev->parent);
|
||||
int ret;
|
||||
unsigned long addr;
|
||||
|
||||
if (!mdev)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtoul(buf, 16, &addr);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
mdev->log_buf_len = (int *)addr;
|
||||
ret = count;
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_RW(log_buf_len);
|
||||
|
||||
static struct attribute *mic_default_attrs[] = {
|
||||
&dev_attr_family.attr,
|
||||
&dev_attr_stepping.attr,
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_shutdown_status.attr,
|
||||
&dev_attr_cmdline.attr,
|
||||
&dev_attr_firmware.attr,
|
||||
&dev_attr_ramdisk.attr,
|
||||
&dev_attr_bootmode.attr,
|
||||
&dev_attr_log_buf_addr.attr,
|
||||
&dev_attr_log_buf_len.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(mic_default);
|
||||
|
||||
void mic_sysfs_init(struct mic_device *mdev)
|
||||
{
|
||||
mdev->attr_group = mic_default_groups;
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/mic_common.h>
|
||||
|
||||
#include "../common/mic_dev.h"
|
||||
#include "mic_device.h"
|
||||
#include "mic_smpt.h"
|
||||
|
@ -62,7 +61,7 @@ static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst,
|
|||
}
|
||||
error:
|
||||
if (err)
|
||||
dev_err(mdev->sdev->parent, "%s %d err %d\n",
|
||||
dev_err(&mdev->pdev->dev, "%s %d err %d\n",
|
||||
__func__, __LINE__, err);
|
||||
return err;
|
||||
}
|
||||
|
@ -440,7 +439,7 @@ void mic_virtio_reset_devices(struct mic_device *mdev)
|
|||
struct list_head *pos, *tmp;
|
||||
struct mic_vdev *mvdev;
|
||||
|
||||
dev_dbg(mdev->sdev->parent, "%s\n", __func__);
|
||||
dev_dbg(&mdev->pdev->dev, "%s\n", __func__);
|
||||
|
||||
list_for_each_safe(pos, tmp, &mdev->vdev_list) {
|
||||
mvdev = list_entry(pos, struct mic_vdev, list);
|
||||
|
@ -686,7 +685,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
|
|||
mvr->head = USHRT_MAX;
|
||||
mvr->mvdev = mvdev;
|
||||
mvr->vrh.notify = mic_notify;
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"%s %d index %d va %p info %p vr_size 0x%x\n",
|
||||
__func__, __LINE__, i, vr->va, vr->info, vr_size);
|
||||
mvr->buf = (void *)__get_free_pages(GFP_KERNEL,
|
||||
|
@ -704,7 +703,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
|
|||
mvdev->virtio_db, MIC_INTR_DB);
|
||||
if (IS_ERR(mvdev->virtio_cookie)) {
|
||||
ret = PTR_ERR(mvdev->virtio_cookie);
|
||||
dev_dbg(mdev->sdev->parent, "request irq failed\n");
|
||||
dev_dbg(&mdev->pdev->dev, "request irq failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -720,7 +719,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
|
|||
smp_wmb();
|
||||
dd->type = type;
|
||||
|
||||
dev_dbg(mdev->sdev->parent, "Added virtio device id %d\n", dd->type);
|
||||
dev_dbg(&mdev->pdev->dev, "Added virtio device id %d\n", dd->type);
|
||||
|
||||
db = bootparam->h2c_config_db;
|
||||
if (db != -1)
|
||||
|
@ -755,7 +754,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
|
|||
db = bootparam->h2c_config_db;
|
||||
if (db == -1)
|
||||
goto skip_hot_remove;
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"Requesting hot remove id %d\n", mvdev->virtio_id);
|
||||
mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
|
||||
mdev->ops->send_intr(mdev, db);
|
||||
|
@ -765,7 +764,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
|
|||
if (ret)
|
||||
break;
|
||||
}
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"Device id %d config_change %d guest_ack %d retry %d\n",
|
||||
mvdev->virtio_id, mvdev->dc->config_change,
|
||||
mvdev->dc->guest_ack, retry);
|
||||
|
@ -794,7 +793,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
|
|||
tmp_mvdev = list_entry(pos, struct mic_vdev, list);
|
||||
if (tmp_mvdev == mvdev) {
|
||||
list_del(pos);
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"Removing virtio device id %d\n",
|
||||
mvdev->virtio_id);
|
||||
break;
|
||||
|
|
|
@ -124,7 +124,7 @@ void mic_bh_handler(struct work_struct *work);
|
|||
/* Helper API to obtain the MIC PCIe device */
|
||||
static inline struct device *mic_dev(struct mic_vdev *mvdev)
|
||||
{
|
||||
return mvdev->mdev->sdev->parent;
|
||||
return &mvdev->mdev->pdev->dev;
|
||||
}
|
||||
|
||||
/* Helper API to check if a virtio device is initialized */
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
static void
|
||||
mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
|
||||
{
|
||||
dev_dbg(mdev->sdev->parent, "Writing 0x%x to scratch pad index %d\n",
|
||||
dev_dbg(&mdev->pdev->dev, "Writing 0x%x to scratch pad index %d\n",
|
||||
val, idx);
|
||||
mic_mmio_write(&mdev->mmio, val,
|
||||
MIC_X100_SBOX_BASE_ADDRESS +
|
||||
|
@ -66,7 +66,7 @@ mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
|
|||
MIC_X100_SBOX_BASE_ADDRESS +
|
||||
MIC_X100_SBOX_SPAD0 + idx * 4);
|
||||
|
||||
dev_dbg(mdev->sdev->parent,
|
||||
dev_dbg(&mdev->pdev->dev,
|
||||
"Reading 0x%x from scratch pad index %d\n", val, idx);
|
||||
return val;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ static void mic_x100_disable_interrupts(struct mic_device *mdev)
|
|||
* @mdev: pointer to mic_device instance
|
||||
*/
|
||||
static void mic_x100_send_sbox_intr(struct mic_device *mdev,
|
||||
int doorbell)
|
||||
int doorbell)
|
||||
{
|
||||
struct mic_mw *mw = &mdev->mmio;
|
||||
u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
|
||||
|
@ -147,7 +147,7 @@ static void mic_x100_send_sbox_intr(struct mic_device *mdev,
|
|||
* @mdev: pointer to mic_device instance
|
||||
*/
|
||||
static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
|
||||
int doorbell)
|
||||
int doorbell)
|
||||
{
|
||||
int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
|
||||
/* Ensure that the interrupt is ordered w.r.t. previous stores. */
|
||||
|
@ -359,15 +359,14 @@ mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw)
|
|||
|
||||
boot_mem = mdev->aper.len >> 20;
|
||||
buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
"%s %d allocation failed\n", __func__, __LINE__);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
len += snprintf(buf, CMDLINE_SIZE - len,
|
||||
" mem=%dM", boot_mem);
|
||||
if (mdev->cmdline)
|
||||
snprintf(buf + len, CMDLINE_SIZE - len, " %s", mdev->cmdline);
|
||||
if (mdev->cosm_dev->cmdline)
|
||||
snprintf(buf + len, CMDLINE_SIZE - len, " %s",
|
||||
mdev->cosm_dev->cmdline);
|
||||
memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
|
||||
kfree(buf);
|
||||
return 0;
|
||||
|
@ -386,12 +385,11 @@ mic_x100_load_ramdisk(struct mic_device *mdev)
|
|||
int rc;
|
||||
struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr;
|
||||
|
||||
rc = request_firmware(&fw,
|
||||
mdev->ramdisk, mdev->sdev->parent);
|
||||
rc = request_firmware(&fw, mdev->cosm_dev->ramdisk, &mdev->pdev->dev);
|
||||
if (rc < 0) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"ramdisk request_firmware failed: %d %s\n",
|
||||
rc, mdev->ramdisk);
|
||||
rc, mdev->cosm_dev->ramdisk);
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
|
@ -423,10 +421,10 @@ mic_x100_get_boot_addr(struct mic_device *mdev)
|
|||
|
||||
scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
|
||||
boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
|
||||
dev_dbg(mdev->sdev->parent, "%s %d boot_addr 0x%x\n",
|
||||
dev_dbg(&mdev->pdev->dev, "%s %d boot_addr 0x%x\n",
|
||||
__func__, __LINE__, boot_addr);
|
||||
if (boot_addr > (1 << 31)) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"incorrect bootaddr 0x%x\n",
|
||||
boot_addr);
|
||||
rc = -EINVAL;
|
||||
|
@ -454,37 +452,37 @@ mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
|
|||
if (rc)
|
||||
goto error;
|
||||
/* load OS */
|
||||
rc = request_firmware(&fw, mdev->firmware, mdev->sdev->parent);
|
||||
rc = request_firmware(&fw, mdev->cosm_dev->firmware, &mdev->pdev->dev);
|
||||
if (rc < 0) {
|
||||
dev_err(mdev->sdev->parent,
|
||||
dev_err(&mdev->pdev->dev,
|
||||
"ramdisk request_firmware failed: %d %s\n",
|
||||
rc, mdev->firmware);
|
||||
rc, mdev->cosm_dev->firmware);
|
||||
goto error;
|
||||
}
|
||||
if (mdev->bootaddr > mdev->aper.len - fw->size) {
|
||||
rc = -EINVAL;
|
||||
dev_err(mdev->sdev->parent, "%s %d rc %d bootaddr 0x%x\n",
|
||||
dev_err(&mdev->pdev->dev, "%s %d rc %d bootaddr 0x%x\n",
|
||||
__func__, __LINE__, rc, mdev->bootaddr);
|
||||
release_firmware(fw);
|
||||
goto error;
|
||||
}
|
||||
memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
|
||||
mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
|
||||
if (!strcmp(mdev->bootmode, "elf"))
|
||||
if (!strcmp(mdev->cosm_dev->bootmode, "flash"))
|
||||
goto done;
|
||||
/* load command line */
|
||||
rc = mic_x100_load_command_line(mdev, fw);
|
||||
if (rc) {
|
||||
dev_err(mdev->sdev->parent, "%s %d rc %d\n",
|
||||
dev_err(&mdev->pdev->dev, "%s %d rc %d\n",
|
||||
__func__, __LINE__, rc);
|
||||
goto error;
|
||||
}
|
||||
release_firmware(fw);
|
||||
/* load ramdisk */
|
||||
if (mdev->ramdisk)
|
||||
if (mdev->cosm_dev->ramdisk)
|
||||
rc = mic_x100_load_ramdisk(mdev);
|
||||
error:
|
||||
dev_dbg(mdev->sdev->parent, "%s %d rc %d\n", __func__, __LINE__, rc);
|
||||
dev_dbg(&mdev->pdev->dev, "%s %d rc %d\n", __func__, __LINE__, rc);
|
||||
done:
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue