diff options
Diffstat (limited to 'drivers')
444 files changed, 16679 insertions, 7507 deletions
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index f85014fbaa12..8ffc308d5fd0 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -81,9 +81,21 @@ static const struct i2c_device_id bmc150_accel_id[] = { MODULE_DEVICE_TABLE(i2c, bmc150_accel_id); +static const struct of_device_id bmc150_accel_of_match[] = { + { .compatible = "bosch,bmc150_accel" }, + { .compatible = "bosch,bmi055_accel" }, + { .compatible = "bosch,bma255" }, + { .compatible = "bosch,bma250e" }, + { .compatible = "bosch,bma222e" }, + { .compatible = "bosch,bma280" }, + { }, +}; +MODULE_DEVICE_TABLE(of, bmc150_accel_of_match); + static struct i2c_driver bmc150_accel_driver = { .driver = { .name = "bmc150_accel_i2c", + .of_match_table = bmc150_accel_of_match, .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match), .pm = &bmc150_accel_pm_ops, }, diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c index 6c214783241c..d4b555203427 100644 --- a/drivers/iio/accel/da280.c +++ b/drivers/iio/accel/da280.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/i2c.h> +#include <linux/acpi.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/byteorder/generic.h> @@ -25,7 +26,7 @@ #define DA280_MODE_ENABLE 0x1e #define DA280_MODE_DISABLE 0x9e -enum { da226, da280 }; +enum da280_chipset { da226, da280 }; /* * a value of + or -4096 corresponds to + or - 1G @@ -91,12 +92,24 @@ static const struct iio_info da280_info = { .read_raw = da280_read_raw, }; +static enum da280_chipset da280_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return -EINVAL; + + return (enum da280_chipset) id->driver_data; +} + static int da280_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; struct iio_dev *indio_dev; struct da280_data *data; + enum da280_chipset chip; ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID); if (ret != DA280_CHIP_ID) @@ -114,7 +127,14 @@ static int da280_probe(struct i2c_client *client, indio_dev->info = &da280_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = da280_channels; - if (id->driver_data == da226) { + + if (ACPI_HANDLE(&client->dev)) { + chip = da280_match_acpi_device(&client->dev); + } else { + chip = id->driver_data; + } + + if (chip == da226) { indio_dev->name = "da226"; indio_dev->num_channels = 2; } else { @@ -158,6 +178,12 @@ static int da280_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume); +static const struct acpi_device_id da280_acpi_match[] = { + {"MIRAACC", da280}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, da280_acpi_match); + static const struct i2c_device_id da280_i2c_id[] = { { "da226", da226 }, { "da280", da280 }, @@ -168,6 +194,7 @@ MODULE_DEVICE_TABLE(i2c, da280_i2c_id); static struct i2c_driver da280_driver = { .driver = { .name = "da280", + .acpi_match_table = ACPI_PTR(da280_acpi_match), .pm = &da280_pm_ops, }, .probe = da280_probe, diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c index 98fbb628d5bd..38411e1c155b 100644 --- a/drivers/iio/accel/kxsd9-i2c.c +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -63,3 +63,6 @@ static struct i2c_driver kxsd9_i2c_driver = { .id_table = kxsd9_i2c_id, }; module_i2c_driver(kxsd9_i2c_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("KXSD9 accelerometer I2C interface"); diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index bfd4bc806fc2..43c3a6b00340 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -135,7 +135,7 @@ struct mma8452_event_regs { u8 ev_count; }; -static const struct mma8452_event_regs ev_regs_accel_falling = { +static const struct mma8452_event_regs ff_mt_ev_regs = { .ev_cfg = MMA8452_FF_MT_CFG, .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE, .ev_cfg_chan_shift = MMA8452_FF_MT_CHAN_SHIFT, @@ -145,7 +145,7 @@ static const struct mma8452_event_regs ev_regs_accel_falling = { .ev_count = MMA8452_FF_MT_COUNT }; -static const struct mma8452_event_regs ev_regs_accel_rising = { +static const struct mma8452_event_regs trans_ev_regs = { .ev_cfg = MMA8452_TRANSIENT_CFG, .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, .ev_cfg_chan_shift = MMA8452_TRANSIENT_CHAN_SHIFT, @@ -284,7 +284,7 @@ static const int mma8452_samp_freq[8][2] = { }; /* Datasheet table: step time "Relationship with the ODR" (sample frequency) */ -static const unsigned int mma8452_transient_time_step_us[4][8] = { +static const unsigned int mma8452_time_step_us[4][8] = { { 1250, 2500, 5000, 10000, 20000, 20000, 20000, 20000 }, /* normal */ { 1250, 2500, 5000, 10000, 20000, 80000, 80000, 80000 }, /* l p l n */ { 1250, 2500, 2500, 2500, 2500, 2500, 2500, 2500 }, /* high res*/ @@ -777,12 +777,12 @@ static int mma8452_get_event_regs(struct mma8452_data *data, & MMA8452_INT_TRANS) && (data->chip_info->enabled_events & MMA8452_INT_TRANS)) - *ev_reg = &ev_regs_accel_rising; + *ev_reg = &trans_ev_regs; else - *ev_reg = &ev_regs_accel_falling; + *ev_reg = &ff_mt_ev_regs; return 0; case IIO_EV_DIR_FALLING: - *ev_reg = &ev_regs_accel_falling; + *ev_reg = &ff_mt_ev_regs; return 0; default: return -EINVAL; @@ -826,7 +826,7 @@ static int mma8452_read_event_value(struct iio_dev *indio_dev, if (power_mode < 0) return power_mode; - us = ret * mma8452_transient_time_step_us[power_mode][ + us = ret * mma8452_time_step_us[power_mode][ mma8452_get_odr_index(data)]; *val = us / USEC_PER_SEC; *val2 = us % USEC_PER_SEC; @@ -883,7 +883,7 @@ static int mma8452_write_event_value(struct iio_dev *indio_dev, return ret; steps = (val * USEC_PER_SEC + val2) / - mma8452_transient_time_step_us[ret][ + mma8452_time_step_us[ret][ mma8452_get_odr_index(data)]; if (steps < 0 || steps > 0xff) diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 460aa58e0159..6fe995cf16a6 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -920,8 +920,6 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); - struct st_sensors_platform_data *pdata = - (struct st_sensors_platform_data *)adata->dev->platform_data; int irq = adata->get_irq_data_ready(indio_dev); int err; @@ -948,9 +946,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev) &adata->sensor_settings->fs.fs_avl[0]; adata->odr = adata->sensor_settings->odr.odr_avl[0].hz; - if (!pdata) - pdata = (struct st_sensors_platform_data *)&default_accel_pdata; - err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); if (err < 0) goto st_accel_power_off; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ef86296b8b0d..486793691de0 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -158,6 +158,7 @@ config AT91_SAMA5D2_ADC tristate "Atmel AT91 SAMA5D2 ADC" depends on ARCH_AT91 || COMPILE_TEST depends on HAS_IOMEM + depends on HAS_DMA select IIO_TRIGGERED_BUFFER help Say yes here to build support for Atmel SAMA5D2 ADC which is diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 8a958d5f1905..327a49ba1991 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/reset.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -53,11 +54,12 @@ struct aspeed_adc_model_data { }; struct aspeed_adc_data { - struct device *dev; - void __iomem *base; - spinlock_t clk_lock; - struct clk_hw *clk_prescaler; - struct clk_hw *clk_scaler; + struct device *dev; + void __iomem *base; + spinlock_t clk_lock; + struct clk_hw *clk_prescaler; + struct clk_hw *clk_scaler; + struct reset_control *rst; }; #define ASPEED_CHAN(_idx, _data_reg_addr) { \ @@ -217,6 +219,15 @@ static int aspeed_adc_probe(struct platform_device *pdev) goto scaler_error; } + data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(data->rst)) { + dev_err(&pdev->dev, + "invalid or missing reset controller device tree entry"); + ret = PTR_ERR(data->rst); + goto reset_error; + } + reset_control_deassert(data->rst); + model_data = of_device_get_match_data(&pdev->dev); if (model_data->wait_init_sequence) { @@ -263,9 +274,10 @@ iio_register_error: writel(ASPEED_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); +reset_error: + reset_control_assert(data->rst); clk_enable_error: clk_hw_unregister_divider(data->clk_scaler); - scaler_error: clk_hw_unregister_divider(data->clk_prescaler); return ret; @@ -280,6 +292,7 @@ static int aspeed_adc_remove(struct platform_device *pdev) writel(ASPEED_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); + reset_control_assert(data->rst); clk_hw_unregister_divider(data->clk_scaler); clk_hw_unregister_divider(data->clk_prescaler); diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 755a493c2a2c..4eff8351ce29 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -16,6 +16,8 @@ #include <linux/bitops.h> #include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> @@ -100,6 +102,8 @@ #define AT91_SAMA5D2_LCDR 0x20 /* Interrupt Enable Register */ #define AT91_SAMA5D2_IER 0x24 +/* Interrupt Enable Register - general overrun error */ +#define AT91_SAMA5D2_IER_GOVRE BIT(25) /* Interrupt Disable Register */ #define AT91_SAMA5D2_IDR 0x28 /* Interrupt Mask Register */ @@ -167,13 +171,19 @@ /* * Maximum number of bytes to hold conversion from all channels - * plus the timestamp + * without the timestamp. */ -#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \ - AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8) +#define AT91_BUFFER_MAX_CONVERSION_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \ + AT91_SAMA5D2_DIFF_CHAN_CNT) * 2) + +/* This total must also include the timestamp */ +#define AT91_BUFFER_MAX_BYTES (AT91_BUFFER_MAX_CONVERSION_BYTES + 8) #define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2) +#define AT91_HWFIFO_MAX_SIZE_STR "128" +#define AT91_HWFIFO_MAX_SIZE 128 + #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ { \ .type = IIO_VOLTAGE, \ @@ -228,6 +238,28 @@ struct at91_adc_trigger { bool hw_trig; }; +/** + * at91_adc_dma - at91-sama5d2 dma information struct + * @dma_chan: the dma channel acquired + * @rx_buf: dma coherent allocated area + * @rx_dma_buf: dma handler for the buffer + * @phys_addr: physical address of the ADC base register + * @buf_idx: index inside the dma buffer where reading was last done + * @rx_buf_sz: size of buffer used by DMA operation + * @watermark: number of conversions to copy before DMA triggers irq + * @dma_ts: hold the start timestamp of dma operation + */ +struct at91_adc_dma { + struct dma_chan *dma_chan; + u8 *rx_buf; + dma_addr_t rx_dma_buf; + phys_addr_t phys_addr; + int buf_idx; + int rx_buf_sz; + int watermark; + s64 dma_ts; +}; + struct at91_adc_state { void __iomem *base; int irq; @@ -242,6 +274,7 @@ struct at91_adc_state { u32 conversion_value; struct at91_adc_soc_info soc_info; wait_queue_head_t wq_data_available; + struct at91_adc_dma dma_st; u16 buffer[AT91_BUFFER_MAX_HWORDS]; /* * lock to prevent concurrent 'single conversion' requests through @@ -322,11 +355,17 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) if (state) { at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); - at91_adc_writel(st, AT91_SAMA5D2_IER, - BIT(chan->channel)); + /* enable irq only if not using DMA */ + if (!st->dma_st.dma_chan) { + at91_adc_writel(st, AT91_SAMA5D2_IER, + BIT(chan->channel)); + } } else { - at91_adc_writel(st, AT91_SAMA5D2_IDR, - BIT(chan->channel)); + /* disable irq only if not using DMA */ + if (!st->dma_st.dma_chan) { + at91_adc_writel(st, AT91_SAMA5D2_IDR, + BIT(chan->channel)); + } at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); } @@ -340,6 +379,10 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig) struct iio_dev *indio = iio_trigger_get_drvdata(trig); struct at91_adc_state *st = iio_priv(indio); + /* if we are using DMA, we must not reenable irq after each trigger */ + if (st->dma_st.dma_chan) + return 0; + enable_irq(st->irq); /* Needed to ACK the DRDY interruption */ @@ -350,6 +393,153 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig) static const struct iio_trigger_ops at91_adc_trigger_ops = { .set_trigger_state = &at91_adc_configure_trigger, .try_reenable = &at91_adc_reenable_trigger, + .validate_device = iio_trigger_validate_own_device, +}; + +static int at91_adc_dma_size_done(struct at91_adc_state *st) +{ + struct dma_tx_state state; + enum dma_status status; + int i, size; + + status = dmaengine_tx_status(st->dma_st.dma_chan, + st->dma_st.dma_chan->cookie, + &state); + if (status != DMA_IN_PROGRESS) + return 0; + + /* Transferred length is size in bytes from end of buffer */ + i = st->dma_st.rx_buf_sz - state.residue; + + /* Return available bytes */ + if (i >= st->dma_st.buf_idx) + size = i - st->dma_st.buf_idx; + else + size = st->dma_st.rx_buf_sz + i - st->dma_st.buf_idx; + return size; +} + +static void at91_dma_buffer_done(void *data) +{ + struct iio_dev *indio_dev = data; + + iio_trigger_poll_chained(indio_dev->trig); +} + +static int at91_adc_dma_start(struct iio_dev *indio_dev) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + int ret; + u8 bit; + + if (!st->dma_st.dma_chan) + return 0; + + /* we start a new DMA, so set buffer index to start */ + st->dma_st.buf_idx = 0; + + /* + * compute buffer size w.r.t. watermark and enabled channels. + * scan_bytes is aligned so we need an exact size for DMA + */ + st->dma_st.rx_buf_sz = 0; + + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->num_channels) { + struct iio_chan_spec const *chan = indio_dev->channels + bit; + + st->dma_st.rx_buf_sz += chan->scan_type.storagebits / 8; + } + st->dma_st.rx_buf_sz *= st->dma_st.watermark; + + /* Prepare a DMA cyclic transaction */ + desc = dmaengine_prep_dma_cyclic(st->dma_st.dma_chan, + st->dma_st.rx_dma_buf, + st->dma_st.rx_buf_sz, + st->dma_st.rx_buf_sz / 2, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); + + if (!desc) { + dev_err(&indio_dev->dev, "cannot prepare DMA cyclic\n"); + return -EBUSY; + } + + desc->callback = at91_dma_buffer_done; + desc->callback_param = indio_dev; + + cookie = dmaengine_submit(desc); + ret = dma_submit_error(cookie); + if (ret) { + dev_err(&indio_dev->dev, "cannot submit DMA cyclic\n"); + dmaengine_terminate_async(st->dma_st.dma_chan); + return ret; + } + + /* enable general overrun error signaling */ + at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_GOVRE); + /* Issue pending DMA requests */ + dma_async_issue_pending(st->dma_st.dma_chan); + + /* consider current time as DMA start time for timestamps */ + st->dma_st.dma_ts = iio_get_time_ns(indio_dev); + + dev_dbg(&indio_dev->dev, "DMA cyclic started\n"); + + return 0; +} + +static int at91_adc_buffer_postenable(struct iio_dev *indio_dev) +{ + int ret; + + ret = at91_adc_dma_start(indio_dev); + if (ret) { + dev_err(&indio_dev->dev, "buffer postenable failed\n"); + return ret; + } + + return iio_triggered_buffer_postenable(indio_dev); +} + +static int at91_adc_buffer_predisable(struct iio_dev *indio_dev) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + int ret; + u8 bit; + + ret = iio_triggered_buffer_predisable(indio_dev); + if (ret < 0) + dev_err(&indio_dev->dev, "buffer predisable failed\n"); + + if (!st->dma_st.dma_chan) + return ret; + + /* if we are using DMA we must clear registers and end DMA */ + dmaengine_terminate_sync(st->dma_st.dma_chan); + + /* + * For each enabled channel we must read the last converted value + * to clear EOC status and not get a possible interrupt later. + * This value is being read by DMA from LCDR anyway + */ + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->num_channels) { + struct iio_chan_spec const *chan = indio_dev->channels + bit; + + if (st->dma_st.dma_chan) + at91_adc_readl(st, chan->address); + } + + /* read overflow register to clear possible overflow status */ + at91_adc_readl(st, AT91_SAMA5D2_OVER); + return ret; +} + +static const struct iio_buffer_setup_ops at91_buffer_setup_ops = { + .postenable = &at91_adc_buffer_postenable, + .predisable = &at91_adc_buffer_predisable, }; static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, @@ -388,24 +578,77 @@ static int at91_adc_trigger_init(struct iio_dev *indio) return 0; } -static irqreturn_t at91_adc_trigger_handler(int irq, void *p) +static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev, + struct iio_poll_func *pf) { - struct iio_poll_func *pf = p; - struct iio_dev *indio = pf->indio_dev; - struct at91_adc_state *st = iio_priv(indio); + struct at91_adc_state *st = iio_priv(indio_dev); int i = 0; u8 bit; - for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { - struct iio_chan_spec const *chan = indio->channels + bit; + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->num_channels) { + struct iio_chan_spec const *chan = indio_dev->channels + bit; st->buffer[i] = at91_adc_readl(st, chan->address); i++; } + iio_push_to_buffers_with_timestamp(indio_dev, st->buffer, + pf->timestamp); +} - iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp); +static void at91_adc_trigger_handler_dma(struct iio_dev *indio_dev) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + int transferred_len = at91_adc_dma_size_done(st); + s64 ns = iio_get_time_ns(indio_dev); + s64 interval; + int sample_index = 0, sample_count, sample_size; + + u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); + /* if we reached this point, we cannot sample faster */ + if (status & AT91_SAMA5D2_IER_GOVRE) + pr_info_ratelimited("%s: conversion overrun detected\n", + indio_dev->name); - iio_trigger_notify_done(indio->trig); + sample_size = div_s64(st->dma_st.rx_buf_sz, st->dma_st.watermark); + + sample_count = div_s64(transferred_len, sample_size); + + /* + * interval between samples is total time since last transfer handling + * divided by the number of samples (total size divided by sample size) + */ + interval = div_s64((ns - st->dma_st.dma_ts), sample_count); + + while (transferred_len >= sample_size) { + iio_push_to_buffers_with_timestamp(indio_dev, + (st->dma_st.rx_buf + st->dma_st.buf_idx), + (st->dma_st.dma_ts + interval * sample_index)); + /* adjust remaining length */ + transferred_len -= sample_size; + /* adjust buffer index */ + st->dma_st.buf_idx += sample_size; + /* in case of reaching end of buffer, reset index */ + if (st->dma_st.buf_idx >= st->dma_st.rx_buf_sz) + st->dma_st.buf_idx = 0; + sample_index++; + } + /* adjust saved time for next transfer handling */ + st->dma_st.dma_ts = iio_get_time_ns(indio_dev); +} + +static irqreturn_t at91_adc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct at91_adc_state *st = iio_priv(indio_dev); + + if (st->dma_st.dma_chan) + at91_adc_trigger_handler_dma(indio_dev); + else + at91_adc_trigger_handler_nodma(indio_dev, pf); + + iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } @@ -414,7 +657,7 @@ static int at91_adc_buffer_init(struct iio_dev *indio) { return devm_iio_triggered_buffer_setup(&indio->dev, indio, &iio_pollfunc_store_time, - &at91_adc_trigger_handler, NULL); + &at91_adc_trigger_handler, &at91_buffer_setup_ops); } static unsigned at91_adc_startup_time(unsigned startup_time_min, @@ -485,10 +728,13 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) if (!(status & imr)) return IRQ_NONE; - if (iio_buffer_enabled(indio)) { + if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) { disable_irq_nosync(irq); iio_trigger_poll(indio->trig); - } else { + } else if (iio_buffer_enabled(indio) && st->dma_st.dma_chan) { + disable_irq_nosync(irq); + WARN(true, "Unexpected irq occurred\n"); + } else if (!iio_buffer_enabled(indio)) { st->conversion_value = at91_adc_readl(st, st->chan->address); st->conversion_done = true; wake_up_interruptible(&st->wq_data_available); @@ -510,7 +756,6 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; - mutex_lock(&st->lock); st->chan = chan; @@ -541,6 +786,9 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); + /* Needed to ACK the DRDY interruption */ + at91_adc_readl(st, AT91_SAMA5D2_LCDR); + mutex_unlock(&st->lock); iio_device_release_direct_mode(indio_dev); @@ -580,9 +828,123 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev, return 0; } +static void at91_adc_dma_init(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct at91_adc_state *st = iio_priv(indio_dev); + struct dma_slave_config config = {0}; + /* + * We make the buffer double the size of the fifo, + * such that DMA uses one half of the buffer (full fifo size) + * and the software uses the other half to read/write. + */ + unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE * + AT91_BUFFER_MAX_CONVERSION_BYTES * 2, + PAGE_SIZE); + + if (st->dma_st.dma_chan) + return; + + st->dma_st.dma_chan = dma_request_slave_channel(&pdev->dev, "rx"); + + if (!st->dma_st.dma_chan) { + dev_info(&pdev->dev, "can't get DMA channel\n"); + goto dma_exit; + } + + st->dma_st.rx_buf = dma_alloc_coherent(st->dma_st.dma_chan->device->dev, + pages * PAGE_SIZE, + &st->dma_st.rx_dma_buf, + GFP_KERNEL); + if (!st->dma_st.rx_buf) { + dev_info(&pdev->dev, "can't allocate coherent DMA area\n"); + goto dma_chan_disable; + } + + /* Configure DMA channel to read data register */ + config.direction = DMA_DEV_TO_MEM; + config.src_addr = (phys_addr_t)(st->dma_st.phys_addr + + AT91_SAMA5D2_LCDR); + config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + config.src_maxburst = 1; + config.dst_maxburst = 1; + + if (dmaengine_slave_config(st->dma_st.dma_chan, &config)) { + dev_info(&pdev->dev, "can't configure DMA slave\n"); + goto dma_free_area; + } + + dev_info(&pdev->dev, "using %s for rx DMA transfers\n", + dma_chan_name(st->dma_st.dma_chan)); + + return; + +dma_free_area: + dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE, + st->dma_st.rx_buf, st->dma_st.rx_dma_buf); +dma_chan_disable: + dma_release_channel(st->dma_st.dma_chan); + st->dma_st.dma_chan = 0; +dma_exit: + dev_info(&pdev->dev, "continuing without DMA support\n"); +} + +static void at91_adc_dma_disable(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct at91_adc_state *st = iio_priv(indio_dev); + unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE * + AT91_BUFFER_MAX_CONVERSION_BYTES * 2, + PAGE_SIZE); + + /* if we are not using DMA, just return */ + if (!st->dma_st.dma_chan) + return; + + /* wait for all transactions to be terminated first*/ + dmaengine_terminate_sync(st->dma_st.dma_chan); + + dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE, + st->dma_st.rx_buf, st->dma_st.rx_dma_buf); + dma_release_channel(st->dma_st.dma_chan); + st->dma_st.dma_chan = 0; + + dev_info(&pdev->dev, "continuing without DMA support\n"); +} + +static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + + if (val > AT91_HWFIFO_MAX_SIZE) + return -EINVAL; + + if (!st->selected_trig->hw_trig) { + dev_dbg(&indio_dev->dev, "we need hw trigger for DMA\n"); + return 0; + } + + dev_dbg(&indio_dev->dev, "new watermark is %u\n", val); + st->dma_st.watermark = val; + + /* + * The logic here is: if we have watermark 1, it means we do + * each conversion with it's own IRQ, thus we don't need DMA. + * If the watermark is higher, we do DMA to do all the transfers in bulk + */ + + if (val == 1) + at91_adc_dma_disable(to_platform_device(&indio_dev->dev)); + else if (val > 1) + at91_adc_dma_init(to_platform_device(&indio_dev->dev)); + + return 0; +} + static const struct iio_info at91_adc_info = { .read_raw = &at91_adc_read_raw, .write_raw = &at91_adc_write_raw, + .hwfifo_set_watermark = &at91_adc_set_watermark, }; static void at91_adc_hw_init(struct at91_adc_state *st) @@ -599,6 +961,42 @@ static void at91_adc_hw_init(struct at91_adc_state *st) at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); } +static ssize_t at91_adc_get_fifo_state(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = + platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(indio_dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", !!st->dma_st.dma_chan); +} + +static ssize_t at91_adc_get_watermark(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = + platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(indio_dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark); +} + +static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + at91_adc_get_fifo_state, NULL, 0); +static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, + at91_adc_get_watermark, NULL, 0); + +static IIO_CONST_ATTR(hwfifo_watermark_min, "2"); +static IIO_CONST_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR); + +static const struct attribute *at91_adc_fifo_attributes[] = { + &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark.dev_attr.attr, + &iio_dev_attr_hwfifo_enabled.dev_attr.attr, + NULL, +}; + static int at91_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; @@ -674,6 +1072,9 @@ static int at91_adc_probe(struct platform_device *pdev) if (!res) return -EINVAL; + /* if we plan to use DMA, we need the physical address of the regs */ + st->dma_st.phys_addr = res->start; + st->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(st->base)) return PTR_ERR(st->base); @@ -737,11 +1138,22 @@ static int at91_adc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "couldn't setup the triggers.\n"); goto per_clk_disable_unprepare; } + /* + * Initially the iio buffer has a length of 2 and + * a watermark of 1 + */ + st->dma_st.watermark = 1; + + iio_buffer_set_attrs(indio_dev->buffer, + at91_adc_fifo_attributes); } + if (dma_coerce_mask_and_coherent(&indio_dev->dev, DMA_BIT_MASK(32))) + dev_info(&pdev->dev, "cannot set DMA mask to 32-bit\n"); + ret = iio_device_register(indio_dev); if (ret < 0) - goto per_clk_disable_unprepare; + goto dma_disable; if (st->selected_trig->hw_trig) dev_info(&pdev->dev, "setting up trigger as %s\n", @@ -752,6 +1164,8 @@ static int at91_adc_probe(struct platform_device *pdev) return 0; +dma_disable: + at91_adc_dma_disable(pdev); per_clk_disable_unprepare: clk_disable_unprepare(st->per_clk); vref_disable: @@ -768,6 +1182,8 @@ static int at91_adc_remove(struct platform_device *pdev) iio_device_unregister(indio_dev); + at91_adc_dma_disable(pdev); + clk_disable_unprepare(st->per_clk); regulator_disable(st->vref); diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 60c9e853dd81..031d568b4972 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -92,22 +92,14 @@ static const struct iio_chan_spec axp288_adc_channels[] = { }, }; -#define AXP288_ADC_MAP(_adc_channel_label, _consumer_dev_name, \ - _consumer_channel) \ - { \ - .adc_channel_label = _adc_channel_label, \ - .consumer_dev_name = _consumer_dev_name, \ - .consumer_channel = _consumer_channel, \ - } - /* for consumer drivers */ static struct iio_map axp288_adc_default_maps[] = { - AXP288_ADC_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"), - AXP288_ADC_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"), - AXP288_ADC_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"), - AXP288_ADC_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"), - AXP288_ADC_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"), - AXP288_ADC_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"), + IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"), + IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"), + IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"), + IIO_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"), + IIO_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"), + IIO_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"), {}, }; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 84a43871f7dc..ddf878163bf9 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -44,13 +44,14 @@ #define INA226_MASK_ENABLE 0x06 #define INA226_CVRF BIT(3) -#define INA219_CNVR BIT(1) #define INA2XX_MAX_REGISTERS 8 /* settings - depend on use case */ -#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ +#define INA219_CONFIG_DEFAULT 0x399F /* PGA=1/8, BRNG=32V */ #define INA219_DEFAULT_IT 532 +#define INA219_DEFAULT_BRNG 1 /* 32V */ +#define INA219_DEFAULT_PGA 125 /* 1000/8 */ #define INA226_CONFIG_DEFAULT 0x4327 #define INA226_DEFAULT_AVG 4 #define INA226_DEFAULT_IT 1110 @@ -63,6 +64,14 @@ */ #define INA2XX_MODE_MASK GENMASK(3, 0) +/* Gain for VShunt: 1/8 (default), 1/4, 1/2, 1 */ +#define INA219_PGA_MASK GENMASK(12, 11) +#define INA219_SHIFT_PGA(val) ((val) << 11) + +/* VBus range: 32V (default), 16V */ +#define INA219_BRNG_MASK BIT(13) +#define INA219_SHIFT_BRNG(val) ((val) << 13) + /* Averaging for VBus/VShunt/Power */ #define INA226_AVG_MASK GENMASK(11, 9) #define INA226_SHIFT_AVG(val) ((val) << 9) @@ -79,6 +88,11 @@ #define INA226_ITS_MASK GENMASK(5, 3) #define INA226_SHIFT_ITS(val) ((val) << 3) +/* INA219 Bus voltage register, low bits are flags */ +#define INA219_OVF BIT(0) +#define INA219_CNVR BIT(1) +#define INA219_BUS_VOLTAGE_SHIFT 3 + /* Cosmetic macro giving the sampling period for a full P=UxI cycle */ #define SAMPLING_PERIOD(c) ((c->int_time_vbus + c->int_time_vshunt) \ * c->avg) @@ -111,8 +125,8 @@ enum ina2xx_ids { ina219, ina226 }; struct ina2xx_config { u16 config_default; int calibration_factor; - int shunt_div; - int bus_voltage_shift; + int shunt_voltage_lsb; /* nV */ + int bus_voltage_shift; /* position of lsb */ int bus_voltage_lsb; /* uV */ int power_lsb; /* uW */ enum ina2xx_ids chip_id; @@ -127,6 +141,8 @@ struct ina2xx_chip_info { int avg; int int_time_vbus; /* Bus voltage integration time uS */ int int_time_vshunt; /* Shunt voltage integration time uS */ + int range_vbus; /* Bus voltage maximum in V */ + int pga_gain_vshunt; /* Shunt voltage PGA gain */ bool allow_async_readout; }; @@ -134,8 +150,8 @@ static const struct ina2xx_config ina2xx_config[] = { [ina219] = { .config_default = INA219_CONFIG_DEFAULT, .calibration_factor = 40960000, - .shunt_div = 100, - .bus_voltage_shift = 3, + .shunt_voltage_lsb = 10000, + .bus_voltage_shift = INA219_BUS_VOLTAGE_SHIFT, .bus_voltage_lsb = 4000, .power_lsb = 20000, .chip_id = ina219, @@ -143,7 +159,7 @@ static const struct ina2xx_config ina2xx_config[] = { [ina226] = { .config_default = INA226_CONFIG_DEFAULT, .calibration_factor = 5120000, - .shunt_div = 400, + .shunt_voltage_lsb = 2500, .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb = 25000, @@ -170,6 +186,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, else *val = regval; + if (chan->address == INA2XX_BUS_VOLTAGE) + *val >>= chip->config->bus_voltage_shift; + return IIO_VAL_INT; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: @@ -197,15 +216,15 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->address) { case INA2XX_SHUNT_VOLTAGE: - /* processed (mV) = raw/shunt_div */ - *val2 = chip->config->shunt_div; - *val = 1; + /* processed (mV) = raw * lsb(nV) / 1000000 */ + *val = chip->config->shunt_voltage_lsb; + *val2 = 1000000; return IIO_VAL_FRACTIONAL; case INA2XX_BUS_VOLTAGE: - /* processed (mV) = raw*lsb (uV) / (1000 << shift) */ + /* processed (mV) = raw * lsb (uV) / 1000 */ *val = chip->config->bus_voltage_lsb; - *val2 = 1000 << chip->config->bus_voltage_shift; + *val2 = 1000; return IIO_VAL_FRACTIONAL; case INA2XX_POWER: @@ -219,6 +238,18 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, *val = 1; return IIO_VAL_INT; } + + case IIO_CHAN_INFO_HARDWAREGAIN: + switch (chan->address) { + case INA2XX_SHUNT_VOLTAGE: + *val = chip->pga_gain_vshunt; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; + + case INA2XX_BUS_VOLTAGE: + *val = chip->range_vbus == 32 ? 1 : 2; + return IIO_VAL_INT; + } } return -EINVAL; @@ -353,6 +384,74 @@ static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip, return 0; } +static const int ina219_vbus_range_tab[] = { 1, 2 }; +static int ina219_set_vbus_range_denom(struct ina2xx_chip_info *chip, + unsigned int range, + unsigned int *config) +{ + if (range == 1) + chip->range_vbus = 32; + else if (range == 2) + chip->range_vbus = 16; + else + return -EINVAL; + + *config &= ~INA219_BRNG_MASK; + *config |= INA219_SHIFT_BRNG(range == 1 ? 1 : 0) & INA219_BRNG_MASK; + + return 0; +} + +static const int ina219_vshunt_gain_tab[] = { 125, 250, 500, 1000 }; +static const int ina219_vshunt_gain_frac[] = { + 125, 1000, 250, 1000, 500, 1000, 1000, 1000 }; + +static int ina219_set_vshunt_pga_gain(struct ina2xx_chip_info *chip, + unsigned int gain, + unsigned int *config) +{ + int bits; + + if (gain < 125 || gain > 1000) + return -EINVAL; + + bits = find_closest(gain, ina219_vshunt_gain_tab, + ARRAY_SIZE(ina219_vshunt_gain_tab)); + + chip->pga_gain_vshunt = ina219_vshunt_gain_tab[bits]; + bits = 3 - bits; + + *config &= ~INA219_PGA_MASK; + *config |= INA219_SHIFT_PGA(bits) & INA219_PGA_MASK; + + return 0; +} + +static int ina2xx_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_HARDWAREGAIN: + switch (chan->address) { + case INA2XX_SHUNT_VOLTAGE: + *type = IIO_VAL_FRACTIONAL; + *length = sizeof(ina219_vshunt_gain_frac) / sizeof(int); + *vals = ina219_vshunt_gain_frac; + return IIO_AVAIL_LIST; + + case INA2XX_BUS_VOLTAGE: + *type = IIO_VAL_INT; + *length = sizeof(ina219_vbus_range_tab) / sizeof(int); + *vals = ina219_vbus_range_tab; + return IIO_AVAIL_LIST; + } + } + + return -EINVAL; +} + static int ina2xx_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -395,6 +494,14 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev, } break; + case IIO_CHAN_INFO_HARDWAREGAIN: + if (chan->address == INA2XX_SHUNT_VOLTAGE) + ret = ina219_set_vshunt_pga_gain(chip, val * 1000 + + val2 / 1000, &tmp); + else + ret = ina219_set_vbus_range_denom(chip, val, &tmp); + break; + default: ret = -EINVAL; } @@ -532,19 +639,23 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, * Sampling Freq is a consequence of the integration times of * the Voltage channels. */ -#define INA219_CHAN_VOLTAGE(_index, _address) { \ +#define INA219_CHAN_VOLTAGE(_index, _address, _shift) { \ .type = IIO_VOLTAGE, \ .address = (_address), \ .indexed = 1, \ .channel = (_index), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_INT_TIME), \ + BIT(IIO_CHAN_INFO_INT_TIME) | \ + BIT(IIO_CHAN_INFO_HARDWAREGAIN), \ + .info_mask_separate_available = \ + BIT(IIO_CHAN_INFO_HARDWAREGAIN), \ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (_index), \ .scan_type = { \ .sign = 'u', \ - .realbits = 16, \ + .shift = _shift, \ + .realbits = 16 - _shift, \ .storagebits = 16, \ .endianness = IIO_LE, \ } \ @@ -579,8 +690,8 @@ static const struct iio_chan_spec ina226_channels[] = { }; static const struct iio_chan_spec ina219_channels[] = { - INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), - INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), + INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE, 0), + INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE, INA219_BUS_VOLTAGE_SHIFT), INA219_CHAN(IIO_POWER, 2, INA2XX_POWER), INA219_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), IIO_CHAN_SOFT_TIMESTAMP(4), @@ -746,7 +857,6 @@ static IIO_CONST_ATTR_NAMED(ina226_integration_time_available, integration_time_available, "0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244"); - static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR, ina2xx_allow_async_readout_show, ina2xx_allow_async_readout_store, 0); @@ -780,6 +890,7 @@ static const struct attribute_group ina226_attribute_group = { static const struct iio_info ina219_info = { .attrs = &ina219_attribute_group, .read_raw = ina2xx_read_raw, + .read_avail = ina2xx_read_avail, .write_raw = ina2xx_write_raw, .debugfs_reg_access = ina2xx_debug_reg, }; @@ -860,6 +971,8 @@ static int ina2xx_probe(struct i2c_client *client, chip->avg = 1; ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val); ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val); + ina219_set_vbus_range_denom(chip, INA219_DEFAULT_BRNG, &val); + ina219_set_vshunt_pga_gain(chip, INA219_DEFAULT_PGA, &val); } ret = ina2xx_init(chip, val); diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 36047147ce7c..48fdbb3a061b 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -233,7 +233,6 @@ struct meson_sar_adc_priv { const struct meson_sar_adc_data *data; struct clk *clkin; struct clk *core_clk; - struct clk *sana_clk; struct clk *adc_sel_clk; struct clk *adc_clk; struct clk_gate clk_gate; @@ -731,12 +730,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) goto err_core_clk; } - ret = clk_prepare_enable(priv->sana_clk); - if (ret) { - dev_err(indio_dev->dev.parent, "failed to enable sana clk\n"); - goto err_sana_clk; - } - regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); @@ -763,8 +756,6 @@ err_adc_clk: regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, MESON_SAR_ADC_REG3_ADC_EN, 0); meson_sar_adc_set_bandgap(indio_dev, false); - clk_disable_unprepare(priv->sana_clk); -err_sana_clk: clk_disable_unprepare(priv->core_clk); err_core_clk: regulator_disable(priv->vref); @@ -790,7 +781,6 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev) meson_sar_adc_set_bandgap(indio_dev, false); - clk_disable_unprepare(priv->sana_clk); clk_disable_unprepare(priv->core_clk); regulator_disable(priv->vref); @@ -993,16 +983,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return PTR_ERR(priv->core_clk); } - priv->sana_clk = devm_clk_get(&pdev->dev, "sana"); - if (IS_ERR(priv->sana_clk)) { - if (PTR_ERR(priv->sana_clk) == -ENOENT) { - priv->sana_clk = NULL; - } else { - dev_err(&pdev->dev, "failed to get sana clk\n"); - return PTR_ERR(priv->sana_clk); - } - } - priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk"); if (IS_ERR(priv->adc_clk)) { if (PTR_ERR(priv->adc_clk) == -ENOENT) { diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index 47d24ae5462f..fe3d7826783c 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -5,6 +5,7 @@ #include <linux/math64.h> #include <linux/log2.h> #include <linux/err.h> +#include <linux/module.h> #include "qcom-vadc-common.h" @@ -229,3 +230,6 @@ int qcom_vadc_decimation_from_dt(u32 value) return __ffs64(value / VADC_DECIMATION_MIN); } EXPORT_SYMBOL(qcom_vadc_decimation_from_dt); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Qualcomm ADC common functionality"); diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index c9d96f935dba..da7fef376ed8 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -92,6 +92,7 @@ #define STM32H7_ADC_SQR3 0x38 #define STM32H7_ADC_SQR4 0x3C #define STM32H7_ADC_DR 0x40 +#define STM32H7_ADC_DIFSEL 0xC0 #define STM32H7_ADC_CALFACT 0xC4 #define STM32H7_ADC_CALFACT2 0xC8 @@ -153,6 +154,8 @@ enum stm32h7_adc_dmngt { /* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */ #define STM32H7_BOOST_CLKRATE 20000000UL +#define STM32_ADC_CH_MAX 20 /* max number of channels */ +#define STM32_ADC_CH_SZ 10 /* max channel name size */ #define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */ #define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */ #define STM32_ADC_TIMEOUT_US 100000 @@ -297,9 +300,11 @@ struct stm32_adc_cfg { * @rx_buf: dma rx buffer cpu address * @rx_dma_buf: dma rx buffer bus address * @rx_buf_sz: dma rx buffer size + * @difsel bitmask to set single-ended/differential channel * @pcsel bitmask to preselect channels on some devices * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) * @cal: optional calibration data on some devices + * @chan_name: channel name array */ struct stm32_adc { struct stm32_adc_common *common; @@ -318,72 +323,37 @@ struct stm32_adc { u8 *rx_buf; dma_addr_t rx_dma_buf; unsigned int rx_buf_sz; + u32 difsel; u32 pcsel; u32 smpr_val[2]; struct stm32_adc_calib cal; + char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ]; }; -/** - * struct stm32_adc_chan_spec - specification of stm32 adc channel - * @type: IIO channel type - * @channel: channel number (single ended) - * @name: channel name (single ended) - */ -struct stm32_adc_chan_spec { - enum iio_chan_type type; - int channel; - const char *name; +struct stm32_adc_diff_channel { + u32 vinp; + u32 vinn; }; /** * struct stm32_adc_info - stm32 ADC, per instance config data - * @channels: Reference to stm32 channels spec * @max_channels: Number of channels * @resolutions: available resolutions * @num_res: number of available resolutions */ struct stm32_adc_info { - const struct stm32_adc_chan_spec *channels; int max_channels; const unsigned int *resolutions; const unsigned int num_res; }; -/* - * Input definitions common for all instances: - * stm32f4 can have up to 16 channels - * stm32h7 can have up to 20 channels - */ -static const struct stm32_adc_chan_spec stm32_adc_channels[] = { - { IIO_VOLTAGE, 0, "in0" }, - { IIO_VOLTAGE, 1, "in1" }, - { IIO_VOLTAGE, 2, "in2" }, - { IIO_VOLTAGE, 3, "in3" }, - { IIO_VOLTAGE, 4, "in4" }, - { IIO_VOLTAGE, 5, "in5" }, - { IIO_VOLTAGE, 6, "in6" }, - { IIO_VOLTAGE, 7, "in7" }, - { IIO_VOLTAGE, 8, "in8" }, - { IIO_VOLTAGE, 9, "in9" }, - { IIO_VOLTAGE, 10, "in10" }, - { IIO_VOLTAGE, 11, "in11" }, - { IIO_VOLTAGE, 12, "in12" }, - { IIO_VOLTAGE, 13, "in13" }, - { IIO_VOLTAGE, 14, "in14" }, - { IIO_VOLTAGE, 15, "in15" }, - { IIO_VOLTAGE, 16, "in16" }, - { IIO_VOLTAGE, 17, "in17" }, - { IIO_VOLTAGE, 18, "in18" }, - { IIO_VOLTAGE, 19, "in19" }, -}; - static const unsigned int stm32f4_adc_resolutions[] = { /* sorted values so the index matches RES[1:0] in STM32F4_ADC_CR1 */ 12, 10, 8, 6, }; +/* stm32f4 can have up to 16 channels */ static const struct stm32_adc_info stm32f4_adc_info = { - .channels = stm32_adc_channels, .max_channels = 16, .resolutions = stm32f4_adc_resolutions, .num_res = ARRAY_SIZE(stm32f4_adc_resolutions), @@ -394,9 +364,9 @@ static const unsigned int stm32h7_adc_resolutions[] = { 16, 14, 12, 10, 8, }; +/* stm32h7 can have up to 20 channels */ static const struct stm32_adc_info stm32h7_adc_info = { - .channels = stm32_adc_channels, - .max_channels = 20, + .max_channels = STM32_ADC_CH_MAX, .resolutions = stm32h7_adc_resolutions, .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), }; @@ -983,15 +953,19 @@ pwr_dwn: * stm32h7_adc_prepare() - Leave power down mode to enable ADC. * @adc: stm32 adc instance * Leave power down mode. + * Configure channels as single ended or differential before enabling ADC. * Enable ADC. * Restore calibration data. - * Pre-select channels that may be used in PCSEL (required by input MUX / IO). + * Pre-select channels that may be used in PCSEL (required by input MUX / IO): + * - Only one input is selected for single ended (e.g. 'vinp') + * - Two inputs are selected for differential channels (e.g. 'vinp' & 'vinn') */ static int stm32h7_adc_prepare(struct stm32_adc *adc) { int ret; stm32h7_adc_exit_pwr_down(adc); + stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel); ret = stm32h7_adc_enable(adc); if (ret) @@ -1263,10 +1237,23 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, return ret; case IIO_CHAN_INFO_SCALE: - *val = adc->common->vref_mv; - *val2 = chan->scan_type.realbits; + if (chan->differential) { + *val = adc->common->vref_mv * 2; + *val2 = chan->scan_type.realbits; + } else { + *val = adc->common->vref_mv; + *val2 = chan->scan_type.realbits; + } return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + if (chan->differential) + /* ADC_full_scale / 2 */ + *val = -((1 << chan->scan_type.realbits) / 2); + else + *val = 0; + return IIO_VAL_INT; + default: return -EINVAL; } @@ -1628,29 +1615,40 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns) } static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, - const struct stm32_adc_chan_spec *channel, - int scan_index, u32 smp) + struct iio_chan_spec *chan, u32 vinp, + u32 vinn, int scan_index, bool differential) { struct stm32_adc *adc = iio_priv(indio_dev); - - chan->type = channel->type; - chan->channel = channel->channel; - chan->datasheet_name = channel->name; + char *name = adc->chan_name[vinp]; + + chan->type = IIO_VOLTAGE; + chan->channel = vinp; + if (differential) { + chan->differential = 1; + chan->channel2 = vinn; + snprintf(name, STM32_ADC_CH_SZ, "in%d-in%d", vinp, vinn); + } else { + snprintf(name, STM32_ADC_CH_SZ, "in%d", vinp); + } + chan->datasheet_name = name; chan->scan_index = scan_index; chan->indexed = 1; chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET); chan->scan_type.sign = 'u'; chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res]; chan->scan_type.storagebits = 16; chan->ext_info = stm32_adc_ext_info; - /* Prepare sampling time settings */ - stm32_adc_smpr_init(adc, chan->channel, smp); - /* pre-build selected channels mask */ adc->pcsel |= BIT(chan->channel); + if (differential) { + /* pre-build diff channels mask */ + adc->difsel |= BIT(chan->channel); + /* Also add negative input to pre-selected channels */ + adc->pcsel |= BIT(chan->channel2); + } } static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) @@ -1658,17 +1656,40 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) struct device_node *node = indio_dev->dev.of_node; struct stm32_adc *adc = iio_priv(indio_dev); const struct stm32_adc_info *adc_info = adc->cfg->adc_info; + struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX]; struct property *prop; const __be32 *cur; struct iio_chan_spec *channels; - int scan_index = 0, num_channels, ret; + int scan_index = 0, num_channels = 0, num_diff = 0, ret, i; u32 val, smp = 0; - num_channels = of_property_count_u32_elems(node, "st,adc-channels"); - if (num_channels < 0 || - num_channels > adc_info->max_channels) { + ret = of_property_count_u32_elems(node, "st,adc-channels"); + if (ret > adc_info->max_channels) { dev_err(&indio_dev->dev, "Bad st,adc-channels?\n"); - return num_channels < 0 ? num_channels : -EINVAL; + return -EINVAL; + } else if (ret > 0) { + num_channels += ret; + } + + ret = of_property_count_elems_of_size(node, "st,adc-diff-channels", + sizeof(*diff)); + if (ret > adc_info->max_channels) { + dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n"); + return -EINVAL; + } else if (ret > 0) { + int size = ret * sizeof(*diff) / sizeof(u32); + + num_diff = ret; + num_channels += ret; + ret = of_property_read_u32_array(node, "st,adc-diff-channels", + (u32 *)diff, size); + if (ret) + return ret; + } + + if (!num_channels) { + dev_err(&indio_dev->dev, "No channels configured\n"); + return -ENODATA; } /* Optional sample time is provided either for each, or all channels */ @@ -1689,6 +1710,33 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) return -EINVAL; } + /* Channel can't be configured both as single-ended & diff */ + for (i = 0; i < num_diff; i++) { + if (val == diff[i].vinp) { + dev_err(&indio_dev->dev, + "channel %d miss-configured\n", val); + return -EINVAL; + } + } + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, + 0, scan_index, false); + scan_index++; + } + + for (i = 0; i < num_diff; i++) { + if (diff[i].vinp >= adc_info->max_channels || + diff[i].vinn >= adc_info->max_channels) { + dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n", + diff[i].vinp, diff[i].vinn); + return -EINVAL; + } + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], + diff[i].vinp, diff[i].vinn, scan_index, + true); + scan_index++; + } + + for (i = 0; i < scan_index; i++) { /* * Using of_property_read_u32_index(), smp value will only be * modified if valid u32 value can be decoded. This allows to @@ -1696,12 +1744,9 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) * value per channel. */ of_property_read_u32_index(node, "st,min-sample-time-nsecs", - scan_index, &smp); - - stm32_adc_chan_init_one(indio_dev, &channels[scan_index], - &adc_info->channels[val], - scan_index, smp); - scan_index++; + i, &smp); + /* Prepare sampling time settings */ + stm32_adc_smpr_init(adc, channels[i].channel, smp); } indio_dev->num_channels = scan_index; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index ed8063f2da99..7d30c59da3e2 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -191,7 +191,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); - struct cros_ec_device *ec_device; struct iio_dev *indio_dev; struct cros_ec_sensors_state *state; struct iio_chan_spec *channel; @@ -201,7 +200,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "No CROS EC device found.\n"); return -EINVAL; } - ec_device = ec_dev->ec_dev; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); if (!indio_dev) diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 147a8c14235f..15ccadc74891 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -3,6 +3,9 @@ * * Copyright (C) 2017 Matt Ranostay <matt@ranostay.consulting> * + * Support for MAX30105 optical particle sensor + * Copyright (C) 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net> + * * 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 @@ -13,6 +16,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * 7-bit I2C chip address: 0x57 * TODO: proximity power saving feature */ @@ -32,6 +36,18 @@ #define MAX30102_REGMAP_NAME "max30102_regmap" #define MAX30102_DRV_NAME "max30102" +#define MAX30102_PART_NUMBER 0x15 + +enum max30102_chip_id { + max30102, + max30105, +}; + +enum max3012_led_idx { + MAX30102_LED_RED, + MAX30102_LED_IR, + MAX30105_LED_GREEN, +}; #define MAX30102_REG_INT_STATUS 0x00 #define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0) @@ -52,7 +68,7 @@ #define MAX30102_REG_FIFO_OVR_CTR 0x05 #define MAX30102_REG_FIFO_RD_PTR 0x06 #define MAX30102_REG_FIFO_DATA 0x07 -#define MAX30102_REG_FIFO_DATA_ENTRY_LEN 6 +#define MAX30102_REG_FIFO_DATA_BYTES 3 #define MAX30102_REG_FIFO_CONFIG 0x08 #define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES BIT(1) @@ -60,11 +76,18 @@ #define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0) #define MAX30102_REG_MODE_CONFIG 0x09 -#define MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0) -#define MAX30102_REG_MODE_CONFIG_MODE_HR_EN BIT(1) -#define MAX30102_REG_MODE_CONFIG_MODE_MASK 0x03 +#define MAX30102_REG_MODE_CONFIG_MODE_NONE 0x00 +#define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */ +#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */ +#define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */ +#define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0) #define MAX30102_REG_MODE_CONFIG_PWR BIT(7) +#define MAX30102_REG_MODE_CONTROL_SLOT21 0x11 /* multi-LED control */ +#define MAX30102_REG_MODE_CONTROL_SLOT43 0x12 +#define MAX30102_REG_MODE_CONTROL_SLOT_MASK (GENMASK(6, 4) | GENMASK(2, 0)) +#define MAX30102_REG_MODE_CONTROL_SLOT_SHIFT 4 + #define MAX30102_REG_SPO2_CONFIG 0x0a #define MAX30102_REG_SPO2_CONFIG_PULSE_411_US 0x03 #define MAX30102_REG_SPO2_CONFIG_SR_400HZ 0x03 @@ -75,6 +98,7 @@ #define MAX30102_REG_RED_LED_CONFIG 0x0c #define MAX30102_REG_IR_LED_CONFIG 0x0d +#define MAX30105_REG_GREEN_LED_CONFIG 0x0e #define MAX30102_REG_TEMP_CONFIG 0x21 #define MAX30102_REG_TEMP_CONFIG_TEMP_EN BIT(0) @@ -82,14 +106,18 @@ #define MAX30102_REG_TEMP_INTEGER 0x1f #define MAX30102_REG_TEMP_FRACTION 0x20 +#define MAX30102_REG_REV_ID 0xfe +#define MAX30102_REG_PART_ID 0xff + struct max30102_data { struct i2c_client *client; struct iio_dev *indio_dev; struct mutex lock; struct regmap *regmap; + enum max30102_chip_id chip_id; - u8 buffer[8]; - __be32 processed_buffer[2]; /* 2 x 18-bit (padded to 32-bits) */ + u8 buffer[12]; + __be32 processed_buffer[3]; /* 3 x 18-bit (padded to 32-bits) */ }; static const struct regmap_config max30102_regmap_config = { @@ -99,37 +127,47 @@ static const struct regmap_config max30102_regmap_config = { .val_bits = 8, }; -static const unsigned long max30102_scan_masks[] = {0x3, 0}; +static const unsigned long max30102_scan_masks[] = { + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR), + 0 +}; + +static const unsigned long max30105_scan_masks[] = { + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR), + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) | + BIT(MAX30105_LED_GREEN), + 0 +}; + +#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \ + .type = IIO_INTENSITY, \ + .channel2 = _mod, \ + .modified = 1, \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 'u', \ + .shift = 8, \ + .realbits = 18, \ + .storagebits = 32, \ + .endianness = IIO_BE, \ + }, \ + } static const struct iio_chan_spec max30102_channels[] = { + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED), + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR), { - .type = IIO_INTENSITY, - .channel2 = IIO_MOD_LIGHT_RED, - .modified = 1, - - .scan_index = 0, - .scan_type = { - .sign = 'u', - .shift = 8, - .realbits = 18, - .storagebits = 32, - .endianness = IIO_BE, - }, - }, - { - .type = IIO_INTENSITY, - .channel2 = IIO_MOD_LIGHT_IR, - .modified = 1, - - .scan_index = 1, - .scan_type = { - .sign = 'u', - .shift = 8, - .realbits = 18, - .storagebits = 32, - .endianness = IIO_BE, - }, + .type = IIO_TEMP, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = -1, }, +}; + +static const struct iio_chan_spec max30105_channels[] = { + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED), + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR), + MAX30102_INTENSITY_CHANNEL(MAX30105_LED_GREEN, IIO_MOD_LIGHT_GREEN), { .type = IIO_TEMP, .info_mask_separate = @@ -138,25 +176,69 @@ static const struct iio_chan_spec max30102_channels[] = { }, }; -static int max30102_set_powermode(struct max30102_data *data, bool state) +static int max30102_set_power(struct max30102_data *data, bool en) { return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG, MAX30102_REG_MODE_CONFIG_PWR, - state ? 0 : MAX30102_REG_MODE_CONFIG_PWR); + en ? 0 : MAX30102_REG_MODE_CONFIG_PWR); } +static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en) +{ + u8 reg = mode; + + if (!en) + reg |= MAX30102_REG_MODE_CONFIG_PWR; + + return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG, + MAX30102_REG_MODE_CONFIG_PWR | + MAX30102_REG_MODE_CONFIG_MODE_MASK, reg); +} + +#define MAX30102_MODE_CONTROL_LED_SLOTS(slot2, slot1) \ + ((slot2 << MAX30102_REG_MODE_CONTROL_SLOT_SHIFT) | slot1) + static int max30102_buffer_postenable(struct iio_dev *indio_dev) { struct max30102_data *data = iio_priv(indio_dev); + int ret; + u8 reg; - return max30102_set_powermode(data, true); + switch (*indio_dev->active_scan_mask) { + case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR): + reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2; + break; + case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) | + BIT(MAX30105_LED_GREEN): + ret = regmap_update_bits(data->regmap, + MAX30102_REG_MODE_CONTROL_SLOT21, + MAX30102_REG_MODE_CONTROL_SLOT_MASK, + MAX30102_MODE_CONTROL_LED_SLOTS(2, 1)); + if (ret) + return ret; + + ret = regmap_update_bits(data->regmap, + MAX30102_REG_MODE_CONTROL_SLOT43, + MAX30102_REG_MODE_CONTROL_SLOT_MASK, + MAX30102_MODE_CONTROL_LED_SLOTS(0, 3)); + if (ret) + return ret; + + reg = MAX30102_REG_MODE_CONFIG_MODE_MULTI; + break; + default: + return -EINVAL; + } + + return max30102_set_powermode(data, reg, true); } static int max30102_buffer_predisable(struct iio_dev *indio_dev) { struct max30102_data *data = iio_priv(indio_dev); - return max30102_set_powermode(data, false); + return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE, + false); } static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = { @@ -180,32 +262,51 @@ static inline int max30102_fifo_count(struct max30102_data *data) return 0; } -static int max30102_read_measurement(struct max30102_data *data) +#define MAX30102_COPY_DATA(i) \ + memcpy(&data->processed_buffer[(i)], \ + &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \ + MAX30102_REG_FIFO_DATA_BYTES) + +static int max30102_read_measurement(struct max30102_data *data, + unsigned int measurements) { int ret; u8 *buffer = (u8 *) &data->buffer; ret = i2c_smbus_read_i2c_block_data(data->client, MAX30102_REG_FIFO_DATA, - MAX30102_REG_FIFO_DATA_ENTRY_LEN, + measurements * + MAX30102_REG_FIFO_DATA_BYTES, buffer); - memcpy(&data->processed_buffer[0], &buffer[0], 3); - memcpy(&data->processed_buffer[1], &buffer[3], 3); + switch (measurements) { + case 3: + MAX30102_COPY_DATA(2); + case 2: /* fall-through */ + MAX30102_COPY_DATA(1); + case 1: /* fall-through */ + MAX30102_COPY_DATA(0); + break; + default: + return -EINVAL; + } - return (ret == MAX30102_REG_FIFO_DATA_ENTRY_LEN) ? 0 : -EINVAL; + return (ret == measurements * MAX30102_REG_FIFO_DATA_BYTES) ? + 0 : -EINVAL; } static irqreturn_t max30102_interrupt_handler(int irq, void *private) { struct iio_dev *indio_dev = private; struct max30102_data *data = iio_priv(indio_dev); + unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask, + indio_dev->masklength); int ret, cnt = 0; mutex_lock(&data->lock); while (cnt || (cnt = max30102_fifo_count(data)) > 0) { - ret = max30102_read_measurement(data); + ret = max30102_read_measurement(data, measurements); if (ret) break; @@ -251,6 +352,29 @@ static int max30102_led_init(struct max30102_data *data) if (ret) return ret; + if (data->chip_id == max30105) { + ret = of_property_read_u32(np, + "maxim,green-led-current-microamp", &val); + if (ret) { + dev_info(dev, "no green-led-current-microamp set\n"); + + /* Default to 7 mA green LED */ + val = 7000; + } + + ret = max30102_get_current_idx(val, ®); + if (ret) { + dev_err(dev, "invalid green LED current setting %d\n", + val); + return ret; + } + + ret = regmap_write(data->regmap, MAX30105_REG_GREEN_LED_CONFIG, + reg); + if (ret) + return ret; + } + ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val); if (ret) { dev_info(dev, "no ir-led-current-microamp set\n"); @@ -261,7 +385,7 @@ static int max30102_led_init(struct max30102_data *data) ret = max30102_get_current_idx(val, ®); if (ret) { - dev_err(dev, "invalid IR LED current setting %d", val); + dev_err(dev, "invalid IR LED current setting %d\n", val); return ret; } @@ -277,7 +401,7 @@ static int max30102_chip_init(struct max30102_data *data) if (ret) return ret; - /* enable 18-bit HR + SPO2 readings at 400Hz */ + /* configure 18-bit HR + SpO2 readings at 400Hz */ ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG, (MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS << MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) | @@ -287,14 +411,6 @@ static int max30102_chip_init(struct max30102_data *data) if (ret) return ret; - /* enable SPO2 mode */ - ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG, - MAX30102_REG_MODE_CONFIG_MODE_MASK, - MAX30102_REG_MODE_CONFIG_MODE_HR_EN | - MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN); - if (ret) - return ret; - /* average 4 samples + generate FIFO interrupt */ ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG, (MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES @@ -329,20 +445,31 @@ static int max30102_read_temp(struct max30102_data *data, int *val) return 0; } -static int max30102_get_temp(struct max30102_data *data, int *val) +static int max30102_get_temp(struct max30102_data *data, int *val, bool en) { int ret; + if (en) { + ret = max30102_set_power(data, true); + if (ret) + return ret; + } + /* start acquisition */ ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG, MAX30102_REG_TEMP_CONFIG_TEMP_EN, MAX30102_REG_TEMP_CONFIG_TEMP_EN); if (ret) - return ret; + goto out; msleep(35); + ret = max30102_read_temp(data, val); - return max30102_read_temp(data, val); +out: + if (en) + max30102_set_power(data, false); + + return ret; } static int max30102_read_raw(struct iio_dev *indio_dev, @@ -355,20 +482,19 @@ static int max30102_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: /* - * Temperature reading can only be acquired while engine - * is running + * Temperature reading can only be acquired when not in + * shutdown; leave shutdown briefly when buffer not running */ mutex_lock(&indio_dev->mlock); - if (!iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else { - ret = max30102_get_temp(data, val); - if (!ret) - ret = IIO_VAL_INT; - } - + ret = max30102_get_temp(data, val, true); + else + ret = max30102_get_temp(data, val, false); mutex_unlock(&indio_dev->mlock); + if (ret) + return ret; + + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: *val = 1000; /* 62.5 */ @@ -391,6 +517,7 @@ static int max30102_probe(struct i2c_client *client, struct iio_buffer *buffer; struct iio_dev *indio_dev; int ret; + unsigned int reg; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -403,10 +530,7 @@ static int max30102_probe(struct i2c_client *client, iio_device_attach_buffer(indio_dev, buffer); indio_dev->name = MAX30102_DRV_NAME; - indio_dev->channels = max30102_channels; indio_dev->info = &max30102_info; - indio_dev->num_channels = ARRAY_SIZE(max30102_channels); - indio_dev->available_scan_masks = max30102_scan_masks; indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); indio_dev->setup_ops = &max30102_buffer_setup_ops; indio_dev->dev.parent = &client->dev; @@ -414,16 +538,50 @@ static int max30102_probe(struct i2c_client *client, data = iio_priv(indio_dev); data->indio_dev = indio_dev; data->client = client; + data->chip_id = id->driver_data; mutex_init(&data->lock); i2c_set_clientdata(client, indio_dev); + switch (data->chip_id) { + case max30105: + indio_dev->channels = max30105_channels; + indio_dev->num_channels = ARRAY_SIZE(max30105_channels); + indio_dev->available_scan_masks = max30105_scan_masks; + break; + case max30102: + indio_dev->channels = max30102_channels; + indio_dev->num_channels = ARRAY_SIZE(max30102_channels); + indio_dev->available_scan_masks = max30102_scan_masks; + break; + default: + return -ENODEV; + } + data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config); if (IS_ERR(data->regmap)) { - dev_err(&client->dev, "regmap initialization failed.\n"); + dev_err(&client->dev, "regmap initialization failed\n"); return PTR_ERR(data->regmap); } - max30102_set_powermode(data, false); + + /* check part ID */ + ret = regmap_read(data->regmap, MAX30102_REG_PART_ID, ®); + if (ret) + return ret; + if (reg != MAX30102_PART_NUMBER) + return -ENODEV; + + /* show revision ID */ + ret = regmap_read(data->regmap, MAX30102_REG_REV_ID, ®); + if (ret) + return ret; + dev_dbg(&client->dev, "max3010x revision %02x\n", reg); + + /* clear mode setting, chip shutdown */ + ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE, + false); + if (ret) + return ret; ret = max30102_chip_init(data); if (ret) @@ -452,19 +610,21 @@ static int max30102_remove(struct i2c_client *client) struct max30102_data *data = iio_priv(indio_dev); iio_device_unregister(indio_dev); - max30102_set_powermode(data, false); + max30102_set_power(data, false); return 0; } static const struct i2c_device_id max30102_id[] = { - { "max30102", 0 }, + { "max30102", max30102 }, + { "max30105", max30105 }, {} }; MODULE_DEVICE_TABLE(i2c, max30102_id); static const struct of_device_id max30102_dt_ids[] = { { .compatible = "maxim,max30102" }, + { .compatible = "maxim,max30105" }, { } }; MODULE_DEVICE_TABLE(of, max30102_dt_ids); @@ -481,5 +641,5 @@ static struct i2c_driver max30102_driver = { module_i2c_driver(max30102_driver); MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>"); -MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor"); +MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index dd6fc6d21f9d..d78a10403bac 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -196,8 +196,7 @@ void inv_mpu_acpi_delete_mux_client(struct i2c_client *client) { struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev)); - if (st->mux_client) - i2c_unregister_device(st->mux_client); + i2c_unregister_device(st->mux_client); } #else diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2f0998ebeed2..19bdf3d2962a 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -588,6 +588,7 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type, return snprintf(buf, len, "%d", vals[0]); case IIO_VAL_INT_PLUS_MICRO_DB: scale_db = true; + /* fall through */ case IIO_VAL_INT_PLUS_MICRO: if (vals[1] < 0) return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]), diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 2356ed9285df..93fd421b10d7 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -334,6 +334,30 @@ config STK3310 Choosing M will build the driver as a module. If so, the module will be called stk3310. +config ST_UVIS25 + tristate "STMicroelectronics UVIS25 sensor driver" + depends on (I2C || SPI) + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select ST_UVIS25_I2C if (I2C) + select ST_UVIS25_SPI if (SPI_MASTER) + help + Say yes here to build support for STMicroelectronics UVIS25 + uv sensor + + To compile this driver as a module, choose M here: the module + will be called st_uvis25. + +config ST_UVIS25_I2C + tristate + depends on ST_UVIS25 + select REGMAP_I2C + +config ST_UVIS25_SPI + tristate + depends on ST_UVIS25 + select REGMAP_SPI + config TCS3414 tristate "TAOS TCS3414 digital color sensor" depends on I2C @@ -425,4 +449,14 @@ config VL6180 To compile this driver as a module, choose M here: the module will be called vl6180. +config ZOPT2201 + tristate "ZOPT2201 ALS and UV B sensor" + depends on I2C + help + Say Y here if you want to build a driver for the IDT + ZOPT2201 ambient light and UV B sensor. + + To compile this driver as a module, choose M here: the + module will be called zopt2201. + endmenu diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index c263469b7ce9..f714067a7816 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -33,6 +33,9 @@ obj-$(CONFIG_RPR0521) += rpr0521.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o obj-$(CONFIG_SI1145) += si1145.o obj-$(CONFIG_STK3310) += stk3310.o +obj-$(CONFIG_ST_UVIS25) += st_uvis25_core.o +obj-$(CONFIG_ST_UVIS25_I2C) += st_uvis25_i2c.o +obj-$(CONFIG_ST_UVIS25_SPI) += st_uvis25_spi.o obj-$(CONFIG_TCS3414) += tcs3414.o obj-$(CONFIG_TCS3472) += tcs3472.o obj-$(CONFIG_TSL2583) += tsl2583.o @@ -41,3 +44,4 @@ obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_VCNL4000) += vcnl4000.o obj-$(CONFIG_VEML6070) += veml6070.o obj-$(CONFIG_VL6180) += vl6180.o +obj-$(CONFIG_ZOPT2201) += zopt2201.o diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index b2a46b390d5c..acfad4aeb27a 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -181,7 +181,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); - struct cros_ec_device *ec_device; struct iio_dev *indio_dev; struct cros_ec_light_prox_state *state; struct iio_chan_spec *channel; @@ -191,7 +190,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) dev_warn(dev, "No CROS EC device found.\n"); return -EINVAL; } - ec_device = ec_dev->ec_dev; indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); if (!indio_dev) diff --git a/drivers/iio/light/st_uvis25.h b/drivers/iio/light/st_uvis25.h new file mode 100644 index 000000000000..5e970ab480cd --- /dev/null +++ b/drivers/iio/light/st_uvis25.h @@ -0,0 +1,37 @@ +/* + * STMicroelectronics uvis25 sensor driver + * + * Copyright 2017 STMicroelectronics Inc. + * + * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * + * Licensed under the GPL-2. + */ + +#ifndef ST_UVIS25_H +#define ST_UVIS25_H + +#define ST_UVIS25_DEV_NAME "uvis25" + +#include <linux/iio/iio.h> + +/** + * struct st_uvis25_hw - ST UVIS25 sensor instance + * @regmap: Register map of the device. + * @trig: The trigger in use by the driver. + * @enabled: Status of the sensor (false->off, true->on). + * @irq: Device interrupt line (I2C or SPI). + */ +struct st_uvis25_hw { + struct regmap *regmap; + + struct iio_trigger *trig; + bool enabled; + int irq; +}; + +extern const struct dev_pm_ops st_uvis25_pm_ops; + +int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap); + +#endif /* ST_UVIS25_H */ diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c new file mode 100644 index 000000000000..302635836e6b --- /dev/null +++ b/drivers/iio/light/st_uvis25_core.c @@ -0,0 +1,359 @@ +/* + * STMicroelectronics uvis25 sensor driver + * + * Copyright 2017 STMicroelectronics Inc. + * + * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * + * Licensed under the GPL-2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/iio/sysfs.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/irqreturn.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/buffer.h> +#include <linux/regmap.h> + +#include "st_uvis25.h" + +#define ST_UVIS25_REG_WHOAMI_ADDR 0x0f +#define ST_UVIS25_REG_WHOAMI_VAL 0xca +#define ST_UVIS25_REG_CTRL1_ADDR 0x20 +#define ST_UVIS25_REG_ODR_MASK BIT(0) +#define ST_UVIS25_REG_BDU_MASK BIT(1) +#define ST_UVIS25_REG_CTRL2_ADDR 0x21 +#define ST_UVIS25_REG_BOOT_MASK BIT(7) +#define ST_UVIS25_REG_CTRL3_ADDR 0x22 +#define ST_UVIS25_REG_HL_MASK BIT(7) +#define ST_UVIS25_REG_STATUS_ADDR 0x27 +#define ST_UVIS25_REG_UV_DA_MASK BIT(0) +#define ST_UVIS25_REG_OUT_ADDR 0x28 + +static const struct iio_chan_spec st_uvis25_channels[] = { + { + .type = IIO_UVINDEX, + .address = ST_UVIS25_REG_OUT_ADDR, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 8, + .storagebits = 8, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static int st_uvis25_check_whoami(struct st_uvis25_hw *hw) +{ + int err, data; + + err = regmap_read(hw->regmap, ST_UVIS25_REG_WHOAMI_ADDR, &data); + if (err < 0) { + dev_err(regmap_get_device(hw->regmap), + "failed to read whoami register\n"); + return err; + } + + if (data != ST_UVIS25_REG_WHOAMI_VAL) { + dev_err(regmap_get_device(hw->regmap), + "wrong whoami {%02x vs %02x}\n", + data, ST_UVIS25_REG_WHOAMI_VAL); + return -ENODEV; + } + + return 0; +} + +static int st_uvis25_set_enable(struct st_uvis25_hw *hw, bool enable) +{ + int err; + + err = regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR, + ST_UVIS25_REG_ODR_MASK, enable); + if (err < 0) + return err; + + hw->enabled = enable; + + return 0; +} + +static int st_uvis25_read_oneshot(struct st_uvis25_hw *hw, u8 addr, int *val) +{ + int err; + + err = st_uvis25_set_enable(hw, true); + if (err < 0) + return err; + + msleep(1500); + + /* + * in order to avoid possible race conditions with interrupt + * generation, disable the sensor first and then poll output + * register. That sequence guarantees the interrupt will be reset + * when irq line is unmasked + */ + err = st_uvis25_set_enable(hw, false); + if (err < 0) + return err; + + err = regmap_read(hw->regmap, addr, val); + + return err < 0 ? err : IIO_VAL_INT; +} + +static int st_uvis25_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *ch, + int *val, int *val2, long mask) +{ + int ret; + + ret = iio_device_claim_direct_mode(iio_dev); + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: { + struct st_uvis25_hw *hw = iio_priv(iio_dev); + + /* + * mask irq line during oneshot read since the sensor + * does not export the capability to disable data-ready line + * in the register map and it is enabled by default. + * If the line is unmasked during read_raw() it will be set + * active and never reset since the trigger is disabled + */ + if (hw->irq > 0) + disable_irq(hw->irq); + ret = st_uvis25_read_oneshot(hw, ch->address, val); + if (hw->irq > 0) + enable_irq(hw->irq); + break; + } + default: + ret = -EINVAL; + break; + } + + iio_device_release_direct_mode(iio_dev); + + return ret; +} + +static irqreturn_t st_uvis25_trigger_handler_thread(int irq, void *private) +{ + struct st_uvis25_hw *hw = private; + int err, status; + + err = regmap_read(hw->regmap, ST_UVIS25_REG_STATUS_ADDR, &status); + if (err < 0) + return IRQ_HANDLED; + + if (!(status & ST_UVIS25_REG_UV_DA_MASK)) + return IRQ_NONE; + + iio_trigger_poll_chained(hw->trig); + + return IRQ_HANDLED; +} + +static int st_uvis25_allocate_trigger(struct iio_dev *iio_dev) +{ + struct st_uvis25_hw *hw = iio_priv(iio_dev); + struct device *dev = regmap_get_device(hw->regmap); + bool irq_active_low = false; + unsigned long irq_type; + int err; + + irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); + + switch (irq_type) { + case IRQF_TRIGGER_HIGH: + case IRQF_TRIGGER_RISING: + break; + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_FALLING: + irq_active_low = true; + break; + default: + dev_info(dev, "mode %lx unsupported\n", irq_type); + return -EINVAL; + } + + err = regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL3_ADDR, + ST_UVIS25_REG_HL_MASK, irq_active_low); + if (err < 0) + return err; + + err = devm_request_threaded_irq(dev, hw->irq, NULL, + st_uvis25_trigger_handler_thread, + irq_type | IRQF_ONESHOT, + iio_dev->name, hw); + if (err) { + dev_err(dev, "failed to request trigger irq %d\n", + hw->irq); + return err; + } + + hw->trig = devm_iio_trigger_alloc(dev, "%s-trigger", + iio_dev->name); + if (!hw->trig) + return -ENOMEM; + + iio_trigger_set_drvdata(hw->trig, iio_dev); + hw->trig->dev.parent = dev; + + return devm_iio_trigger_register(dev, hw->trig); +} + +static int st_uvis25_buffer_preenable(struct iio_dev *iio_dev) +{ + return st_uvis25_set_enable(iio_priv(iio_dev), true); +} + +static int st_uvis25_buffer_postdisable(struct iio_dev *iio_dev) +{ + return st_uvis25_set_enable(iio_priv(iio_dev), false); +} + +static const struct iio_buffer_setup_ops st_uvis25_buffer_ops = { + .preenable = st_uvis25_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = st_uvis25_buffer_postdisable, +}; + +static irqreturn_t st_uvis25_buffer_handler_thread(int irq, void *p) +{ + u8 buffer[ALIGN(sizeof(u8), sizeof(s64)) + sizeof(s64)]; + struct iio_poll_func *pf = p; + struct iio_dev *iio_dev = pf->indio_dev; + struct st_uvis25_hw *hw = iio_priv(iio_dev); + int err; + + err = regmap_read(hw->regmap, ST_UVIS25_REG_OUT_ADDR, (int *)buffer); + if (err < 0) + goto out; + + iio_push_to_buffers_with_timestamp(iio_dev, buffer, + iio_get_time_ns(iio_dev)); + +out: + iio_trigger_notify_done(hw->trig); + + return IRQ_HANDLED; +} + +static int st_uvis25_allocate_buffer(struct iio_dev *iio_dev) +{ + struct st_uvis25_hw *hw = iio_priv(iio_dev); + + return devm_iio_triggered_buffer_setup(regmap_get_device(hw->regmap), + iio_dev, NULL, + st_uvis25_buffer_handler_thread, + &st_uvis25_buffer_ops); +} + +static const struct iio_info st_uvis25_info = { + .read_raw = st_uvis25_read_raw, +}; + +static int st_uvis25_init_sensor(struct st_uvis25_hw *hw) +{ + int err; + + err = regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL2_ADDR, + ST_UVIS25_REG_BOOT_MASK, 1); + if (err < 0) + return err; + + msleep(2000); + + return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR, + ST_UVIS25_REG_BDU_MASK, 1); +} + +int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap) +{ + struct st_uvis25_hw *hw; + struct iio_dev *iio_dev; + int err; + + iio_dev = devm_iio_device_alloc(dev, sizeof(*hw)); + if (!iio_dev) + return -ENOMEM; + + dev_set_drvdata(dev, (void *)iio_dev); + + hw = iio_priv(iio_dev); + hw->irq = irq; + hw->regmap = regmap; + + err = st_uvis25_check_whoami(hw); + if (err < 0) + return err; + + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->dev.parent = dev; + iio_dev->channels = st_uvis25_channels; + iio_dev->num_channels = ARRAY_SIZE(st_uvis25_channels); + iio_dev->name = ST_UVIS25_DEV_NAME; + iio_dev->info = &st_uvis25_info; + + err = st_uvis25_init_sensor(hw); + if (err < 0) + return err; + + if (hw->irq > 0) { + err = st_uvis25_allocate_buffer(iio_dev); + if (err < 0) + return err; + + err = st_uvis25_allocate_trigger(iio_dev); + if (err) + return err; + } + + return devm_iio_device_register(dev, iio_dev); +} +EXPORT_SYMBOL(st_uvis25_probe); + +static int __maybe_unused st_uvis25_suspend(struct device *dev) +{ + struct iio_dev *iio_dev = dev_get_drvdata(dev); + struct st_uvis25_hw *hw = iio_priv(iio_dev); + + return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR, + ST_UVIS25_REG_ODR_MASK, 0); +} + +static int __maybe_unused st_uvis25_resume(struct device *dev) +{ + struct iio_dev *iio_dev = dev_get_drvdata(dev); + struct st_uvis25_hw *hw = iio_priv(iio_dev); + + if (hw->enabled) + return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR, + ST_UVIS25_REG_ODR_MASK, 1); + + return 0; +} + +const struct dev_pm_ops st_uvis25_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(st_uvis25_suspend, st_uvis25_resume) +}; +EXPORT_SYMBOL(st_uvis25_pm_ops); + +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); +MODULE_DESCRIPTION("STMicroelectronics uvis25 sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c new file mode 100644 index 000000000000..c939c0b0ff10 --- /dev/null +++ b/drivers/iio/light/st_uvis25_i2c.c @@ -0,0 +1,69 @@ +/* + * STMicroelectronics uvis25 i2c driver + * + * Copyright 2017 STMicroelectronics Inc. + * + * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * + * Licensed under the GPL-2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/acpi.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/regmap.h> + +#include "st_uvis25.h" + +#define UVIS25_I2C_AUTO_INCREMENT BIT(7) + +const struct regmap_config st_uvis25_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .write_flag_mask = UVIS25_I2C_AUTO_INCREMENT, + .read_flag_mask = UVIS25_I2C_AUTO_INCREMENT, +}; + +static int st_uvis25_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &st_uvis25_i2c_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to register i2c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return st_uvis25_probe(&client->dev, client->irq, regmap); +} + +static const struct of_device_id st_uvis25_i2c_of_match[] = { + { .compatible = "st,uvis25", }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_uvis25_i2c_of_match); + +static const struct i2c_device_id st_uvis25_i2c_id_table[] = { + { ST_UVIS25_DEV_NAME }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, st_uvis25_i2c_id_table); + +static struct i2c_driver st_uvis25_driver = { + .driver = { + .name = "st_uvis25_i2c", + .pm = &st_uvis25_pm_ops, + .of_match_table = of_match_ptr(st_uvis25_i2c_of_match), + }, + .probe = st_uvis25_i2c_probe, + .id_table = st_uvis25_i2c_id_table, +}; +module_i2c_driver(st_uvis25_driver); + +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); +MODULE_DESCRIPTION("STMicroelectronics uvis25 i2c driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/light/st_uvis25_spi.c b/drivers/iio/light/st_uvis25_spi.c new file mode 100644 index 000000000000..e697e14e7952 --- /dev/null +++ b/drivers/iio/light/st_uvis25_spi.c @@ -0,0 +1,68 @@ +/* + * STMicroelectronics uvis25 spi driver + * + * Copyright 2017 STMicroelectronics Inc. + * + * Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * + * Licensed under the GPL-2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/slab.h> +#include <linux/regmap.h> + +#include "st_uvis25.h" + +#define UVIS25_SENSORS_SPI_READ BIT(7) +#define UVIS25_SPI_AUTO_INCREMENT BIT(6) + +const struct regmap_config st_uvis25_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = UVIS25_SENSORS_SPI_READ | UVIS25_SPI_AUTO_INCREMENT, + .write_flag_mask = UVIS25_SPI_AUTO_INCREMENT, +}; + +static int st_uvis25_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &st_uvis25_spi_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return st_uvis25_probe(&spi->dev, spi->irq, regmap); +} + +static const struct of_device_id st_uvis25_spi_of_match[] = { + { .compatible = "st,uvis25", }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_uvis25_spi_of_match); + +static const struct spi_device_id st_uvis25_spi_id_table[] = { + { ST_UVIS25_DEV_NAME }, + {}, +}; +MODULE_DEVICE_TABLE(spi, st_uvis25_spi_id_table); + +static struct spi_driver st_uvis25_driver = { + .driver = { + .name = "st_uvis25_spi", + .pm = &st_uvis25_pm_ops, + .of_match_table = of_match_ptr(st_uvis25_spi_of_match), + }, + .probe = st_uvis25_spi_probe, + .id_table = st_uvis25_spi_id_table, +}; +module_spi_driver(st_uvis25_driver); + +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); +MODULE_DESCRIPTION("STMicroelectronics uvis25 spi driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c new file mode 100644 index 000000000000..041ac9effdb0 --- /dev/null +++ b/drivers/iio/light/zopt2201.c @@ -0,0 +1,568 @@ +/* + * zopt2201.c - Support for IDT ZOPT2201 ambient light and UV B sensor + * + * Copyright 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Datasheet: https://www.idt.com/document/dst/zopt2201-datasheet + * 7-bit I2C slave addresses 0x53 (default) or 0x52 (programmed) + * + * TODO: interrupt support, ALS/UVB raw mode + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/mutex.h> +#include <linux/err.h> +#include <linux/delay.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +#define ZOPT2201_DRV_NAME "zopt2201" + +/* Registers */ +#define ZOPT2201_MAIN_CTRL 0x00 +#define ZOPT2201_LS_MEAS_RATE 0x04 +#define ZOPT2201_LS_GAIN 0x05 +#define ZOPT2201_PART_ID 0x06 +#define ZOPT2201_MAIN_STATUS 0x07 +#define ZOPT2201_ALS_DATA 0x0d /* LSB first, 13 to 20 bits */ +#define ZOPT2201_UVB_DATA 0x10 /* LSB first, 13 to 20 bits */ +#define ZOPT2201_UV_COMP_DATA 0x13 /* LSB first, 13 to 20 bits */ +#define ZOPT2201_COMP_DATA 0x16 /* LSB first, 13 to 20 bits */ +#define ZOPT2201_INT_CFG 0x19 +#define ZOPT2201_INT_PST 0x1a + +#define ZOPT2201_MAIN_CTRL_LS_MODE BIT(3) /* 0 .. ALS, 1 .. UV B */ +#define ZOPT2201_MAIN_CTRL_LS_EN BIT(1) + +/* Values for ZOPT2201_LS_MEAS_RATE resolution / bit width */ +#define ZOPT2201_MEAS_RES_20BIT 0 /* takes 400 ms */ +#define ZOPT2201_MEAS_RES_19BIT 1 /* takes 200 ms */ +#define ZOPT2201_MEAS_RES_18BIT 2 /* takes 100 ms, default */ +#define ZOPT2201_MEAS_RES_17BIT 3 /* takes 50 ms */ +#define ZOPT2201_MEAS_RES_16BIT 4 /* takes 25 ms */ +#define ZOPT2201_MEAS_RES_13BIT 5 /* takes 3.125 ms */ +#define ZOPT2201_MEAS_RES_SHIFT 4 + +/* Values for ZOPT2201_LS_MEAS_RATE measurement rate */ +#define ZOPT2201_MEAS_FREQ_25MS 0 +#define ZOPT2201_MEAS_FREQ_50MS 1 +#define ZOPT2201_MEAS_FREQ_100MS 2 /* default */ +#define ZOPT2201_MEAS_FREQ_200MS 3 +#define ZOPT2201_MEAS_FREQ_500MS 4 +#define ZOPT2201_MEAS_FREQ_1000MS 5 +#define ZOPT2201_MEAS_FREQ_2000MS 6 + +/* Values for ZOPT2201_LS_GAIN */ +#define ZOPT2201_LS_GAIN_1 0 +#define ZOPT2201_LS_GAIN_3 1 +#define ZOPT2201_LS_GAIN_6 2 +#define ZOPT2201_LS_GAIN_9 3 +#define ZOPT2201_LS_GAIN_18 4 + +/* Values for ZOPT2201_MAIN_STATUS */ +#define ZOPT2201_MAIN_STATUS_POWERON BIT(5) +#define ZOPT2201_MAIN_STATUS_INT BIT(4) +#define ZOPT2201_MAIN_STATUS_DRDY BIT(3) + +#define ZOPT2201_PART_NUMBER 0xb2 + +struct zopt2201_data { + struct i2c_client *client; + struct mutex lock; + u8 gain; + u8 res; + u8 rate; +}; + +static const struct { + unsigned int gain; /* gain factor */ + unsigned int scale; /* micro lux per count */ +} zopt2201_gain_als[] = { + { 1, 19200000 }, + { 3, 6400000 }, + { 6, 3200000 }, + { 9, 2133333 }, + { 18, 1066666 }, +}; + +static const struct { + unsigned int gain; /* gain factor */ + unsigned int scale; /* micro W/m2 per count */ +} zopt2201_gain_uvb[] = { + { 1, 460800 }, + { 3, 153600 }, + { 6, 76800 }, + { 9, 51200 }, + { 18, 25600 }, +}; + +static const struct { + unsigned int bits; /* sensor resolution in bits */ + unsigned long us; /* measurement time in micro seconds */ +} zopt2201_resolution[] = { + { 20, 400000 }, + { 19, 200000 }, + { 18, 100000 }, + { 17, 50000 }, + { 16, 25000 }, + { 13, 3125 }, +}; + +static const struct { + unsigned int scale, uscale; /* scale factor as integer + micro */ + u8 gain; /* gain register value */ + u8 res; /* resolution register value */ +} zopt2201_scale_als[] = { + { 19, 200000, 0, 5 }, + { 6, 400000, 1, 5 }, + { 3, 200000, 2, 5 }, + { 2, 400000, 0, 4 }, + { 2, 133333, 3, 5 }, + { 1, 200000, 0, 3 }, + { 1, 66666, 4, 5 }, + { 0, 800000, 1, 4 }, + { 0, 600000, 0, 2 }, + { 0, 400000, 2, 4 }, + { 0, 300000, 0, 1 }, + { 0, 266666, 3, 4 }, + { 0, 200000, 2, 3 }, + { 0, 150000, 0, 0 }, + { 0, 133333, 4, 4 }, + { 0, 100000, 2, 2 }, + { 0, 66666, 4, 3 }, + { 0, 50000, 2, 1 }, + { 0, 33333, 4, 2 }, + { 0, 25000, 2, 0 }, + { 0, 16666, 4, 1 }, + { 0, 8333, 4, 0 }, +}; + +static const struct { + unsigned int scale, uscale; /* scale factor as integer + micro */ + u8 gain; /* gain register value */ + u8 res; /* resolution register value */ +} zopt2201_scale_uvb[] = { + { 0, 460800, 0, 5 }, + { 0, 153600, 1, 5 }, + { 0, 76800, 2, 5 }, + { 0, 57600, 0, 4 }, + { 0, 51200, 3, 5 }, + { 0, 28800, 0, 3 }, + { 0, 25600, 4, 5 }, + { 0, 19200, 1, 4 }, + { 0, 14400, 0, 2 }, + { 0, 9600, 2, 4 }, + { 0, 7200, 0, 1 }, + { 0, 6400, 3, 4 }, + { 0, 4800, 2, 3 }, + { 0, 3600, 0, 0 }, + { 0, 3200, 4, 4 }, + { 0, 2400, 2, 2 }, + { 0, 1600, 4, 3 }, + { 0, 1200, 2, 1 }, + { 0, 800, 4, 2 }, + { 0, 600, 2, 0 }, + { 0, 400, 4, 1 }, + { 0, 200, 4, 0 }, +}; + +static int zopt2201_enable_mode(struct zopt2201_data *data, bool uvb_mode) +{ + u8 out = ZOPT2201_MAIN_CTRL_LS_EN; + + if (uvb_mode) + out |= ZOPT2201_MAIN_CTRL_LS_MODE; + + return i2c_smbus_write_byte_data(data->client, ZOPT2201_MAIN_CTRL, out); +} + +static int zopt2201_read(struct zopt2201_data *data, u8 reg) +{ + struct i2c_client *client = data->client; + int tries = 10; + u8 buf[3]; + int ret; + + mutex_lock(&data->lock); + ret = zopt2201_enable_mode(data, reg == ZOPT2201_UVB_DATA); + if (ret < 0) + goto fail; + + while (tries--) { + unsigned long t = zopt2201_resolution[data->res].us; + + if (t <= 20000) + usleep_range(t, t + 1000); + else + msleep(t / 1000); + ret = i2c_smbus_read_byte_data(client, ZOPT2201_MAIN_STATUS); + if (ret < 0) + goto fail; + if (ret & ZOPT2201_MAIN_STATUS_DRDY) + break; + } + + if (tries < 0) { + ret = -ETIMEDOUT; + goto fail; + } + + ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf); + if (ret < 0) + goto fail; + + ret = i2c_smbus_write_byte_data(client, ZOPT2201_MAIN_CTRL, 0x00); + if (ret < 0) + goto fail; + mutex_unlock(&data->lock); + + return (buf[2] << 16) | (buf[1] << 8) | buf[0]; + +fail: + mutex_unlock(&data->lock); + return ret; +} + +static const struct iio_chan_spec zopt2201_channels[] = { + { + .type = IIO_LIGHT, + .address = ZOPT2201_ALS_DATA, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_UV, + .address = ZOPT2201_UVB_DATA, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_UVINDEX, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, +}; + +static int zopt2201_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct zopt2201_data *data = iio_priv(indio_dev); + u64 tmp; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = zopt2201_read(data, chan->address); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_PROCESSED: + ret = zopt2201_read(data, ZOPT2201_UVB_DATA); + if (ret < 0) + return ret; + *val = ret * 18 * + (1 << (20 - zopt2201_resolution[data->res].bits)) / + zopt2201_gain_uvb[data->gain].gain; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->address) { + case ZOPT2201_ALS_DATA: + *val = zopt2201_gain_als[data->gain].scale; + break; + case ZOPT2201_UVB_DATA: + *val = zopt2201_gain_uvb[data->gain].scale; + break; + default: + return -EINVAL; + } + + *val2 = 1000000; + *val2 *= (1 << (zopt2201_resolution[data->res].bits - 13)); + tmp = div_s64(*val * 1000000ULL, *val2); + *val = div_s64_rem(tmp, 1000000, val2); + + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_INT_TIME: + *val = 0; + *val2 = zopt2201_resolution[data->res].us; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int zopt2201_set_resolution(struct zopt2201_data *data, u8 res) +{ + int ret; + + ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_MEAS_RATE, + (res << ZOPT2201_MEAS_RES_SHIFT) | + data->rate); + if (ret < 0) + return ret; + + data->res = res; + + return 0; +} + +static int zopt2201_write_resolution(struct zopt2201_data *data, + int val, int val2) +{ + int i, ret; + + if (val != 0) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++) + if (val2 == zopt2201_resolution[i].us) { + mutex_lock(&data->lock); + ret = zopt2201_set_resolution(data, i); + mutex_unlock(&data->lock); + return ret; + } + + return -EINVAL; +} + +static int zopt2201_set_gain(struct zopt2201_data *data, u8 gain) +{ + int ret; + + ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_GAIN, gain); + if (ret < 0) + return ret; + + data->gain = gain; + + return 0; +} + +static int zopt2201_write_scale_als_by_idx(struct zopt2201_data *data, int idx) +{ + int ret; + + mutex_lock(&data->lock); + ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res); + if (ret < 0) + goto unlock; + + ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain); + +unlock: + mutex_unlock(&data->lock); + return ret; +} + +static int zopt2201_write_scale_als(struct zopt2201_data *data, + int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++) + if (val == zopt2201_scale_als[i].scale && + val2 == zopt2201_scale_als[i].uscale) { + return zopt2201_write_scale_als_by_idx(data, i); + } + + return -EINVAL; +} + +static int zopt2201_write_scale_uvb_by_idx(struct zopt2201_data *data, int idx) +{ + int ret; + + mutex_lock(&data->lock); + ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res); + if (ret < 0) + goto unlock; + + ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain); + +unlock: + mutex_unlock(&data->lock); + return ret; +} + +static int zopt2201_write_scale_uvb(struct zopt2201_data *data, + int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++) + if (val == zopt2201_scale_uvb[i].scale && + val2 == zopt2201_scale_uvb[i].uscale) + return zopt2201_write_scale_uvb_by_idx(data, i); + + return -EINVAL; +} + +static int zopt2201_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct zopt2201_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + return zopt2201_write_resolution(data, val, val2); + case IIO_CHAN_INFO_SCALE: + switch (chan->address) { + case ZOPT2201_ALS_DATA: + return zopt2201_write_scale_als(data, val, val2); + case ZOPT2201_UVB_DATA: + return zopt2201_write_scale_uvb(data, val, val2); + default: + return -EINVAL; + } + } + + return -EINVAL; +} + +static ssize_t zopt2201_show_int_time_available(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + size_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06lu ", + zopt2201_resolution[i].us); + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEV_ATTR_INT_TIME_AVAIL(zopt2201_show_int_time_available); + +static ssize_t zopt2201_show_als_scale_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ", + zopt2201_scale_als[i].scale, + zopt2201_scale_als[i].uscale); + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t zopt2201_show_uvb_scale_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ", + zopt2201_scale_uvb[i].scale, + zopt2201_scale_uvb[i].uscale); + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(in_illuminance_scale_available, 0444, + zopt2201_show_als_scale_avail, NULL, 0); +static IIO_DEVICE_ATTR(in_intensity_uv_scale_available, 0444, + zopt2201_show_uvb_scale_avail, NULL, 0); + +static struct attribute *zopt2201_attributes[] = { + &iio_dev_attr_integration_time_available.dev_attr.attr, + &iio_dev_attr_in_illuminance_scale_available.dev_attr.attr, + &iio_dev_attr_in_intensity_uv_scale_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group zopt2201_attribute_group = { + .attrs = zopt2201_attributes, +}; + +static const struct iio_info zopt2201_info = { + .read_raw = zopt2201_read_raw, + .write_raw = zopt2201_write_raw, + .attrs = &zopt2201_attribute_group, +}; + +static int zopt2201_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct zopt2201_data *data; + struct iio_dev *indio_dev; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) + return -EOPNOTSUPP; + + ret = i2c_smbus_read_byte_data(client, ZOPT2201_PART_ID); + if (ret < 0) + return ret; + if (ret != ZOPT2201_PART_NUMBER) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &zopt2201_info; + indio_dev->channels = zopt2201_channels; + indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels); + indio_dev->name = ZOPT2201_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + data->rate = ZOPT2201_MEAS_FREQ_100MS; + ret = zopt2201_set_resolution(data, ZOPT2201_MEAS_RES_18BIT); + if (ret < 0) + return ret; + + ret = zopt2201_set_gain(data, ZOPT2201_LS_GAIN_3); + if (ret < 0) + return ret; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id zopt2201_id[] = { + { "zopt2201", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, zopt2201_id); + +static struct i2c_driver zopt2201_driver = { + .driver = { + .name = ZOPT2201_DRV_NAME, + }, + .probe = zopt2201_probe, + .id_table = zopt2201_id, +}; + +module_i2c_driver(zopt2201_driver); + +MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>"); +MODULE_DESCRIPTION("IDT ZOPT2201 ambient light and UV B sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index c09329069d0a..42a827a66512 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -788,6 +788,7 @@ static const struct acpi_device_id ak_acpi_match[] = { {"AK8975", AK8975}, {"AK8963", AK8963}, {"INVN6500", AK8963}, + {"AK009911", AK09911}, {"AK09911", AK09911}, {"AK09912", AK09912}, { }, diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index df23dbcc030a..b8a2c2c8cac5 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -1031,6 +1031,7 @@ static const struct dev_pm_ops sx9500_pm_ops = { static const struct acpi_device_id sx9500_acpi_match[] = { {"SSX9500", 0}, + {"SASX9500", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 554683912cff..e95ab683331e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -26,6 +26,10 @@ if STAGING source "drivers/staging/irda/net/Kconfig" +source "drivers/staging/ipx/Kconfig" + +source "drivers/staging/ncpfs/Kconfig" + source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6e536020029a..af8cd6a3a1f6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -3,6 +3,8 @@ obj-y += media/ obj-y += typec/ +obj-$(CONFIG_IPX) += ipx/ +obj-$(CONFIG_NCP_FS) += ncpfs/ obj-$(CONFIG_IRDA) += irda/net/ obj-$(CONFIG_IRDA) += irda/drivers/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 0f695df14c9d..4e8947923904 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* mm/ashmem.c * * Anonymous Shared Memory Subsystem, ashmem @@ -5,15 +6,6 @@ * Copyright (C) 2008 Google, Inc. * * Robert Love <rlove@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. */ #define pr_fmt(fmt) "ashmem: " fmt diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h index 5abcfd7aa706..60d7208f110a 100644 --- a/drivers/staging/android/ashmem.h +++ b/drivers/staging/android/ashmem.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR Apache-2.0) /* * include/linux/ashmem.h * diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index c78989351f9c..6ed2cc15c8c0 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -1,16 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <linux/kernel.h> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a7d9b0e98572..cada3725e2e4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,42 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * * drivers/staging/android/ion/ion.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ +#include <linux/anon_inodes.h> +#include <linux/debugfs.h> #include <linux/device.h> +#include <linux/dma-buf.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/file.h> #include <linux/freezer.h> #include <linux/fs.h> -#include <linux/anon_inodes.h> +#include <linux/idr.h> #include <linux/kthread.h> #include <linux/list.h> #include <linux/memblock.h> #include <linux/miscdevice.h> -#include <linux/export.h> #include <linux/mm.h> #include <linux/mm_types.h> #include <linux/rbtree.h> -#include <linux/slab.h> +#include <linux/sched/task.h> #include <linux/seq_file.h> +#include <linux/slab.h> #include <linux/uaccess.h> #include <linux/vmalloc.h> -#include <linux/debugfs.h> -#include <linux/dma-buf.h> -#include <linux/idr.h> -#include <linux/sched/task.h> #include "ion.h" @@ -567,9 +557,9 @@ void ion_device_add_heap(struct ion_heap *heap) char debug_name[64]; snprintf(debug_name, 64, "%s_shrink", heap->name); - debug_file = debugfs_create_file( - debug_name, 0644, dev->debug_root, heap, - &debug_shrink_fops); + debug_file = debugfs_create_file(debug_name, + 0644, dev->debug_root, heap, + &debug_shrink_fops); if (!debug_file) { char buf[256], *path; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index f5f9cd63f8e9..c24c6e230654 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion.h * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #ifndef _ION_H @@ -189,7 +180,8 @@ struct ion_heap { wait_queue_head_t waitqueue; struct task_struct *task; - int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); + int (*debug_show)(struct ion_heap *heap, struct seq_file *s, + void *unused); }; /** diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index fee7650d6fbb..e129237a0417 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_carveout_heap.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <linux/spinlock.h> #include <linux/dma-mapping.h> diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 102c09398317..159d72f5bc42 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_chunk_heap.c * * Copyright (C) 2012 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <linux/dma-mapping.h> #include <linux/err.h> diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index dd5545d9990a..50a9736ab455 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_cma_heap.c * * Copyright (C) Linaro 2012 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <linux/device.h> diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 91faa7f035b9..2af86a2d94fb 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_heap.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <linux/err.h> diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 817849df9de3..b3017f12835f 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_mem_pool.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <linux/debugfs.h> diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 4dc5d7a589c2..71c4228f8238 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_system_heap.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #include <asm/page.h> diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h index 13df42d200b7..5b531af6820e 100644 --- a/drivers/staging/android/uapi/ashmem.h +++ b/drivers/staging/android/uapi/ashmem.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR Apache-2.0) /* * drivers/staging/android/uapi/ashmem.h * diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 9e21451149d0..825d3e95ccd3 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/uapi/ion.h * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * */ #ifndef _UAPI_LINUX_ION_H diff --git a/drivers/staging/ccree/Documentation/devicetree/bindings/crypto/arm-cryptocell.txt b/drivers/staging/ccree/Documentation/devicetree/bindings/crypto/arm-cryptocell.txt deleted file mode 100644 index 2ea65175c032..000000000000 --- a/drivers/staging/ccree/Documentation/devicetree/bindings/crypto/arm-cryptocell.txt +++ /dev/null @@ -1,27 +0,0 @@ -Arm TrustZone CryptoCell cryptographic accelerators - -Required properties: -- compatible: must be "arm,cryptocell-712-ree". -- reg: shall contain base register location and length. - Typically length is 0x10000. -- interrupts: shall contain the interrupt for the device. - -Optional properties: -- interrupt-parent: can designate the interrupt controller the - device interrupt is connected to, if needed. -- clocks: may contain the clock handling the device, if needed. -- power-domains: may contain a reference to the PM domain, if applicable. - - -Examples: - -Zynq FPGA device ----------------- - - arm_cc7x: arm_cc7x@80000000 { - compatible = "arm,cryptocell-712-ree"; - interrupt-parent = <&intc>; - interrupts = < 0 30 4 >; - reg = < 0x80000000 0x10000 >; - }; - diff --git a/drivers/staging/ccree/TODO b/drivers/staging/ccree/TODO index c9f5754d062d..f44edcd56595 100644 --- a/drivers/staging/ccree/TODO +++ b/drivers/staging/ccree/TODO @@ -6,25 +6,6 @@ * * ************************************************************************* -ccree specific items -a.k.a stuff fixing for this driver to move out of staging -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +1. Migrate sysfs to debugfs. +2. Handle HW FIFO fullness more cleanly. -1. Move to using Crypto Engine to handle backlog queueing. -2. Remove synchronous algorithm support leftovers. -3. Separate platform specific code for FIPS and power management into separate platform modules. -4. Drop legacy kernel support code. -5. Move most (all?) #ifdef CONFIG into inline functions. -6. Remove all unused definitions. -7. Re-factor to accomediate newer/older HW revisions besides the 712. -8. Handle the many checkpatch errors. -9. Implement ahash import/export correctly. -10. Go through a proper review of DT bindings and sysfs ABI -11. Sort out FIPS mode: bake tests into testmgr, sort out behaviour on error, - figure if 3DES weak key check is needed - -Kernel infrastructure items -a.k.a stuff we either neither need to fix in the kernel or understand what we're doing wrong -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1. ahash import/export context has a PAGE_SIZE/8 size limit. We need more. -2. Crypto Engine seems to be built for HW with hardware queue depth of 1, we have 600++. diff --git a/drivers/staging/ccree/cc_hw_queue_defs.h b/drivers/staging/ccree/cc_hw_queue_defs.h index 2ae0f655e7a0..c5aaa79dcfc0 100644 --- a/drivers/staging/ccree/cc_hw_queue_defs.h +++ b/drivers/staging/ccree/cc_hw_queue_defs.h @@ -30,8 +30,6 @@ /* Define max. available slots in HW queue */ #define HW_QUEUE_SLOTS_MAX 15 -#define CC_REG_NAME(word, name) DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name - #define CC_REG_LOW(word, name) \ (DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SHIFT) diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index ba0954e4d2e5..5548c7b24fc9 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -51,7 +51,7 @@ /* Value of each ICV_CMP byte (of 8) in case of success */ #define ICV_VERIF_OK 0x01 -struct ssi_aead_handle { +struct cc_aead_handle { ssi_sram_addr_t sram_workspace_addr; struct list_head aead_list; }; @@ -68,7 +68,7 @@ struct cc_xcbc_s { dma_addr_t xcbc_keys_dma_addr; }; -struct ssi_aead_ctx { +struct cc_aead_ctx { struct ssi_drvdata *drvdata; u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */ u8 *enckey; @@ -90,9 +90,9 @@ static inline bool valid_assoclen(struct aead_request *req) return ((req->assoclen == 16) || (req->assoclen == 20)); } -static void ssi_aead_exit(struct crypto_aead *tfm) +static void cc_aead_exit(struct crypto_aead *tfm) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "Clearing context @%p for %s\n", crypto_aead_ctx(tfm), @@ -100,7 +100,8 @@ static void ssi_aead_exit(struct crypto_aead *tfm) /* Unmap enckey buffer */ if (ctx->enckey) { - dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, ctx->enckey_dma_addr); + dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, + ctx->enckey_dma_addr); dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n", &ctx->enckey_dma_addr); ctx->enckey_dma_addr = 0; @@ -143,10 +144,10 @@ static void ssi_aead_exit(struct crypto_aead *tfm) } } -static int ssi_aead_init(struct crypto_aead *tfm) +static int cc_aead_init(struct crypto_aead *tfm) { struct aead_alg *alg = crypto_aead_alg(tfm); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct ssi_crypto_alg *ssi_alg = container_of(alg, struct ssi_crypto_alg, aead_alg); struct device *dev = drvdata_to_dev(ssi_alg->drvdata); @@ -221,19 +222,19 @@ static int ssi_aead_init(struct crypto_aead *tfm) return 0; init_failed: - ssi_aead_exit(tfm); + cc_aead_exit(tfm); return -ENOMEM; } -static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void cc_aead_complete(struct device *dev, void *ssi_req) { struct aead_request *areq = (struct aead_request *)ssi_req; struct aead_req_ctx *areq_ctx = aead_request_ctx(areq); struct crypto_aead *tfm = crypto_aead_reqtfm(ssi_req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); int err = 0; - ssi_buffer_mgr_unmap_aead_request(dev, areq); + cc_unmap_aead_request(dev, areq); /* Restore ordinary iv pointer */ areq->iv = areq_ctx->backup_iv; @@ -246,36 +247,43 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c /* In case of payload authentication failure, MUST NOT * revealed the decrypted message --> zero its memory. */ - ssi_buffer_mgr_zero_sgl(areq->dst, areq_ctx->cryptlen); + cc_zero_sgl(areq->dst, areq_ctx->cryptlen); err = -EBADMSG; } } else { /*ENCRYPT*/ - if (unlikely(areq_ctx->is_icv_fragmented)) - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->mac_buf, areq_ctx->dst_sgl, - areq->cryptlen + areq_ctx->dst_offset, - (areq->cryptlen + areq_ctx->dst_offset + - ctx->authsize), - SSI_SG_FROM_BUF); - - /* If an IV was generated, copy it back to the user provided buffer. */ + if (areq_ctx->is_icv_fragmented) { + u32 skip = areq->cryptlen + areq_ctx->dst_offset; + + cc_copy_sg_portion(dev, areq_ctx->mac_buf, + areq_ctx->dst_sgl, skip, + (skip + ctx->authsize), + SSI_SG_FROM_BUF); + } + + /* If an IV was generated, copy it back to the user provided + * buffer. + */ if (areq_ctx->backup_giv) { if (ctx->cipher_mode == DRV_CIPHER_CTR) - memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_IV_SIZE); + memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + + CTR_RFC3686_NONCE_SIZE, + CTR_RFC3686_IV_SIZE); else if (ctx->cipher_mode == DRV_CIPHER_CCM) - memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE); + memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + + CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE); } } aead_request_complete(areq, err); } -static int xcbc_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) +static int xcbc_setkey(struct cc_hw_desc *desc, struct cc_aead_ctx *ctx) { /* Load the AES key */ hw_desc_init(&desc[0]); - /* We are using for the source/user key the same buffer as for the output keys, - * because after this key loading it is not needed anymore + /* We are using for the source/user key the same buffer + * as for the output keys, * because after this key loading it + * is not needed anymore */ set_din_type(&desc[0], DMA_DLLI, ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen, @@ -309,7 +317,7 @@ static int xcbc_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) return 4; } -static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) +static int hmac_setkey(struct cc_hw_desc *desc, struct cc_aead_ctx *ctx) { unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; unsigned int digest_ofs = 0; @@ -328,8 +336,8 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], hash_mode); set_din_sram(&desc[idx], - ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->auth_mode), + cc_larval_digest_addr(ctx->drvdata, + ctx->auth_mode), digest_size); set_flow_mode(&desc[idx], S_DIN_to_HASH); set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); @@ -378,7 +386,7 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) return idx; } -static int validate_keys_sizes(struct ssi_aead_ctx *ctx) +static int validate_keys_sizes(struct cc_aead_ctx *ctx) { struct device *dev = drvdata_to_dev(ctx->drvdata); @@ -390,9 +398,9 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx) case DRV_HASH_SHA256: break; case DRV_HASH_XCBC_MAC: - if ((ctx->auth_keylen != AES_KEYSIZE_128) && - (ctx->auth_keylen != AES_KEYSIZE_192) && - (ctx->auth_keylen != AES_KEYSIZE_256)) + if (ctx->auth_keylen != AES_KEYSIZE_128 && + ctx->auth_keylen != AES_KEYSIZE_192 && + ctx->auth_keylen != AES_KEYSIZE_256) return -ENOTSUPP; break; case DRV_HASH_NULL: /* Not authenc (e.g., CCM) - no auth_key) */ @@ -404,16 +412,16 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx) return -EINVAL; } /* Check cipher key size */ - if (unlikely(ctx->flow_mode == S_DIN_to_DES)) { + if (ctx->flow_mode == S_DIN_to_DES) { if (ctx->enc_keylen != DES3_EDE_KEY_SIZE) { dev_err(dev, "Invalid cipher(3DES) key size: %u\n", ctx->enc_keylen); return -EINVAL; } } else { /* Default assumed to be AES ciphers */ - if ((ctx->enc_keylen != AES_KEYSIZE_128) && - (ctx->enc_keylen != AES_KEYSIZE_192) && - (ctx->enc_keylen != AES_KEYSIZE_256)) { + if (ctx->enc_keylen != AES_KEYSIZE_128 && + ctx->enc_keylen != AES_KEYSIZE_192 && + ctx->enc_keylen != AES_KEYSIZE_256) { dev_err(dev, "Invalid cipher(AES) key size: %u\n", ctx->enc_keylen); return -EINVAL; @@ -427,13 +435,13 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx) * (copy to intenral buffer or hash in case of key longer than block */ static int -ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +cc_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { dma_addr_t key_dma_addr = 0; - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); - u32 larval_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->auth_mode); + u32 larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->auth_mode); struct ssi_crypto_req ssi_req = {}; unsigned int blocksize; unsigned int digestsize; @@ -457,9 +465,10 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keyl hashmode = DRV_HASH_HW_SHA256; } - if (likely(keylen != 0)) { - key_dma_addr = dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, key_dma_addr))) { + if (keylen != 0) { + key_dma_addr = dma_map_single(dev, (void *)key, keylen, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, key_dma_addr)) { dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", key, keylen); return -ENOMEM; @@ -538,19 +547,19 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keyl } rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (unlikely(rc != 0)) + if (rc) dev_err(dev, "send_request() failed (rc=%d)\n", rc); - if (likely(key_dma_addr != 0)) + if (key_dma_addr) dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE); return rc; } static int -ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +cc_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct rtattr *rta = (struct rtattr *)key; struct ssi_crypto_req ssi_req = {}; struct crypto_authenc_key_param *param; @@ -586,8 +595,9 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) /* Copy nonce from last 4 bytes in CTR key to * first 4 bytes in CTR IV */ - memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + ctx->enc_keylen - - CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE); + memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + + ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE, + CTR_RFC3686_NONCE_SIZE); /* Set CTR key size */ ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE; } @@ -597,7 +607,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) } rc = validate_keys_sizes(ctx); - if (unlikely(rc != 0)) + if (rc) goto badkey; /* STAT_PHASE_1: Copy key to ctx */ @@ -609,8 +619,8 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen); } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */ - rc = ssi_get_plain_hmac_key(tfm, key, ctx->auth_keylen); - if (rc != 0) + rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen); + if (rc) goto badkey; } @@ -636,7 +646,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) if (seq_len > 0) { /* For CCM there is no sequence to setup the key */ rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 0); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); goto setkey_error; } @@ -653,9 +663,10 @@ setkey_error: } #if SSI_CC_HAS_AES_CCM -static int ssi_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +static int cc_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); if (keylen < 3) return -EINVAL; @@ -663,20 +674,19 @@ static int ssi_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, unsign keylen -= 3; memcpy(ctx->ctr_nonce, key + keylen, 3); - return ssi_aead_setkey(tfm, key, keylen); + return cc_aead_setkey(tfm, key, keylen); } #endif /*SSI_CC_HAS_AES_CCM*/ -static int ssi_aead_setauthsize( - struct crypto_aead *authenc, - unsigned int authsize) +static int cc_aead_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc); + struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc); struct device *dev = drvdata_to_dev(ctx->drvdata); /* Unsupported auth. sizes */ - if ((authsize == 0) || - (authsize > crypto_aead_maxauthsize(authenc))) { + if (authsize == 0 || + authsize > crypto_aead_maxauthsize(authenc)) { return -ENOTSUPP; } @@ -687,8 +697,8 @@ static int ssi_aead_setauthsize( } #if SSI_CC_HAS_AES_CCM -static int ssi_rfc4309_ccm_setauthsize(struct crypto_aead *authenc, - unsigned int authsize) +static int cc_rfc4309_ccm_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) { switch (authsize) { case 8: @@ -699,11 +709,11 @@ static int ssi_rfc4309_ccm_setauthsize(struct crypto_aead *authenc, return -EINVAL; } - return ssi_aead_setauthsize(authenc, authsize); + return cc_aead_setauthsize(authenc, authsize); } -static int ssi_ccm_setauthsize(struct crypto_aead *authenc, - unsigned int authsize) +static int cc_ccm_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) { switch (authsize) { case 4: @@ -718,19 +728,15 @@ static int ssi_ccm_setauthsize(struct crypto_aead *authenc, return -EINVAL; } - return ssi_aead_setauthsize(authenc, authsize); + return cc_aead_setauthsize(authenc, authsize); } #endif /*SSI_CC_HAS_AES_CCM*/ -static inline void -ssi_aead_create_assoc_desc( - struct aead_request *areq, - unsigned int flow_mode, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_set_assoc_desc(struct aead_request *areq, unsigned int flow_mode, + struct cc_hw_desc desc[], unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(areq); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *areq_ctx = aead_request_ctx(areq); enum ssi_req_dma_buf_type assoc_dma_type = areq_ctx->assoc_buff_type; unsigned int idx = *seq_size; @@ -743,8 +749,8 @@ ssi_aead_create_assoc_desc( set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src), areq->assoclen, NS_BIT); set_flow_mode(&desc[idx], flow_mode); - if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) && - (areq_ctx->cryptlen > 0)) + if (ctx->auth_mode == DRV_HASH_XCBC_MAC && + areq_ctx->cryptlen > 0) set_din_not_last_indication(&desc[idx]); break; case SSI_DMA_BUF_MLLI: @@ -753,8 +759,8 @@ ssi_aead_create_assoc_desc( set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr, areq_ctx->assoc.mlli_nents, NS_BIT); set_flow_mode(&desc[idx], flow_mode); - if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) && - (areq_ctx->cryptlen > 0)) + if (ctx->auth_mode == DRV_HASH_XCBC_MAC && + areq_ctx->cryptlen > 0) set_din_not_last_indication(&desc[idx]); break; case SSI_DMA_BUF_NULL: @@ -765,19 +771,16 @@ ssi_aead_create_assoc_desc( *seq_size = (++idx); } -static inline void -ssi_aead_process_authenc_data_desc( - struct aead_request *areq, - unsigned int flow_mode, - struct cc_hw_desc desc[], - unsigned int *seq_size, - int direct) +static void cc_proc_authen_desc(struct aead_request *areq, + unsigned int flow_mode, + struct cc_hw_desc desc[], + unsigned int *seq_size, int direct) { struct aead_req_ctx *areq_ctx = aead_request_ctx(areq); enum ssi_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type; unsigned int idx = *seq_size; struct crypto_aead *tfm = crypto_aead_reqtfm(areq); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); switch (data_dma_type) { @@ -807,7 +810,7 @@ ssi_aead_process_authenc_data_desc( ssi_sram_addr_t mlli_addr = areq_ctx->assoc.sram_addr; u32 mlli_nents = areq_ctx->assoc.mlli_nents; - if (likely(areq_ctx->is_single_pass)) { + if (areq_ctx->is_single_pass) { if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { mlli_addr = areq_ctx->dst.sram_addr; mlli_nents = areq_ctx->dst.mlli_nents; @@ -832,18 +835,16 @@ ssi_aead_process_authenc_data_desc( *seq_size = (++idx); } -static inline void -ssi_aead_process_cipher_data_desc( - struct aead_request *areq, - unsigned int flow_mode, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_proc_cipher_desc(struct aead_request *areq, + unsigned int flow_mode, + struct cc_hw_desc desc[], + unsigned int *seq_size) { unsigned int idx = *seq_size; struct aead_req_ctx *areq_ctx = aead_request_ctx(areq); enum ssi_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type; struct crypto_aead *tfm = crypto_aead_reqtfm(areq); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); if (areq_ctx->cryptlen == 0) @@ -855,7 +856,8 @@ ssi_aead_process_cipher_data_desc( hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, (sg_dma_address(areq_ctx->src_sgl) + - areq_ctx->src_offset), areq_ctx->cryptlen, NS_BIT); + areq_ctx->src_offset), areq_ctx->cryptlen, + NS_BIT); set_dout_dlli(&desc[idx], (sg_dma_address(areq_ctx->dst_sgl) + areq_ctx->dst_offset), @@ -879,13 +881,12 @@ ssi_aead_process_cipher_data_desc( *seq_size = (++idx); } -static inline void ssi_aead_process_digest_result_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_proc_digest_desc(struct aead_request *req, + struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); unsigned int idx = *seq_size; unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? @@ -930,13 +931,12 @@ static inline void ssi_aead_process_digest_result_desc( *seq_size = (++idx); } -static inline void ssi_aead_setup_cipher_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_set_cipher_desc(struct aead_request *req, + struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); unsigned int hw_iv_size = req_ctx->hw_iv_size; unsigned int idx = *seq_size; @@ -976,11 +976,8 @@ static inline void ssi_aead_setup_cipher_desc( *seq_size = idx; } -static inline void ssi_aead_process_cipher( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size, - unsigned int data_flow_mode) +static void cc_proc_cipher(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size, unsigned int data_flow_mode) { struct aead_req_ctx *req_ctx = aead_request_ctx(req); int direct = req_ctx->gen_ctx.op_type; @@ -989,8 +986,8 @@ static inline void ssi_aead_process_cipher( if (req_ctx->cryptlen == 0) return; /*null processing*/ - ssi_aead_setup_cipher_desc(req, desc, &idx); - ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, &idx); + cc_set_cipher_desc(req, desc, &idx); + cc_proc_cipher_desc(req, data_flow_mode, desc, &idx); if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { /* We must wait for DMA to write all cipher */ hw_desc_init(&desc[idx]); @@ -1002,13 +999,11 @@ static inline void ssi_aead_process_cipher( *seq_size = idx; } -static inline void ssi_aead_hmac_setup_digest_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_set_hmac_desc(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ? @@ -1039,13 +1034,11 @@ static inline void ssi_aead_hmac_setup_digest_desc( *seq_size = idx; } -static inline void ssi_aead_xcbc_setup_digest_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_set_xcbc_desc(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); unsigned int idx = *seq_size; /* Loading MAC state */ @@ -1101,28 +1094,26 @@ static inline void ssi_aead_xcbc_setup_digest_desc( *seq_size = idx; } -static inline void ssi_aead_process_digest_header_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_proc_header_desc(struct aead_request *req, + struct cc_hw_desc desc[], + unsigned int *seq_size) { unsigned int idx = *seq_size; /* Hash associated data */ if (req->assoclen > 0) - ssi_aead_create_assoc_desc(req, DIN_HASH, desc, &idx); + cc_set_assoc_desc(req, DIN_HASH, desc, &idx); /* Hash IV */ *seq_size = idx; } -static inline void ssi_aead_process_digest_scheme_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_proc_scheme_desc(struct aead_request *req, + struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); - struct ssi_aead_handle *aead_handle = ctx->drvdata->aead_handle; + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_handle *aead_handle = ctx->drvdata->aead_handle; unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ? @@ -1180,20 +1171,17 @@ static inline void ssi_aead_process_digest_scheme_desc( *seq_size = idx; } -static inline void ssi_aead_load_mlli_to_sram( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_mlli_to_sram(struct aead_request *req, + struct cc_hw_desc desc[], unsigned int *seq_size) { struct aead_req_ctx *req_ctx = aead_request_ctx(req); struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); - if (unlikely( - (req_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) || - (req_ctx->data_buff_type == SSI_DMA_BUF_MLLI) || - !req_ctx->is_single_pass)) { + if (req_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI || + req_ctx->data_buff_type == SSI_DMA_BUF_MLLI || + !req_ctx->is_single_pass) { dev_dbg(dev, "Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n", (unsigned int)ctx->drvdata->mlli_sram_addr, req_ctx->mlli_params.mlli_len); @@ -1210,54 +1198,51 @@ static inline void ssi_aead_load_mlli_to_sram( } } -static inline enum cc_flow_mode ssi_aead_get_data_flow_mode( - enum drv_crypto_direction direct, - enum cc_flow_mode setup_flow_mode, - bool is_single_pass) +static enum cc_flow_mode cc_get_data_flow(enum drv_crypto_direction direct, + enum cc_flow_mode setup_flow_mode, + bool is_single_pass) { enum cc_flow_mode data_flow_mode; if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { if (setup_flow_mode == S_DIN_to_AES) - data_flow_mode = likely(is_single_pass) ? + data_flow_mode = is_single_pass ? AES_to_HASH_and_DOUT : DIN_AES_DOUT; else - data_flow_mode = likely(is_single_pass) ? + data_flow_mode = is_single_pass ? DES_to_HASH_and_DOUT : DIN_DES_DOUT; } else { /* Decrypt */ if (setup_flow_mode == S_DIN_to_AES) - data_flow_mode = likely(is_single_pass) ? - AES_and_HASH : DIN_AES_DOUT; + data_flow_mode = is_single_pass ? + AES_and_HASH : DIN_AES_DOUT; else - data_flow_mode = likely(is_single_pass) ? - DES_and_HASH : DIN_DES_DOUT; + data_flow_mode = is_single_pass ? + DES_and_HASH : DIN_DES_DOUT; } return data_flow_mode; } -static inline void ssi_aead_hmac_authenc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_hmac_authenc(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); int direct = req_ctx->gen_ctx.op_type; - unsigned int data_flow_mode = ssi_aead_get_data_flow_mode( + unsigned int data_flow_mode = cc_get_data_flow( direct, ctx->flow_mode, req_ctx->is_single_pass); if (req_ctx->is_single_pass) { /** * Single-pass flow */ - ssi_aead_hmac_setup_digest_desc(req, desc, seq_size); - ssi_aead_setup_cipher_desc(req, desc, seq_size); - ssi_aead_process_digest_header_desc(req, desc, seq_size); - ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, seq_size); - ssi_aead_process_digest_scheme_desc(req, desc, seq_size); - ssi_aead_process_digest_result_desc(req, desc, seq_size); + cc_set_hmac_desc(req, desc, seq_size); + cc_set_cipher_desc(req, desc, seq_size); + cc_proc_header_desc(req, desc, seq_size); + cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size); + cc_proc_scheme_desc(req, desc, seq_size); + cc_proc_digest_desc(req, desc, seq_size); return; } @@ -1268,49 +1253,47 @@ static inline void ssi_aead_hmac_authenc( */ if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { /* encrypt first.. */ - ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); + cc_proc_cipher(req, desc, seq_size, data_flow_mode); /* authenc after..*/ - ssi_aead_hmac_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); - ssi_aead_process_digest_scheme_desc(req, desc, seq_size); - ssi_aead_process_digest_result_desc(req, desc, seq_size); + cc_set_hmac_desc(req, desc, seq_size); + cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); + cc_proc_scheme_desc(req, desc, seq_size); + cc_proc_digest_desc(req, desc, seq_size); } else { /*DECRYPT*/ /* authenc first..*/ - ssi_aead_hmac_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); - ssi_aead_process_digest_scheme_desc(req, desc, seq_size); + cc_set_hmac_desc(req, desc, seq_size); + cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); + cc_proc_scheme_desc(req, desc, seq_size); /* decrypt after.. */ - ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); + cc_proc_cipher(req, desc, seq_size, data_flow_mode); /* read the digest result with setting the completion bit * must be after the cipher operation */ - ssi_aead_process_digest_result_desc(req, desc, seq_size); + cc_proc_digest_desc(req, desc, seq_size); } } -static inline void -ssi_aead_xcbc_authenc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void +cc_xcbc_authenc(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); int direct = req_ctx->gen_ctx.op_type; - unsigned int data_flow_mode = ssi_aead_get_data_flow_mode( + unsigned int data_flow_mode = cc_get_data_flow( direct, ctx->flow_mode, req_ctx->is_single_pass); if (req_ctx->is_single_pass) { /** * Single-pass flow */ - ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size); - ssi_aead_setup_cipher_desc(req, desc, seq_size); - ssi_aead_process_digest_header_desc(req, desc, seq_size); - ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, seq_size); - ssi_aead_process_digest_result_desc(req, desc, seq_size); + cc_set_xcbc_desc(req, desc, seq_size); + cc_set_cipher_desc(req, desc, seq_size); + cc_proc_header_desc(req, desc, seq_size); + cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size); + cc_proc_digest_desc(req, desc, seq_size); return; } @@ -1321,25 +1304,25 @@ ssi_aead_xcbc_authenc( */ if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { /* encrypt first.. */ - ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); + cc_proc_cipher(req, desc, seq_size, data_flow_mode); /* authenc after.. */ - ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); - ssi_aead_process_digest_result_desc(req, desc, seq_size); + cc_set_xcbc_desc(req, desc, seq_size); + cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); + cc_proc_digest_desc(req, desc, seq_size); } else { /*DECRYPT*/ /* authenc first.. */ - ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); + cc_set_xcbc_desc(req, desc, seq_size); + cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); /* decrypt after..*/ - ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); + cc_proc_cipher(req, desc, seq_size, data_flow_mode); /* read the digest result with setting the completion bit * must be after the cipher operation */ - ssi_aead_process_digest_result_desc(req, desc, seq_size); + cc_proc_digest_desc(req, desc, seq_size); } } -static int validate_data_size(struct ssi_aead_ctx *ctx, +static int validate_data_size(struct cc_aead_ctx *ctx, enum drv_crypto_direction direct, struct aead_request *req) { @@ -1349,16 +1332,16 @@ static int validate_data_size(struct ssi_aead_ctx *ctx, unsigned int cipherlen = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ? (req->cryptlen - ctx->authsize) : req->cryptlen; - if (unlikely((direct == DRV_CRYPTO_DIRECTION_DECRYPT) && - (req->cryptlen < ctx->authsize))) + if (direct == DRV_CRYPTO_DIRECTION_DECRYPT && + req->cryptlen < ctx->authsize) goto data_size_err; areq_ctx->is_single_pass = true; /*defaulted to fast flow*/ switch (ctx->flow_mode) { case S_DIN_to_AES: - if (unlikely((ctx->cipher_mode == DRV_CIPHER_CBC) && - !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE))) + if (ctx->cipher_mode == DRV_CIPHER_CBC && + !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE)) goto data_size_err; if (ctx->cipher_mode == DRV_CIPHER_CCM) break; @@ -1371,15 +1354,15 @@ static int validate_data_size(struct ssi_aead_ctx *ctx, if (!IS_ALIGNED(assoclen, sizeof(u32))) areq_ctx->is_single_pass = false; - if ((ctx->cipher_mode == DRV_CIPHER_CTR) && + if (ctx->cipher_mode == DRV_CIPHER_CTR && !IS_ALIGNED(cipherlen, sizeof(u32))) areq_ctx->is_single_pass = false; break; case S_DIN_to_DES: - if (unlikely(!IS_ALIGNED(cipherlen, DES_BLOCK_SIZE))) + if (!IS_ALIGNED(cipherlen, DES_BLOCK_SIZE)) goto data_size_err; - if (unlikely(!IS_ALIGNED(assoclen, DES_BLOCK_SIZE))) + if (!IS_ALIGNED(assoclen, DES_BLOCK_SIZE)) areq_ctx->is_single_pass = false; break; default: @@ -1438,13 +1421,11 @@ static int set_msg_len(u8 *block, unsigned int msglen, unsigned int csize) return 0; } -static inline int ssi_aead_ccm( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static int cc_ccm(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); unsigned int idx = *seq_size; unsigned int cipher_flow_mode; @@ -1508,7 +1489,7 @@ static inline int ssi_aead_ccm( /* process assoc data */ if (req->assoclen > 0) { - ssi_aead_create_assoc_desc(req, DIN_HASH, desc, &idx); + cc_set_assoc_desc(req, DIN_HASH, desc, &idx); } else { hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, @@ -1519,8 +1500,8 @@ static inline int ssi_aead_ccm( } /* process the cipher */ - if (req_ctx->cryptlen != 0) - ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, &idx); + if (req_ctx->cryptlen) + cc_proc_cipher_desc(req, cipher_flow_mode, desc, &idx); /* Read temporal MAC */ hw_desc_init(&desc[idx]); @@ -1565,12 +1546,14 @@ static inline int ssi_aead_ccm( static int config_ccm_adata(struct aead_request *req) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); struct aead_req_ctx *req_ctx = aead_request_ctx(req); //unsigned int size_of_a = 0, rem_a_size = 0; unsigned int lp = req->iv[0]; - /* Note: The code assume that req->iv[0] already contains the value of L' of RFC3610 */ + /* Note: The code assume that req->iv[0] already contains the value + * of L' of RFC3610 + */ unsigned int l = lp + 1; /* This is L' of RFC 3610. */ unsigned int m = ctx->authsize; /* This is M' of RFC 3610. */ u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET; @@ -1601,7 +1584,7 @@ static int config_ccm_adata(struct aead_request *req) *b0 |= 64; /* Enable bit 6 if Adata exists. */ rc = set_msg_len(b0 + 16 - l, cryptlen, l); /* Write L'. */ - if (rc != 0) { + if (rc) { dev_err(dev, "message len overflow detected"); return rc; } @@ -1619,19 +1602,26 @@ static int config_ccm_adata(struct aead_request *req) return 0; } -static void ssi_rfc4309_ccm_process(struct aead_request *req) +static void cc_proc_rfc4309_ccm(struct aead_request *req) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); /* L' */ memset(areq_ctx->ctr_iv, 0, AES_BLOCK_SIZE); - areq_ctx->ctr_iv[0] = 3; /* For RFC 4309, always use 4 bytes for message length (at most 2^32-1 bytes). */ + /* For RFC 4309, always use 4 bytes for message length + * (at most 2^32-1 bytes). + */ + areq_ctx->ctr_iv[0] = 3; - /* In RFC 4309 there is an 11-bytes nonce+IV part, that we build here. */ - memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, CCM_BLOCK_NONCE_SIZE); - memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv, CCM_BLOCK_IV_SIZE); + /* In RFC 4309 there is an 11-bytes nonce+IV part, + * that we build here. + */ + memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, + CCM_BLOCK_NONCE_SIZE); + memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv, + CCM_BLOCK_IV_SIZE); req->iv = areq_ctx->ctr_iv; req->assoclen -= CCM_BLOCK_IV_SIZE; } @@ -1639,13 +1629,11 @@ static void ssi_rfc4309_ccm_process(struct aead_request *req) #if SSI_CC_HAS_AES_GCM -static inline void ssi_aead_gcm_setup_ghash_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_set_ghash_desc(struct aead_request *req, + struct cc_hw_desc desc[], unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); unsigned int idx = *seq_size; @@ -1703,7 +1691,9 @@ static inline void ssi_aead_gcm_setup_ghash_desc( set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); idx++; - /* Load GHASH initial STATE (which is 0). (for any hash there is an initial state) */ + /* Load GHASH initial STATE (which is 0). (for any hash there is an + * initial state) + */ hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE); set_dout_no_dma(&desc[idx], 0, 0, 1); @@ -1717,13 +1707,11 @@ static inline void ssi_aead_gcm_setup_ghash_desc( *seq_size = idx; } -static inline void ssi_aead_gcm_setup_gctr_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_set_gctr_desc(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); unsigned int idx = *seq_size; @@ -1738,7 +1726,7 @@ static inline void ssi_aead_gcm_setup_gctr_desc( set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; - if ((req_ctx->cryptlen != 0) && (!req_ctx->plaintext_authenticate_only)) { + if (req_ctx->cryptlen && !req_ctx->plaintext_authenticate_only) { /* load AES/CTR initial CTR value inc by 2*/ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); @@ -1755,13 +1743,12 @@ static inline void ssi_aead_gcm_setup_gctr_desc( *seq_size = idx; } -static inline void ssi_aead_process_gcm_result_desc( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static void cc_proc_gcm_result(struct aead_request *req, + struct cc_hw_desc desc[], + unsigned int *seq_size) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); dma_addr_t mac_result; unsigned int idx = *seq_size; @@ -1821,10 +1808,8 @@ static inline void ssi_aead_process_gcm_result_desc( *seq_size = idx; } -static inline int ssi_aead_gcm( - struct aead_request *req, - struct cc_hw_desc desc[], - unsigned int *seq_size) +static int cc_gcm(struct aead_request *req, struct cc_hw_desc desc[], + unsigned int *seq_size) { struct aead_req_ctx *req_ctx = aead_request_ctx(req); unsigned int cipher_flow_mode; @@ -1837,36 +1822,34 @@ static inline int ssi_aead_gcm( //in RFC4543 no data to encrypt. just copy data from src to dest. if (req_ctx->plaintext_authenticate_only) { - ssi_aead_process_cipher_data_desc(req, BYPASS, desc, seq_size); - ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size); + cc_proc_cipher_desc(req, BYPASS, desc, seq_size); + cc_set_ghash_desc(req, desc, seq_size); /* process(ghash) assoc data */ - ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size); - ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size); - ssi_aead_process_gcm_result_desc(req, desc, seq_size); + cc_set_assoc_desc(req, DIN_HASH, desc, seq_size); + cc_set_gctr_desc(req, desc, seq_size); + cc_proc_gcm_result(req, desc, seq_size); return 0; } // for gcm and rfc4106. - ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size); + cc_set_ghash_desc(req, desc, seq_size); /* process(ghash) assoc data */ if (req->assoclen > 0) - ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size); - ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size); + cc_set_assoc_desc(req, DIN_HASH, desc, seq_size); + cc_set_gctr_desc(req, desc, seq_size); /* process(gctr+ghash) */ - if (req_ctx->cryptlen != 0) - ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size); - ssi_aead_process_gcm_result_desc(req, desc, seq_size); + if (req_ctx->cryptlen) + cc_proc_cipher_desc(req, cipher_flow_mode, desc, seq_size); + cc_proc_gcm_result(req, desc, seq_size); return 0; } #ifdef CC_DEBUG -static inline void ssi_aead_dump_gcm( - const char *title, - struct aead_request *req) +static void cc_dump_gcm(const char *title, struct aead_request *req) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); if (ctx->cipher_mode != DRV_CIPHER_GCTR) @@ -1894,20 +1877,23 @@ static inline void ssi_aead_dump_gcm( dump_byte_array("mac_buf", req_ctx->mac_buf, AES_BLOCK_SIZE); - dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.len_a, AES_BLOCK_SIZE); + dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.len_a, + AES_BLOCK_SIZE); if (req->src && req->cryptlen) - dump_byte_array("req->src", sg_virt(req->src), req->cryptlen + req->assoclen); + dump_byte_array("req->src", sg_virt(req->src), + req->cryptlen + req->assoclen); if (req->dst) - dump_byte_array("req->dst", sg_virt(req->dst), req->cryptlen + ctx->authsize + req->assoclen); + dump_byte_array("req->dst", sg_virt(req->dst), + req->cryptlen + ctx->authsize + req->assoclen); } #endif static int config_gcm_context(struct aead_request *req) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *req_ctx = aead_request_ctx(req); struct device *dev = drvdata_to_dev(ctx->drvdata); @@ -1938,10 +1924,14 @@ static int config_gcm_context(struct aead_request *req) memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); temp64 = cpu_to_be64(cryptlen * 8); memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); - } else { //rfc4543=> all data(AAD,IV,Plain) are considered additional data that is nothing is encrypted. + } else { + /* rfc4543=> all data(AAD,IV,Plain) are considered additional + * data that is nothing is encrypted. + */ __be64 temp64; - temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + cryptlen) * 8); + temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + + cryptlen) * 8); memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); temp64 = 0; memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); @@ -1950,27 +1940,30 @@ static int config_gcm_context(struct aead_request *req) return 0; } -static void ssi_rfc4_gcm_process(struct aead_request *req) +static void cc_proc_rfc4_gcm(struct aead_request *req) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); - memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE); - memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv, GCM_BLOCK_RFC4_IV_SIZE); + memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, + ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE); + memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv, + GCM_BLOCK_RFC4_IV_SIZE); req->iv = areq_ctx->ctr_iv; req->assoclen -= GCM_BLOCK_RFC4_IV_SIZE; } #endif /*SSI_CC_HAS_AES_GCM*/ -static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction direct) +static int cc_proc_aead(struct aead_request *req, + enum drv_crypto_direction direct) { int rc = 0; int seq_len = 0; struct cc_hw_desc desc[MAX_AEAD_PROCESS_SEQ]; struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); struct device *dev = drvdata_to_dev(ctx->drvdata); struct ssi_crypto_req ssi_req = {}; @@ -1983,7 +1976,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction /* STAT_PHASE_0: Init and sanity checks */ /* Check data length according to mode */ - if (unlikely(validate_data_size(ctx, direct, req) != 0)) { + if (validate_data_size(ctx, direct, req)) { dev_err(dev, "Unsupported crypt/assoc len %d/%d.\n", req->cryptlen, req->assoclen); crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN); @@ -1991,7 +1984,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction } /* Setup DX request structure */ - ssi_req.user_cb = (void *)ssi_aead_complete; + ssi_req.user_cb = (void *)cc_aead_complete; ssi_req.user_arg = (void *)req; /* Setup request context */ @@ -2005,7 +1998,8 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction /* Build CTR IV - Copy nonce from last 4 bytes in * CTR key to first 4 bytes in CTR IV */ - memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, CTR_RFC3686_NONCE_SIZE); + memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, + CTR_RFC3686_NONCE_SIZE); if (!areq_ctx->backup_giv) /*User none-generated IV*/ memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, req->iv, CTR_RFC3686_IV_SIZE); @@ -2020,7 +2014,8 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction (ctx->cipher_mode == DRV_CIPHER_GCTR)) { areq_ctx->hw_iv_size = AES_BLOCK_SIZE; if (areq_ctx->ctr_iv != req->iv) { - memcpy(areq_ctx->ctr_iv, req->iv, crypto_aead_ivsize(tfm)); + memcpy(areq_ctx->ctr_iv, req->iv, + crypto_aead_ivsize(tfm)); req->iv = areq_ctx->ctr_iv; } } else { @@ -2030,7 +2025,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction #if SSI_CC_HAS_AES_CCM if (ctx->cipher_mode == DRV_CIPHER_CCM) { rc = config_ccm_adata(req); - if (unlikely(rc != 0)) { + if (rc) { dev_dbg(dev, "config_ccm_adata() returned with a failure %d!", rc); goto exit; @@ -2045,7 +2040,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction #if SSI_CC_HAS_AES_GCM if (ctx->cipher_mode == DRV_CIPHER_GCTR) { rc = config_gcm_context(req); - if (unlikely(rc != 0)) { + if (rc) { dev_dbg(dev, "config_gcm_context() returned with a failure %d!", rc); goto exit; @@ -2053,8 +2048,8 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction } #endif /*SSI_CC_HAS_AES_GCM*/ - rc = ssi_buffer_mgr_map_aead_request(ctx->drvdata, req); - if (unlikely(rc != 0)) { + rc = cc_map_aead_request(ctx->drvdata, req); + if (rc) { dev_err(dev, "map_request() failed\n"); goto exit; } @@ -2063,20 +2058,29 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction if (areq_ctx->backup_giv) { /* set the DMA mapped IV address*/ if (ctx->cipher_mode == DRV_CIPHER_CTR) { - ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CTR_RFC3686_NONCE_SIZE; + ssi_req.ivgen_dma_addr[0] = + areq_ctx->gen_ctx.iv_dma_addr + + CTR_RFC3686_NONCE_SIZE; ssi_req.ivgen_dma_addr_len = 1; } else if (ctx->cipher_mode == DRV_CIPHER_CCM) { - /* In ccm, the IV needs to exist both inside B0 and inside the counter. - * It is also copied to iv_dma_addr for other reasons (like returning - * it to the user). + /* In ccm, the IV needs to exist both inside B0 and + * inside the counter.It is also copied to iv_dma_addr + * for other reasons (like returning it to the user). * So, using 3 (identical) IV outputs. */ - ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CCM_BLOCK_IV_OFFSET; - ssi_req.ivgen_dma_addr[1] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET; - ssi_req.ivgen_dma_addr[2] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET; + ssi_req.ivgen_dma_addr[0] = + areq_ctx->gen_ctx.iv_dma_addr + + CCM_BLOCK_IV_OFFSET; + ssi_req.ivgen_dma_addr[1] = + sg_dma_address(&areq_ctx->ccm_adata_sg) + + CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET; + ssi_req.ivgen_dma_addr[2] = + sg_dma_address(&areq_ctx->ccm_adata_sg) + + CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET; ssi_req.ivgen_dma_addr_len = 3; } else { - ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr; + ssi_req.ivgen_dma_addr[0] = + areq_ctx->gen_ctx.iv_dma_addr; ssi_req.ivgen_dma_addr_len = 1; } @@ -2087,32 +2091,32 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction /* STAT_PHASE_2: Create sequence */ /* Load MLLI tables to SRAM if necessary */ - ssi_aead_load_mlli_to_sram(req, desc, &seq_len); + cc_mlli_to_sram(req, desc, &seq_len); /*TODO: move seq len by reference */ switch (ctx->auth_mode) { case DRV_HASH_SHA1: case DRV_HASH_SHA256: - ssi_aead_hmac_authenc(req, desc, &seq_len); + cc_hmac_authenc(req, desc, &seq_len); break; case DRV_HASH_XCBC_MAC: - ssi_aead_xcbc_authenc(req, desc, &seq_len); + cc_xcbc_authenc(req, desc, &seq_len); break; #if (SSI_CC_HAS_AES_CCM || SSI_CC_HAS_AES_GCM) case DRV_HASH_NULL: #if SSI_CC_HAS_AES_CCM if (ctx->cipher_mode == DRV_CIPHER_CCM) - ssi_aead_ccm(req, desc, &seq_len); + cc_ccm(req, desc, &seq_len); #endif /*SSI_CC_HAS_AES_CCM*/ #if SSI_CC_HAS_AES_GCM if (ctx->cipher_mode == DRV_CIPHER_GCTR) - ssi_aead_gcm(req, desc, &seq_len); + cc_gcm(req, desc, &seq_len); #endif /*SSI_CC_HAS_AES_GCM*/ - break; + break; #endif default: dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode); - ssi_buffer_mgr_unmap_aead_request(dev, req); + cc_unmap_aead_request(dev, req); rc = -ENOTSUPP; goto exit; } @@ -2121,16 +2125,16 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_aead_request(dev, req); + cc_unmap_aead_request(dev, req); } exit: return rc; } -static int ssi_aead_encrypt(struct aead_request *req) +static int cc_aead_encrypt(struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc; @@ -2142,7 +2146,7 @@ static int ssi_aead_encrypt(struct aead_request *req) areq_ctx->plaintext_authenticate_only = false; - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; @@ -2150,13 +2154,13 @@ static int ssi_aead_encrypt(struct aead_request *req) } #if SSI_CC_HAS_AES_CCM -static int ssi_rfc4309_ccm_encrypt(struct aead_request *req) +static int cc_rfc4309_ccm_encrypt(struct aead_request *req) { - /* Very similar to ssi_aead_encrypt() above. */ + /* Very similar to cc_aead_encrypt() above. */ struct aead_req_ctx *areq_ctx = aead_request_ctx(req); struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); int rc = -EINVAL; @@ -2170,9 +2174,9 @@ static int ssi_rfc4309_ccm_encrypt(struct aead_request *req) areq_ctx->backup_giv = NULL; areq_ctx->is_gcm4543 = true; - ssi_rfc4309_ccm_process(req); + cc_proc_rfc4309_ccm(req); - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; out: @@ -2180,7 +2184,7 @@ out: } #endif /* SSI_CC_HAS_AES_CCM */ -static int ssi_aead_decrypt(struct aead_request *req) +static int cc_aead_decrypt(struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc; @@ -2192,7 +2196,7 @@ static int ssi_aead_decrypt(struct aead_request *req) areq_ctx->plaintext_authenticate_only = false; - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; @@ -2200,10 +2204,10 @@ static int ssi_aead_decrypt(struct aead_request *req) } #if SSI_CC_HAS_AES_CCM -static int ssi_rfc4309_ccm_decrypt(struct aead_request *req) +static int cc_rfc4309_ccm_decrypt(struct aead_request *req) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc = -EINVAL; @@ -2218,9 +2222,9 @@ static int ssi_rfc4309_ccm_decrypt(struct aead_request *req) areq_ctx->backup_giv = NULL; areq_ctx->is_gcm4543 = true; - ssi_rfc4309_ccm_process(req); + cc_proc_rfc4309_ccm(req); - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; @@ -2231,9 +2235,10 @@ out: #if SSI_CC_HAS_AES_GCM -static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +static int cc_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "%s() keylen %d, key %p\n", __func__, keylen, key); @@ -2244,12 +2249,13 @@ static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign keylen -= 4; memcpy(ctx->ctr_nonce, key + keylen, 4); - return ssi_aead_setkey(tfm, key, keylen); + return cc_aead_setkey(tfm, key, keylen); } -static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +static int cc_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "%s() keylen %d, key %p\n", __func__, keylen, key); @@ -2260,11 +2266,11 @@ static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign keylen -= 4; memcpy(ctx->ctr_nonce, key + keylen, 4); - return ssi_aead_setkey(tfm, key, keylen); + return cc_aead_setkey(tfm, key, keylen); } -static int ssi_gcm_setauthsize(struct crypto_aead *authenc, - unsigned int authsize) +static int cc_gcm_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) { switch (authsize) { case 4: @@ -2279,13 +2285,13 @@ static int ssi_gcm_setauthsize(struct crypto_aead *authenc, return -EINVAL; } - return ssi_aead_setauthsize(authenc, authsize); + return cc_aead_setauthsize(authenc, authsize); } -static int ssi_rfc4106_gcm_setauthsize(struct crypto_aead *authenc, - unsigned int authsize) +static int cc_rfc4106_gcm_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc); + struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc); struct device *dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "authsize %d\n", authsize); @@ -2299,13 +2305,13 @@ static int ssi_rfc4106_gcm_setauthsize(struct crypto_aead *authenc, return -EINVAL; } - return ssi_aead_setauthsize(authenc, authsize); + return cc_aead_setauthsize(authenc, authsize); } -static int ssi_rfc4543_gcm_setauthsize(struct crypto_aead *authenc, - unsigned int authsize) +static int cc_rfc4543_gcm_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) { - struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc); + struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc); struct device *dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "authsize %d\n", authsize); @@ -2313,15 +2319,15 @@ static int ssi_rfc4543_gcm_setauthsize(struct crypto_aead *authenc, if (authsize != 16) return -EINVAL; - return ssi_aead_setauthsize(authenc, authsize); + return cc_aead_setauthsize(authenc, authsize); } -static int ssi_rfc4106_gcm_encrypt(struct aead_request *req) +static int cc_rfc4106_gcm_encrypt(struct aead_request *req) { - /* Very similar to ssi_aead_encrypt() above. */ + /* Very similar to cc_aead_encrypt() above. */ struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc = -EINVAL; @@ -2337,19 +2343,19 @@ static int ssi_rfc4106_gcm_encrypt(struct aead_request *req) areq_ctx->plaintext_authenticate_only = false; - ssi_rfc4_gcm_process(req); + cc_proc_rfc4_gcm(req); areq_ctx->is_gcm4543 = true; - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; out: return rc; } -static int ssi_rfc4543_gcm_encrypt(struct aead_request *req) +static int cc_rfc4543_gcm_encrypt(struct aead_request *req) { - /* Very similar to ssi_aead_encrypt() above. */ + /* Very similar to cc_aead_encrypt() above. */ struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc; @@ -2361,22 +2367,22 @@ static int ssi_rfc4543_gcm_encrypt(struct aead_request *req) areq_ctx->backup_iv = req->iv; areq_ctx->backup_giv = NULL; - ssi_rfc4_gcm_process(req); + cc_proc_rfc4_gcm(req); areq_ctx->is_gcm4543 = true; - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; return rc; } -static int ssi_rfc4106_gcm_decrypt(struct aead_request *req) +static int cc_rfc4106_gcm_decrypt(struct aead_request *req) { - /* Very similar to ssi_aead_decrypt() above. */ + /* Very similar to cc_aead_decrypt() above. */ struct crypto_aead *tfm = crypto_aead_reqtfm(req); - struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc = -EINVAL; @@ -2392,19 +2398,19 @@ static int ssi_rfc4106_gcm_decrypt(struct aead_request *req) areq_ctx->plaintext_authenticate_only = false; - ssi_rfc4_gcm_process(req); + cc_proc_rfc4_gcm(req); areq_ctx->is_gcm4543 = true; - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; out: return rc; } -static int ssi_rfc4543_gcm_decrypt(struct aead_request *req) +static int cc_rfc4543_gcm_decrypt(struct aead_request *req) { - /* Very similar to ssi_aead_decrypt() above. */ + /* Very similar to cc_aead_decrypt() above. */ struct aead_req_ctx *areq_ctx = aead_request_ctx(req); int rc; @@ -2416,10 +2422,10 @@ static int ssi_rfc4543_gcm_decrypt(struct aead_request *req) areq_ctx->backup_iv = req->iv; areq_ctx->backup_giv = NULL; - ssi_rfc4_gcm_process(req); + cc_proc_rfc4_gcm(req); areq_ctx->is_gcm4543 = true; - rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT); + rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); if (rc != -EINPROGRESS) req->iv = areq_ctx->backup_iv; @@ -2435,12 +2441,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = AES_BLOCK_SIZE, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, @@ -2454,12 +2460,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = DES3_EDE_BLOCK_SIZE, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, @@ -2473,12 +2479,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = AES_BLOCK_SIZE, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, @@ -2492,12 +2498,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = DES3_EDE_BLOCK_SIZE, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, @@ -2511,12 +2517,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = AES_BLOCK_SIZE, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = AES_BLOCK_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2530,12 +2536,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, @@ -2549,12 +2555,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, @@ -2568,12 +2574,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_aead_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_aead_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2588,12 +2594,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_ccm_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_ccm_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = AES_BLOCK_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2607,12 +2613,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_rfc4309_ccm_setkey, - .setauthsize = ssi_rfc4309_ccm_setauthsize, - .encrypt = ssi_rfc4309_ccm_encrypt, - .decrypt = ssi_rfc4309_ccm_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_rfc4309_ccm_setkey, + .setauthsize = cc_rfc4309_ccm_setauthsize, + .encrypt = cc_rfc4309_ccm_encrypt, + .decrypt = cc_rfc4309_ccm_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = CCM_BLOCK_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2628,12 +2634,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_aead_setkey, - .setauthsize = ssi_gcm_setauthsize, - .encrypt = ssi_aead_encrypt, - .decrypt = ssi_aead_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_aead_setkey, + .setauthsize = cc_gcm_setauthsize, + .encrypt = cc_aead_encrypt, + .decrypt = cc_aead_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = 12, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2647,12 +2653,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_rfc4106_gcm_setkey, - .setauthsize = ssi_rfc4106_gcm_setauthsize, - .encrypt = ssi_rfc4106_gcm_encrypt, - .decrypt = ssi_rfc4106_gcm_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_rfc4106_gcm_setkey, + .setauthsize = cc_rfc4106_gcm_setauthsize, + .encrypt = cc_rfc4106_gcm_encrypt, + .decrypt = cc_rfc4106_gcm_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = GCM_BLOCK_RFC4_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2666,12 +2672,12 @@ static struct ssi_alg_template aead_algs[] = { .blocksize = 1, .type = CRYPTO_ALG_TYPE_AEAD, .template_aead = { - .setkey = ssi_rfc4543_gcm_setkey, - .setauthsize = ssi_rfc4543_gcm_setauthsize, - .encrypt = ssi_rfc4543_gcm_encrypt, - .decrypt = ssi_rfc4543_gcm_decrypt, - .init = ssi_aead_init, - .exit = ssi_aead_exit, + .setkey = cc_rfc4543_gcm_setkey, + .setauthsize = cc_rfc4543_gcm_setauthsize, + .encrypt = cc_rfc4543_gcm_encrypt, + .decrypt = cc_rfc4543_gcm_decrypt, + .init = cc_aead_init, + .exit = cc_aead_exit, .ivsize = GCM_BLOCK_RFC4_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, @@ -2682,7 +2688,7 @@ static struct ssi_alg_template aead_algs[] = { #endif /*SSI_CC_HAS_AES_GCM*/ }; -static struct ssi_crypto_alg *ssi_aead_create_alg( +static struct ssi_crypto_alg *cc_create_aead_alg( struct ssi_alg_template *template, struct device *dev) { @@ -2695,17 +2701,18 @@ static struct ssi_crypto_alg *ssi_aead_create_alg( alg = &template->template_aead; - snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name); + snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", + template->name); snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", template->driver_name); alg->base.cra_module = THIS_MODULE; alg->base.cra_priority = SSI_CRA_PRIO; - alg->base.cra_ctxsize = sizeof(struct ssi_aead_ctx); + alg->base.cra_ctxsize = sizeof(struct cc_aead_ctx); alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY | template->type; - alg->init = ssi_aead_init; - alg->exit = ssi_aead_exit; + alg->init = cc_aead_init; + alg->exit = cc_aead_exit; t_alg->aead_alg = *alg; @@ -2716,15 +2723,16 @@ static struct ssi_crypto_alg *ssi_aead_create_alg( return t_alg; } -int ssi_aead_free(struct ssi_drvdata *drvdata) +int cc_aead_free(struct ssi_drvdata *drvdata) { struct ssi_crypto_alg *t_alg, *n; - struct ssi_aead_handle *aead_handle = - (struct ssi_aead_handle *)drvdata->aead_handle; + struct cc_aead_handle *aead_handle = + (struct cc_aead_handle *)drvdata->aead_handle; if (aead_handle) { /* Remove registered algs */ - list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, entry) { + list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, + entry) { crypto_unregister_aead(&t_alg->aead_alg); list_del(&t_alg->entry); kfree(t_alg); @@ -2736,9 +2744,9 @@ int ssi_aead_free(struct ssi_drvdata *drvdata) return 0; } -int ssi_aead_alloc(struct ssi_drvdata *drvdata) +int cc_aead_alloc(struct ssi_drvdata *drvdata) { - struct ssi_aead_handle *aead_handle; + struct cc_aead_handle *aead_handle; struct ssi_crypto_alg *t_alg; int rc = -ENOMEM; int alg; @@ -2753,8 +2761,9 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata) INIT_LIST_HEAD(&aead_handle->aead_list); drvdata->aead_handle = aead_handle; - aead_handle->sram_workspace_addr = ssi_sram_mgr_alloc( - drvdata, MAX_HMAC_DIGEST_SIZE); + aead_handle->sram_workspace_addr = cc_sram_alloc(drvdata, + MAX_HMAC_DIGEST_SIZE); + if (aead_handle->sram_workspace_addr == NULL_SRAM_ADDR) { dev_err(dev, "SRAM pool exhausted\n"); rc = -ENOMEM; @@ -2763,7 +2772,7 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata) /* Linux crypto */ for (alg = 0; alg < ARRAY_SIZE(aead_algs); alg++) { - t_alg = ssi_aead_create_alg(&aead_algs[alg], dev); + t_alg = cc_create_aead_alg(&aead_algs[alg], dev); if (IS_ERR(t_alg)) { rc = PTR_ERR(t_alg); dev_err(dev, "%s alg allocation failed\n", @@ -2772,7 +2781,7 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata) } t_alg->drvdata = drvdata; rc = crypto_register_aead(&t_alg->aead_alg); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "%s alg registration failed\n", t_alg->aead_alg.base.cra_driver_name); goto fail2; @@ -2788,7 +2797,7 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata) fail2: kfree(t_alg); fail1: - ssi_aead_free(drvdata); + cc_aead_free(drvdata); fail0: return rc; } diff --git a/drivers/staging/ccree/ssi_aead.h b/drivers/staging/ccree/ssi_aead.h index e85bcd917e7b..51722414a6a9 100644 --- a/drivers/staging/ccree/ssi_aead.h +++ b/drivers/staging/ccree/ssi_aead.h @@ -28,7 +28,7 @@ /* mac_cmp - HW writes 8 B but all bytes hold the same value */ #define ICV_CMP_SIZE 8 #define CCM_CONFIG_BUF_SIZE (AES_BLOCK_SIZE * 3) -#define MAX_MAC_SIZE MAX(SHA256_DIGEST_SIZE, AES_BLOCK_SIZE) +#define MAX_MAC_SIZE SHA256_DIGEST_SIZE /* defines for AES GCM configuration buffer */ #define GCM_BLOCK_LEN_SIZE 8 @@ -74,17 +74,22 @@ struct aead_req_ctx { } gcm_len_block; u8 ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned; - unsigned int hw_iv_size ____cacheline_aligned; /*HW actual size input*/ - u8 backup_mac[MAX_MAC_SIZE]; /*used to prevent cache coherence problem*/ + /* HW actual size input */ + unsigned int hw_iv_size ____cacheline_aligned; + /* used to prevent cache coherence problem */ + u8 backup_mac[MAX_MAC_SIZE]; u8 *backup_iv; /*store iv for generated IV flow*/ u8 *backup_giv; /*store iv for rfc3686(ctr) flow*/ dma_addr_t mac_buf_dma_addr; /* internal ICV DMA buffer */ - dma_addr_t ccm_iv0_dma_addr; /* buffer for internal ccm configurations */ + /* buffer for internal ccm configurations */ + dma_addr_t ccm_iv0_dma_addr; dma_addr_t icv_dma_addr; /* Phys. address of ICV */ //used in gcm - dma_addr_t gcm_iv_inc1_dma_addr; /* buffer for internal gcm configurations */ - dma_addr_t gcm_iv_inc2_dma_addr; /* buffer for internal gcm configurations */ + /* buffer for internal gcm configurations */ + dma_addr_t gcm_iv_inc1_dma_addr; + /* buffer for internal gcm configurations */ + dma_addr_t gcm_iv_inc2_dma_addr; dma_addr_t hkey_dma_addr; /* Phys. address of hkey */ dma_addr_t gcm_block_len_dma_addr; /* Phys. address of gcm block len */ bool is_gcm4543; @@ -111,7 +116,7 @@ struct aead_req_ctx { bool plaintext_authenticate_only; //for gcm_rfc4543 }; -int ssi_aead_alloc(struct ssi_drvdata *drvdata); -int ssi_aead_free(struct ssi_drvdata *drvdata); +int cc_aead_alloc(struct ssi_drvdata *drvdata); +int cc_aead_free(struct ssi_drvdata *drvdata); #endif /*__SSI_AEAD_H__*/ diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 1f8a225530a8..bac9d12126d2 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -33,11 +33,6 @@ #include "ssi_hash.h" #include "ssi_aead.h" -#define GET_DMA_BUFFER_TYPE(buff_type) ( \ - ((buff_type) == SSI_DMA_BUF_NULL) ? "BUF_NULL" : \ - ((buff_type) == SSI_DMA_BUF_DLLI) ? "BUF_DLLI" : \ - ((buff_type) == SSI_DMA_BUF_MLLI) ? "BUF_MLLI" : "BUF_INVALID") - enum dma_buffer_type { DMA_NULL_TYPE = -1, DMA_SGL_TYPE = 1, @@ -64,25 +59,61 @@ struct buffer_array { u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI]; }; +static inline char *cc_dma_buf_type(enum ssi_req_dma_buf_type type) +{ + switch (type) { + case SSI_DMA_BUF_NULL: + return "BUF_NULL"; + case SSI_DMA_BUF_DLLI: + return "BUF_DLLI"; + case SSI_DMA_BUF_MLLI: + return "BUF_MLLI"; + default: + return "BUF_INVALID"; + } +} + /** - * ssi_buffer_mgr_get_sgl_nents() - Get scatterlist number of entries. + * cc_copy_mac() - Copy MAC to temporary location + * + * @dev: device object + * @req: aead request object + * @dir: [IN] copy from/to sgl + */ +static void cc_copy_mac(struct device *dev, struct aead_request *req, + enum ssi_sg_cpy_direct dir) +{ + struct aead_req_ctx *areq_ctx = aead_request_ctx(req); + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + u32 skip = req->assoclen + req->cryptlen; + + if (areq_ctx->is_gcm4543) + skip += crypto_aead_ivsize(tfm); + + cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src, + (skip - areq_ctx->req_authsize), skip, dir); +} + +/** + * cc_get_sgl_nents() - Get scatterlist number of entries. * * @sg_list: SG list * @nbytes: [IN] Total SGL data bytes. * @lbytes: [OUT] Returns the amount of bytes at the last entry */ -static unsigned int ssi_buffer_mgr_get_sgl_nents( +static unsigned int cc_get_sgl_nents( struct device *dev, struct scatterlist *sg_list, unsigned int nbytes, u32 *lbytes, bool *is_chained) { unsigned int nents = 0; - while (nbytes != 0) { - if (sg_list->length != 0) { + while (nbytes) { + if (sg_list->length) { nents++; /* get the number of bytes in the last entry */ *lbytes = nbytes; - nbytes -= (sg_list->length > nbytes) ? nbytes : sg_list->length; + nbytes -= (sg_list->length > nbytes) ? + nbytes : sg_list->length; sg_list = sg_next(sg_list); } else { sg_list = (struct scatterlist *)sg_page(sg_list); @@ -95,11 +126,11 @@ static unsigned int ssi_buffer_mgr_get_sgl_nents( } /** - * ssi_buffer_mgr_zero_sgl() - Zero scatter scatter list data. + * cc_zero_sgl() - Zero scatter scatter list data. * * @sgl: */ -void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len) +void cc_zero_sgl(struct scatterlist *sgl, u32 data_len) { struct scatterlist *current_sg = sgl; int sg_index = 0; @@ -116,7 +147,7 @@ void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len) } /** - * ssi_buffer_mgr_copy_scatterlist_portion() - Copy scatter list data, + * cc_copy_sg_portion() - Copy scatter list data, * from to_skip to end, to dest and vice versa * * @dest: @@ -125,19 +156,19 @@ void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len) * @end: * @direct: */ -void ssi_buffer_mgr_copy_scatterlist_portion( +void cc_copy_sg_portion( struct device *dev, u8 *dest, struct scatterlist *sg, u32 to_skip, u32 end, enum ssi_sg_cpy_direct direct) { u32 nents, lbytes; - nents = ssi_buffer_mgr_get_sgl_nents(dev, sg, end, &lbytes, NULL); + nents = cc_get_sgl_nents(dev, sg, end, &lbytes, NULL); sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip, (direct == SSI_SG_TO_BUF)); } -static inline int ssi_buffer_mgr_render_buff_to_mlli( +static int cc_render_buff_to_mlli( struct device *dev, dma_addr_t buff_dma, u32 buff_size, u32 *curr_nents, u32 **mlli_entry_pp) { @@ -173,7 +204,7 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli( return 0; } -static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( +static int cc_render_sg_to_mlli( struct device *dev, struct scatterlist *sgl, u32 sgl_data_len, u32 sgl_offset, u32 *curr_nents, u32 **mlli_entry_pp) @@ -182,17 +213,17 @@ static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( u32 *mlli_entry_p = *mlli_entry_pp; s32 rc = 0; - for ( ; (curr_sgl) && (sgl_data_len != 0); + for ( ; (curr_sgl && sgl_data_len); curr_sgl = sg_next(curr_sgl)) { u32 entry_data_len = (sgl_data_len > sg_dma_len(curr_sgl) - sgl_offset) ? sg_dma_len(curr_sgl) - sgl_offset : sgl_data_len; sgl_data_len -= entry_data_len; - rc = ssi_buffer_mgr_render_buff_to_mlli( - dev, sg_dma_address(curr_sgl) + sgl_offset, - entry_data_len, curr_nents, &mlli_entry_p); - if (rc != 0) + rc = cc_render_buff_to_mlli(dev, sg_dma_address(curr_sgl) + + sgl_offset, entry_data_len, + curr_nents, &mlli_entry_p); + if (rc) return rc; sgl_offset = 0; @@ -201,7 +232,7 @@ static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( return 0; } -static int ssi_buffer_mgr_generate_mlli( +static int cc_generate_mlli( struct device *dev, struct buffer_array *sg_data, struct mlli_params *mlli_params) @@ -216,7 +247,7 @@ static int ssi_buffer_mgr_generate_mlli( mlli_params->mlli_virt_addr = dma_pool_alloc( mlli_params->curr_pool, GFP_KERNEL, &mlli_params->mlli_dma_addr); - if (unlikely(!mlli_params->mlli_virt_addr)) { + if (!mlli_params->mlli_virt_addr) { dev_err(dev, "dma_pool_alloc() failed\n"); rc = -ENOMEM; goto build_mlli_exit; @@ -225,17 +256,19 @@ static int ssi_buffer_mgr_generate_mlli( mlli_p = (u32 *)mlli_params->mlli_virt_addr; /* go over all SG's and link it to one MLLI table */ for (i = 0; i < sg_data->num_of_buffers; i++) { + union buffer_array_entry *entry = &sg_data->entry[i]; + u32 tot_len = sg_data->total_data_len[i]; + u32 offset = sg_data->offset[i]; + if (sg_data->type[i] == DMA_SGL_TYPE) - rc = ssi_buffer_mgr_render_scatterlist_to_mlli( - dev, sg_data->entry[i].sgl, - sg_data->total_data_len[i], sg_data->offset[i], - &total_nents, &mlli_p); + rc = cc_render_sg_to_mlli(dev, entry->sgl, tot_len, + offset, &total_nents, + &mlli_p); else /*DMA_BUFF_TYPE*/ - rc = ssi_buffer_mgr_render_buff_to_mlli( - dev, sg_data->entry[i].buffer_dma, - sg_data->total_data_len[i], &total_nents, - &mlli_p); - if (rc != 0) + rc = cc_render_buff_to_mlli(dev, entry->buffer_dma, + tot_len, &total_nents, + &mlli_p); + if (rc) return rc; /* set last bit in the current table */ @@ -260,7 +293,7 @@ build_mlli_exit: return rc; } -static inline void ssi_buffer_mgr_add_buffer_entry( +static void cc_add_buffer_entry( struct device *dev, struct buffer_array *sgl_data, dma_addr_t buffer_dma, unsigned int buffer_len, bool is_last_entry, u32 *mlli_nents) @@ -281,7 +314,7 @@ static inline void ssi_buffer_mgr_add_buffer_entry( sgl_data->num_of_buffers++; } -static inline void ssi_buffer_mgr_add_scatterlist_entry( +static void cc_add_sg_entry( struct device *dev, struct buffer_array *sgl_data, unsigned int nents, @@ -308,8 +341,8 @@ static inline void ssi_buffer_mgr_add_scatterlist_entry( } static int -ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents, - enum dma_data_direction direction) +cc_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents, + enum dma_data_direction direction) { u32 i, j; struct scatterlist *l_sg = sg; @@ -317,7 +350,7 @@ ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents, for (i = 0; i < nents; i++) { if (!l_sg) break; - if (unlikely(dma_map_sg(dev, l_sg, 1, direction) != 1)) { + if (dma_map_sg(dev, l_sg, 1, direction) != 1) { dev_err(dev, "dma_map_page() sg buffer failed\n"); goto err; } @@ -336,7 +369,7 @@ err: return 0; } -static int ssi_buffer_mgr_map_scatterlist( +static int cc_map_sg( struct device *dev, struct scatterlist *sg, unsigned int nbytes, int direction, u32 *nents, u32 max_sg_nents, @@ -346,7 +379,7 @@ static int ssi_buffer_mgr_map_scatterlist( if (sg_is_last(sg)) { /* One entry only case -set to DLLI */ - if (unlikely(dma_map_sg(dev, sg, 1, direction) != 1)) { + if (dma_map_sg(dev, sg, 1, direction) != 1) { dev_err(dev, "dma_map_sg() single buffer failed\n"); return -ENOMEM; } @@ -357,8 +390,8 @@ static int ssi_buffer_mgr_map_scatterlist( *nents = 1; *mapped_nents = 1; } else { /*sg_is_last*/ - *nents = ssi_buffer_mgr_get_sgl_nents(dev, sg, nbytes, lbytes, - &is_chained); + *nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes, + &is_chained); if (*nents > max_sg_nents) { *nents = 0; dev_err(dev, "Too many fragments. current %d max %d\n", @@ -370,7 +403,7 @@ static int ssi_buffer_mgr_map_scatterlist( * be changed from the original sgl nents */ *mapped_nents = dma_map_sg(dev, sg, *nents, direction); - if (unlikely(*mapped_nents == 0)) { + if (*mapped_nents == 0) { *nents = 0; dev_err(dev, "dma_map_sg() sg buffer failed\n"); return -ENOMEM; @@ -379,11 +412,9 @@ static int ssi_buffer_mgr_map_scatterlist( /*In this case the driver maps entry by entry so it * must have the same nents before and after map */ - *mapped_nents = ssi_buffer_mgr_dma_map_sg(dev, - sg, - *nents, - direction); - if (unlikely(*mapped_nents != *nents)) { + *mapped_nents = cc_dma_map_sg(dev, sg, *nents, + direction); + if (*mapped_nents != *nents) { *nents = *mapped_nents; dev_err(dev, "dma_map_sg() sg buffer failed\n"); return -ENOMEM; @@ -394,7 +425,7 @@ static int ssi_buffer_mgr_map_scatterlist( return 0; } -static inline int +static int ssi_aead_handle_config_buf(struct device *dev, struct aead_req_ctx *areq_ctx, u8 *config_data, @@ -403,9 +434,9 @@ ssi_aead_handle_config_buf(struct device *dev, { dev_dbg(dev, " handle additional data config set to DLLI\n"); /* create sg for the current buffer */ - sg_init_one(&areq_ctx->ccm_adata_sg, config_data, AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size); - if (unlikely(dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1, - DMA_TO_DEVICE) != 1)) { + sg_init_one(&areq_ctx->ccm_adata_sg, config_data, + AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size); + if (dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE) != 1) { dev_err(dev, "dma_map_sg() config buffer failed\n"); return -ENOMEM; } @@ -416,25 +447,22 @@ ssi_aead_handle_config_buf(struct device *dev, areq_ctx->ccm_adata_sg.offset, areq_ctx->ccm_adata_sg.length); /* prepare for case of MLLI */ if (assoclen > 0) { - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, 1, - &areq_ctx->ccm_adata_sg, - (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size), - 0, false, NULL); + cc_add_sg_entry(dev, sg_data, 1, &areq_ctx->ccm_adata_sg, + (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size), + 0, false, NULL); } return 0; } -static inline int ssi_ahash_handle_curr_buf(struct device *dev, - struct ahash_req_ctx *areq_ctx, - u8 *curr_buff, - u32 curr_buff_cnt, - struct buffer_array *sg_data) +static int ssi_ahash_handle_curr_buf(struct device *dev, + struct ahash_req_ctx *areq_ctx, + u8 *curr_buff, u32 curr_buff_cnt, + struct buffer_array *sg_data) { dev_dbg(dev, " handle curr buff %x set to DLLI\n", curr_buff_cnt); /* create sg for the current buffer */ sg_init_one(areq_ctx->buff_sg, curr_buff, curr_buff_cnt); - if (unlikely(dma_map_sg(dev, areq_ctx->buff_sg, 1, - DMA_TO_DEVICE) != 1)) { + if (dma_map_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE) != 1) { dev_err(dev, "dma_map_sg() src buffer failed\n"); return -ENOMEM; } @@ -446,12 +474,12 @@ static inline int ssi_ahash_handle_curr_buf(struct device *dev, areq_ctx->curr_sg = areq_ctx->buff_sg; areq_ctx->in_nents = 0; /* prepare for case of MLLI */ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, 1, areq_ctx->buff_sg, - curr_buff_cnt, 0, false, NULL); + cc_add_sg_entry(dev, sg_data, 1, areq_ctx->buff_sg, curr_buff_cnt, 0, + false, NULL); return 0; } -void ssi_buffer_mgr_unmap_blkcipher_request( +void cc_unmap_blkcipher_request( struct device *dev, void *ctx, unsigned int ivsize, @@ -460,7 +488,7 @@ void ssi_buffer_mgr_unmap_blkcipher_request( { struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx; - if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) { + if (req_ctx->gen_ctx.iv_dma_addr) { dev_dbg(dev, "Unmapped iv: iv_dma_addr=%pad iv_size=%u\n", &req_ctx->gen_ctx.iv_dma_addr, ivsize); dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr, @@ -484,7 +512,7 @@ void ssi_buffer_mgr_unmap_blkcipher_request( } } -int ssi_buffer_mgr_map_blkcipher_request( +int cc_map_blkcipher_request( struct ssi_drvdata *drvdata, void *ctx, unsigned int ivsize, @@ -507,15 +535,14 @@ int ssi_buffer_mgr_map_blkcipher_request( sg_data.num_of_buffers = 0; /* Map IV buffer */ - if (likely(ivsize != 0)) { + if (ivsize) { dump_byte_array("iv", (u8 *)info, ivsize); req_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, (void *)info, ivsize, req_ctx->is_giv ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, - req_ctx->gen_ctx.iv_dma_addr))) { + if (dma_mapping_error(dev, req_ctx->gen_ctx.iv_dma_addr)) { dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n", ivsize, info); return -ENOMEM; @@ -527,74 +554,62 @@ int ssi_buffer_mgr_map_blkcipher_request( } /* Map the src SGL */ - rc = ssi_buffer_mgr_map_scatterlist(dev, src, - nbytes, DMA_BIDIRECTIONAL, - &req_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, - &mapped_nents); - if (unlikely(rc != 0)) { + rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); + if (rc) { rc = -ENOMEM; goto ablkcipher_exit; } if (mapped_nents > 1) req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI; - if (unlikely(src == dst)) { + if (src == dst) { /* Handle inplace operation */ - if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { + if (req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI) { req_ctx->out_nents = 0; - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - req_ctx->in_nents, - src, nbytes, 0, - true, - &req_ctx->in_mlli_nents); + cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src, + nbytes, 0, true, + &req_ctx->in_mlli_nents); } } else { /* Map the dst sg */ - if (unlikely(ssi_buffer_mgr_map_scatterlist( - dev, dst, nbytes, - DMA_BIDIRECTIONAL, &req_ctx->out_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, - &mapped_nents))){ + if (cc_map_sg(dev, dst, nbytes, DMA_BIDIRECTIONAL, + &req_ctx->out_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, + &dummy, &mapped_nents)) { rc = -ENOMEM; goto ablkcipher_exit; } if (mapped_nents > 1) req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI; - if (unlikely((req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI))) { - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - req_ctx->in_nents, - src, nbytes, 0, - true, - &req_ctx->in_mlli_nents); - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - req_ctx->out_nents, - dst, nbytes, 0, - true, - &req_ctx->out_mlli_nents); + if (req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI) { + cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src, + nbytes, 0, true, + &req_ctx->in_mlli_nents); + cc_add_sg_entry(dev, &sg_data, req_ctx->out_nents, dst, + nbytes, 0, true, + &req_ctx->out_mlli_nents); } } - if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { + if (req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; - rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params); - if (unlikely(rc != 0)) + rc = cc_generate_mlli(dev, &sg_data, mlli_params); + if (rc) goto ablkcipher_exit; } dev_dbg(dev, "areq_ctx->dma_buf_type = %s\n", - GET_DMA_BUFFER_TYPE(req_ctx->dma_buf_type)); + cc_dma_buf_type(req_ctx->dma_buf_type)); return 0; ablkcipher_exit: - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); return rc; } -void ssi_buffer_mgr_unmap_aead_request( - struct device *dev, struct aead_request *req) +void cc_unmap_aead_request(struct device *dev, struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); unsigned int hw_iv_size = areq_ctx->hw_iv_size; @@ -604,29 +619,29 @@ void ssi_buffer_mgr_unmap_aead_request( bool chained; u32 size_to_unmap = 0; - if (areq_ctx->mac_buf_dma_addr != 0) { + if (areq_ctx->mac_buf_dma_addr) { dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr, MAX_MAC_SIZE, DMA_BIDIRECTIONAL); } #if SSI_CC_HAS_AES_GCM if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) { - if (areq_ctx->hkey_dma_addr != 0) { + if (areq_ctx->hkey_dma_addr) { dma_unmap_single(dev, areq_ctx->hkey_dma_addr, AES_BLOCK_SIZE, DMA_BIDIRECTIONAL); } - if (areq_ctx->gcm_block_len_dma_addr != 0) { + if (areq_ctx->gcm_block_len_dma_addr) { dma_unmap_single(dev, areq_ctx->gcm_block_len_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } - if (areq_ctx->gcm_iv_inc1_dma_addr != 0) { + if (areq_ctx->gcm_iv_inc1_dma_addr) { dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } - if (areq_ctx->gcm_iv_inc2_dma_addr != 0) { + if (areq_ctx->gcm_iv_inc2_dma_addr) { dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } @@ -634,14 +649,14 @@ void ssi_buffer_mgr_unmap_aead_request( #endif if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { - if (areq_ctx->ccm_iv0_dma_addr != 0) { + if (areq_ctx->ccm_iv0_dma_addr) { dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE); } - if (areq_ctx->gen_ctx.iv_dma_addr != 0) { + if (areq_ctx->gen_ctx.iv_dma_addr) { dma_unmap_single(dev, areq_ctx->gen_ctx.iv_dma_addr, hw_iv_size, DMA_BIDIRECTIONAL); } @@ -668,37 +683,29 @@ void ssi_buffer_mgr_unmap_aead_request( size_to_unmap += crypto_aead_ivsize(tfm); dma_unmap_sg(dev, req->src, - ssi_buffer_mgr_get_sgl_nents(dev, req->src, size_to_unmap, - &dummy, &chained), + cc_get_sgl_nents(dev, req->src, size_to_unmap, + &dummy, &chained), DMA_BIDIRECTIONAL); - if (unlikely(req->src != req->dst)) { + if (req->src != req->dst) { dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n", sg_virt(req->dst)); dma_unmap_sg(dev, req->dst, - ssi_buffer_mgr_get_sgl_nents(dev, req->dst, - size_to_unmap, - &dummy, &chained), + cc_get_sgl_nents(dev, req->dst, size_to_unmap, + &dummy, &chained), DMA_BIDIRECTIONAL); } if (drvdata->coherent && - (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && - likely(req->src == req->dst)) { - u32 size_to_skip = req->assoclen; - - if (areq_ctx->is_gcm4543) - size_to_skip += crypto_aead_ivsize(tfm); - - /* copy mac to a temporary location to deal with possible - * data memory overriding that caused by cache coherence problem. + areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && + req->src == req->dst) { + /* copy back mac from temporary location to deal with possible + * data memory overriding that caused by cache coherence + * problem. */ - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, req->src, - size_to_skip + req->cryptlen - areq_ctx->req_authsize, - size_to_skip + req->cryptlen, SSI_SG_FROM_BUF); + cc_copy_mac(dev, req, SSI_SG_FROM_BUF); } } -static inline int ssi_buffer_mgr_get_aead_icv_nents( +static int cc_get_aead_icv_nents( struct device *dev, struct scatterlist *sgl, unsigned int sgl_nents, @@ -707,7 +714,9 @@ static inline int ssi_buffer_mgr_get_aead_icv_nents( bool *is_icv_fragmented) { unsigned int icv_max_size = 0; - unsigned int icv_required_size = authsize > last_entry_data_size ? (authsize - last_entry_data_size) : authsize; + unsigned int icv_required_size = authsize > last_entry_data_size ? + (authsize - last_entry_data_size) : + authsize; unsigned int nents; unsigned int i; @@ -726,10 +735,12 @@ static inline int ssi_buffer_mgr_get_aead_icv_nents( icv_max_size = sgl->length; if (last_entry_data_size > authsize) { - nents = 0; /* ICV attached to data in last entry (not fragmented!) */ + /* ICV attached to data in last entry (not fragmented!) */ + nents = 0; *is_icv_fragmented = false; } else if (last_entry_data_size == authsize) { - nents = 1; /* ICV placed in whole last entry (not fragmented!) */ + /* ICV placed in whole last entry (not fragmented!) */ + nents = 1; *is_icv_fragmented = false; } else if (icv_max_size > icv_required_size) { nents = 1; @@ -748,7 +759,7 @@ static inline int ssi_buffer_mgr_get_aead_icv_nents( return nents; } -static inline int ssi_buffer_mgr_aead_chain_iv( +static int cc_aead_chain_iv( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -759,14 +770,15 @@ static inline int ssi_buffer_mgr_aead_chain_iv( struct device *dev = drvdata_to_dev(drvdata); int rc = 0; - if (unlikely(!req->iv)) { + if (!req->iv) { areq_ctx->gen_ctx.iv_dma_addr = 0; goto chain_iv_exit; } - areq_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, req->iv, hw_iv_size, + areq_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, req->iv, + hw_iv_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr))) { + if (dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr)) { dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n", hw_iv_size, req->iv); rc = -ENOMEM; @@ -775,16 +787,16 @@ static inline int ssi_buffer_mgr_aead_chain_iv( dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n", hw_iv_size, req->iv, &areq_ctx->gen_ctx.iv_dma_addr); - if (do_chain && areq_ctx->plaintext_authenticate_only) { // TODO: what about CTR?? ask Ron + // TODO: what about CTR?? ask Ron + if (do_chain && areq_ctx->plaintext_authenticate_only) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm); unsigned int iv_ofs = GCM_BLOCK_RFC4_IV_OFFSET; /* Chain to given list */ - ssi_buffer_mgr_add_buffer_entry( - dev, sg_data, - areq_ctx->gen_ctx.iv_dma_addr + iv_ofs, - iv_size_to_authenc, is_last, - &areq_ctx->assoc.mlli_nents); + cc_add_buffer_entry(dev, sg_data, + (areq_ctx->gen_ctx.iv_dma_addr + iv_ofs), + iv_size_to_authenc, is_last, + &areq_ctx->assoc.mlli_nents); areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; } @@ -792,7 +804,7 @@ chain_iv_exit: return rc; } -static inline int ssi_buffer_mgr_aead_chain_assoc( +static int cc_aead_chain_assoc( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -815,12 +827,12 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( goto chain_assoc_exit; } - if (unlikely(req->assoclen == 0)) { + if (req->assoclen == 0) { areq_ctx->assoc_buff_type = SSI_DMA_BUF_NULL; areq_ctx->assoc.nents = 0; areq_ctx->assoc.mlli_nents = 0; dev_dbg(dev, "Chain assoc of length 0: buff_type=%s nents=%u\n", - GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), + cc_dma_buf_type(areq_ctx->assoc_buff_type), areq_ctx->assoc.nents); goto chain_assoc_exit; } @@ -828,12 +840,15 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( //iterate over the sgl to see how many entries are for associated data //it is assumed that if we reach here , the sgl is already mapped sg_index = current_sg->length; - if (sg_index > size_of_assoc) { //the first entry in the scatter list contains all the associated data + //the first entry in the scatter list contains all the associated data + if (sg_index > size_of_assoc) { mapped_nents++; } else { while (sg_index <= size_of_assoc) { current_sg = sg_next(current_sg); - //if have reached the end of the sgl, then this is unexpected + /* if have reached the end of the sgl, then this is + * unexpected + */ if (!current_sg) { dev_err(dev, "reached end of sg list. unexpected\n"); return -EINVAL; @@ -842,7 +857,7 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( mapped_nents++; } } - if (unlikely(mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)) { + if (mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) { dev_err(dev, "Too many fragments. current %d max %d\n", mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES); return -ENOMEM; @@ -853,8 +868,7 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( * ccm header configurations */ if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { - if (unlikely((mapped_nents + 1) > - LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)) { + if ((mapped_nents + 1) > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) { dev_err(dev, "CCM case.Too many fragments. Current %d max %d\n", (areq_ctx->assoc.nents + 1), LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES); @@ -863,21 +877,18 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( } } - if (likely(mapped_nents == 1) && - (areq_ctx->ccm_hdr_size == ccm_header_size_null)) + if (mapped_nents == 1 && areq_ctx->ccm_hdr_size == ccm_header_size_null) areq_ctx->assoc_buff_type = SSI_DMA_BUF_DLLI; else areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; - if (unlikely((do_chain) || - (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI))) { + if (do_chain || areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) { dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n", - GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), + cc_dma_buf_type(areq_ctx->assoc_buff_type), areq_ctx->assoc.nents); - ssi_buffer_mgr_add_scatterlist_entry( - dev, sg_data, areq_ctx->assoc.nents, - req->src, req->assoclen, 0, is_last, - &areq_ctx->assoc.mlli_nents); + cc_add_sg_entry(dev, sg_data, areq_ctx->assoc.nents, req->src, + req->assoclen, 0, is_last, + &areq_ctx->assoc.mlli_nents); areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; } @@ -885,7 +896,7 @@ chain_assoc_exit: return rc; } -static inline void ssi_buffer_mgr_prepare_aead_data_dlli( +static void cc_prepare_aead_data_dlli( struct aead_request *req, u32 *src_last_bytes, u32 *dst_last_bytes) { @@ -894,7 +905,7 @@ static inline void ssi_buffer_mgr_prepare_aead_data_dlli( unsigned int authsize = areq_ctx->req_authsize; areq_ctx->is_icv_fragmented = false; - if (likely(req->src == req->dst)) { + if (req->src == req->dst) { /*INPLACE*/ areq_ctx->icv_dma_addr = sg_dma_address( areq_ctx->src_sgl) + @@ -921,7 +932,7 @@ static inline void ssi_buffer_mgr_prepare_aead_data_dlli( } } -static inline int ssi_buffer_mgr_prepare_aead_data_mlli( +static int cc_prepare_aead_data_mlli( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -932,59 +943,43 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type; unsigned int authsize = areq_ctx->req_authsize; int rc = 0, icv_nents; - struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct device *dev = drvdata_to_dev(drvdata); - if (likely(req->src == req->dst)) { + if (req->src == req->dst) { /*INPLACE*/ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->src.nents, - areq_ctx->src_sgl, - areq_ctx->cryptlen, - areq_ctx->src_offset, - is_last_table, - &areq_ctx->src.mlli_nents); - - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev, - areq_ctx->src_sgl, - areq_ctx->src.nents, - authsize, - *src_last_bytes, - &areq_ctx->is_icv_fragmented); - if (unlikely(icv_nents < 0)) { + cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents, + areq_ctx->src_sgl, areq_ctx->cryptlen, + areq_ctx->src_offset, is_last_table, + &areq_ctx->src.mlli_nents); + + icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->src_sgl, + areq_ctx->src.nents, + authsize, *src_last_bytes, + &areq_ctx->is_icv_fragmented); + if (icv_nents < 0) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; } - if (unlikely(areq_ctx->is_icv_fragmented)) { + if (areq_ctx->is_icv_fragmented) { /* Backup happens only when ICV is fragmented, ICV - * verification is made by CPU compare in order to simplify - * MAC verification upon request completion + * verification is made by CPU compare in order to + * simplify MAC verification upon request completion */ if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { - if (!drvdata->coherent) { /* In coherent platforms (e.g. ACP) * already copying ICV for any * INPLACE-DECRYPT operation, hence * we must neglect this code. */ - u32 skip = req->assoclen; - - if (areq_ctx->is_gcm4543) - skip += crypto_aead_ivsize(tfm); - - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, - req->src, - (skip + req->cryptlen - - areq_ctx->req_authsize), - skip + req->cryptlen, - SSI_SG_TO_BUF); - } + if (!drvdata->coherent) + cc_copy_mac(dev, req, SSI_SG_TO_BUF); + areq_ctx->icv_virt_addr = areq_ctx->backup_mac; } else { areq_ctx->icv_virt_addr = areq_ctx->mac_buf; - areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr; + areq_ctx->icv_dma_addr = + areq_ctx->mac_buf_dma_addr; } } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ @@ -998,47 +993,32 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { /*NON-INPLACE and DECRYPT*/ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->src.nents, - areq_ctx->src_sgl, - areq_ctx->cryptlen, - areq_ctx->src_offset, - is_last_table, - &areq_ctx->src.mlli_nents); - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->dst.nents, - areq_ctx->dst_sgl, - areq_ctx->cryptlen, - areq_ctx->dst_offset, - is_last_table, - &areq_ctx->dst.mlli_nents); - - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev, - areq_ctx->src_sgl, - areq_ctx->src.nents, - authsize, - *src_last_bytes, - &areq_ctx->is_icv_fragmented); - if (unlikely(icv_nents < 0)) { + cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents, + areq_ctx->src_sgl, areq_ctx->cryptlen, + areq_ctx->src_offset, is_last_table, + &areq_ctx->src.mlli_nents); + cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents, + areq_ctx->dst_sgl, areq_ctx->cryptlen, + areq_ctx->dst_offset, is_last_table, + &areq_ctx->dst.mlli_nents); + + icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->src_sgl, + areq_ctx->src.nents, + authsize, *src_last_bytes, + &areq_ctx->is_icv_fragmented); + if (icv_nents < 0) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; } - if (unlikely(areq_ctx->is_icv_fragmented)) { - /* Backup happens only when ICV is fragmented, ICV - * verification is made by CPU compare in order to simplify - * MAC verification upon request completion - */ - u32 size_to_skip = req->assoclen; - - if (areq_ctx->is_gcm4543) - size_to_skip += crypto_aead_ivsize(tfm); - - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, req->src, - size_to_skip + req->cryptlen - areq_ctx->req_authsize, - size_to_skip + req->cryptlen, SSI_SG_TO_BUF); + /* Backup happens only when ICV is fragmented, ICV + * verification is made by CPU compare in order to simplify + * MAC verification upon request completion + */ + if (areq_ctx->is_icv_fragmented) { + cc_copy_mac(dev, req, SSI_SG_TO_BUF); areq_ctx->icv_virt_addr = areq_ctx->backup_mac; + } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ areq_ctx->icv_dma_addr = sg_dma_address( @@ -1051,33 +1031,25 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else { /*NON-INPLACE and ENCRYPT*/ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->dst.nents, - areq_ctx->dst_sgl, - areq_ctx->cryptlen, - areq_ctx->dst_offset, - is_last_table, - &areq_ctx->dst.mlli_nents); - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->src.nents, - areq_ctx->src_sgl, - areq_ctx->cryptlen, - areq_ctx->src_offset, - is_last_table, - &areq_ctx->src.mlli_nents); - - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev, - areq_ctx->dst_sgl, - areq_ctx->dst.nents, - authsize, - *dst_last_bytes, - &areq_ctx->is_icv_fragmented); - if (unlikely(icv_nents < 0)) { + cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents, + areq_ctx->dst_sgl, areq_ctx->cryptlen, + areq_ctx->dst_offset, is_last_table, + &areq_ctx->dst.mlli_nents); + cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents, + areq_ctx->src_sgl, areq_ctx->cryptlen, + areq_ctx->src_offset, is_last_table, + &areq_ctx->src.mlli_nents); + + icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->dst_sgl, + areq_ctx->dst.nents, + authsize, *dst_last_bytes, + &areq_ctx->is_icv_fragmented); + if (icv_nents < 0) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; } - if (likely(!areq_ctx->is_icv_fragmented)) { + if (!areq_ctx->is_icv_fragmented) { /* Contig. ICV */ areq_ctx->icv_dma_addr = sg_dma_address( &areq_ctx->dst_sgl[areq_ctx->dst.nents - 1]) + @@ -1095,7 +1067,7 @@ prepare_data_mlli_exit: return rc; } -static inline int ssi_buffer_mgr_aead_chain_data( +static int cc_aead_chain_data( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -1109,7 +1081,8 @@ static inline int ssi_buffer_mgr_aead_chain_data( int rc = 0; u32 src_mapped_nents = 0, dst_mapped_nents = 0; u32 offset = 0; - unsigned int size_for_map = req->assoclen + req->cryptlen; /*non-inplace mode*/ + /* non-inplace mode */ + unsigned int size_for_map = req->assoclen + req->cryptlen; struct crypto_aead *tfm = crypto_aead_reqtfm(req); u32 sg_index = 0; bool chained = false; @@ -1130,11 +1103,10 @@ static inline int ssi_buffer_mgr_aead_chain_data( if (is_gcm4543) size_for_map += crypto_aead_ivsize(tfm); - size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0; - src_mapped_nents = ssi_buffer_mgr_get_sgl_nents(dev, req->src, - size_for_map, - &src_last_bytes, - &chained); + size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? + authsize : 0; + src_mapped_nents = cc_get_sgl_nents(dev, req->src, size_for_map, + &src_last_bytes, &chained); sg_index = areq_ctx->src_sgl->length; //check where the data starts while (sg_index <= size_to_skip) { @@ -1148,7 +1120,7 @@ static inline int ssi_buffer_mgr_aead_chain_data( sg_index += areq_ctx->src_sgl->length; src_mapped_nents--; } - if (unlikely(src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { + if (src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) { dev_err(dev, "Too many fragments. current %d max %d\n", src_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES); return -ENOMEM; @@ -1160,26 +1132,23 @@ static inline int ssi_buffer_mgr_aead_chain_data( if (req->src != req->dst) { size_for_map = req->assoclen + req->cryptlen; - size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0; + size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? + authsize : 0; if (is_gcm4543) size_for_map += crypto_aead_ivsize(tfm); - rc = ssi_buffer_mgr_map_scatterlist(dev, req->dst, size_for_map, - DMA_BIDIRECTIONAL, - &areq_ctx->dst.nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dst_last_bytes, - &dst_mapped_nents); - if (unlikely(rc != 0)) { + rc = cc_map_sg(dev, req->dst, size_for_map, DMA_BIDIRECTIONAL, + &areq_ctx->dst.nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes, + &dst_mapped_nents); + if (rc) { rc = -ENOMEM; goto chain_data_exit; } } - dst_mapped_nents = ssi_buffer_mgr_get_sgl_nents(dev, req->dst, - size_for_map, - &dst_last_bytes, - &chained); + dst_mapped_nents = cc_get_sgl_nents(dev, req->dst, size_for_map, + &dst_last_bytes, &chained); sg_index = areq_ctx->dst_sgl->length; offset = size_to_skip; @@ -1195,34 +1164,32 @@ static inline int ssi_buffer_mgr_aead_chain_data( sg_index += areq_ctx->dst_sgl->length; dst_mapped_nents--; } - if (unlikely(dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES)) { + if (dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) { dev_err(dev, "Too many fragments. current %d max %d\n", dst_mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES); return -ENOMEM; } areq_ctx->dst.nents = dst_mapped_nents; areq_ctx->dst_offset = offset; - if ((src_mapped_nents > 1) || - (dst_mapped_nents > 1) || + if (src_mapped_nents > 1 || + dst_mapped_nents > 1 || do_chain) { areq_ctx->data_buff_type = SSI_DMA_BUF_MLLI; - rc = ssi_buffer_mgr_prepare_aead_data_mlli(drvdata, req, - sg_data, - &src_last_bytes, - &dst_last_bytes, - is_last_table); + rc = cc_prepare_aead_data_mlli(drvdata, req, sg_data, + &src_last_bytes, + &dst_last_bytes, is_last_table); } else { areq_ctx->data_buff_type = SSI_DMA_BUF_DLLI; - ssi_buffer_mgr_prepare_aead_data_dlli( - req, &src_last_bytes, &dst_last_bytes); + cc_prepare_aead_data_dlli(req, &src_last_bytes, + &dst_last_bytes); } chain_data_exit: return rc; } -static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata, - struct aead_request *req) +static void cc_update_aead_mlli_nents(struct ssi_drvdata *drvdata, + struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); u32 curr_mlli_size = 0; @@ -1272,7 +1239,7 @@ static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata, } } -int ssi_buffer_mgr_map_aead_request( +int cc_map_aead_request( struct ssi_drvdata *drvdata, struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); @@ -1284,7 +1251,7 @@ int ssi_buffer_mgr_map_aead_request( int rc = 0; struct crypto_aead *tfm = crypto_aead_reqtfm(req); bool is_gcm4543 = areq_ctx->is_gcm4543; - + dma_addr_t dma_addr; u32 mapped_nents = 0; u32 dummy = 0; /*used for the assoc data fragments */ u32 size_to_map = 0; @@ -1292,22 +1259,13 @@ int ssi_buffer_mgr_map_aead_request( mlli_params->curr_pool = NULL; sg_data.num_of_buffers = 0; + /* copy mac to a temporary location to deal with possible + * data memory overriding that caused by cache coherence problem. + */ if (drvdata->coherent && - (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && - likely(req->src == req->dst)) { - u32 size_to_skip = req->assoclen; - - if (is_gcm4543) - size_to_skip += crypto_aead_ivsize(tfm); - - /* copy mac to a temporary location to deal with possible - * data memory overriding that caused by cache coherence problem. - */ - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, req->src, - size_to_skip + req->cryptlen - areq_ctx->req_authsize, - size_to_skip + req->cryptlen, SSI_SG_TO_BUF); - } + areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && + req->src == req->dst) + cc_copy_mac(dev, req, SSI_SG_TO_BUF); /* cacluate the size for cipher remove ICV in decrypt*/ areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type == @@ -1315,34 +1273,34 @@ int ssi_buffer_mgr_map_aead_request( req->cryptlen : (req->cryptlen - authsize); - areq_ctx->mac_buf_dma_addr = dma_map_single(dev, areq_ctx->mac_buf, - MAX_MAC_SIZE, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, areq_ctx->mac_buf_dma_addr))) { + dma_addr = dma_map_single(dev, areq_ctx->mac_buf, MAX_MAC_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n", MAX_MAC_SIZE, areq_ctx->mac_buf); rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->mac_buf_dma_addr = dma_addr; if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { - areq_ctx->ccm_iv0_dma_addr = dma_map_single(dev, - (areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET), - AES_BLOCK_SIZE, - DMA_TO_DEVICE); + void *addr = areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET; + + dma_addr = dma_map_single(dev, addr, AES_BLOCK_SIZE, + DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->ccm_iv0_dma_addr))) { + if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n", - AES_BLOCK_SIZE, - (areq_ctx->ccm_config + - CCM_CTR_COUNT_0_OFFSET)); + AES_BLOCK_SIZE, addr); areq_ctx->ccm_iv0_dma_addr = 0; rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->ccm_iv0_dma_addr = dma_addr; + if (ssi_aead_handle_config_buf(dev, areq_ctx, areq_ctx->ccm_config, &sg_data, - req->assoclen) != 0) { + req->assoclen)) { rc = -ENOMEM; goto aead_map_failure; } @@ -1350,53 +1308,49 @@ int ssi_buffer_mgr_map_aead_request( #if SSI_CC_HAS_AES_GCM if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) { - areq_ctx->hkey_dma_addr = dma_map_single(dev, - areq_ctx->hkey, - AES_BLOCK_SIZE, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, areq_ctx->hkey_dma_addr))) { + dma_addr = dma_map_single(dev, areq_ctx->hkey, AES_BLOCK_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, areq_ctx->hkey); rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->hkey_dma_addr = dma_addr; - areq_ctx->gcm_block_len_dma_addr = dma_map_single(dev, - &areq_ctx->gcm_len_block, - AES_BLOCK_SIZE, - DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_block_len_dma_addr))) { + dma_addr = dma_map_single(dev, &areq_ctx->gcm_len_block, + AES_BLOCK_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, &areq_ctx->gcm_len_block); rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->gcm_block_len_dma_addr = dma_addr; - areq_ctx->gcm_iv_inc1_dma_addr = dma_map_single(dev, - areq_ctx->gcm_iv_inc1, - AES_BLOCK_SIZE, - DMA_TO_DEVICE); + dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc1, + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_iv_inc1_dma_addr))) { + if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1)); areq_ctx->gcm_iv_inc1_dma_addr = 0; rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->gcm_iv_inc1_dma_addr = dma_addr; - areq_ctx->gcm_iv_inc2_dma_addr = dma_map_single(dev, - areq_ctx->gcm_iv_inc2, - AES_BLOCK_SIZE, - DMA_TO_DEVICE); + dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc2, + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_iv_inc2_dma_addr))) { + if (dma_mapping_error(dev, dma_addr)) { dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2)); areq_ctx->gcm_iv_inc2_dma_addr = 0; rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->gcm_iv_inc2_dma_addr = dma_addr; } #endif /*SSI_CC_HAS_AES_GCM*/ @@ -1406,29 +1360,31 @@ int ssi_buffer_mgr_map_aead_request( if (is_gcm4543) size_to_map += crypto_aead_ivsize(tfm); - rc = ssi_buffer_mgr_map_scatterlist(dev, req->src, - size_to_map, DMA_BIDIRECTIONAL, &areq_ctx->src.nents, - LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); - if (unlikely(rc != 0)) { + rc = cc_map_sg(dev, req->src, size_to_map, DMA_BIDIRECTIONAL, + &areq_ctx->src.nents, + (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + + LLI_MAX_NUM_OF_DATA_ENTRIES), + &dummy, &mapped_nents); + if (rc) { rc = -ENOMEM; goto aead_map_failure; } - if (likely(areq_ctx->is_single_pass)) { + if (areq_ctx->is_single_pass) { /* * Create MLLI table for: * (1) Assoc. data * (2) Src/Dst SGLs * Note: IV is contg. buffer (not an SGL) */ - rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, true, false); - if (unlikely(rc != 0)) + rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false); + if (rc) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_iv(drvdata, req, &sg_data, true, false); - if (unlikely(rc != 0)) + rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false); + if (rc) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_data(drvdata, req, &sg_data, true, false); - if (unlikely(rc != 0)) + rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false); + if (rc) goto aead_map_failure; } else { /* DOUBLE-PASS flow */ /* @@ -1451,27 +1407,28 @@ int ssi_buffer_mgr_map_aead_request( * (3) MLLI for src * (4) MLLI for dst */ - rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, false, true); - if (unlikely(rc != 0)) + rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true); + if (rc) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_iv(drvdata, req, &sg_data, false, true); - if (unlikely(rc != 0)) + rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true); + if (rc) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_data(drvdata, req, &sg_data, true, true); - if (unlikely(rc != 0)) + rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true); + if (rc) goto aead_map_failure; } - /* Mlli support -start building the MLLI according to the above results */ - if (unlikely( - (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) || - (areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI))) { + /* Mlli support -start building the MLLI according to the above + * results + */ + if (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI || + areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; - rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params); - if (unlikely(rc != 0)) + rc = cc_generate_mlli(dev, &sg_data, mlli_params); + if (rc) goto aead_map_failure; - ssi_buffer_mgr_update_aead_mlli_nents(drvdata, req); + cc_update_aead_mlli_nents(drvdata, req); dev_dbg(dev, "assoc params mn %d\n", areq_ctx->assoc.mlli_nents); dev_dbg(dev, "src params mn %d\n", areq_ctx->src.mlli_nents); @@ -1480,12 +1437,13 @@ int ssi_buffer_mgr_map_aead_request( return 0; aead_map_failure: - ssi_buffer_mgr_unmap_aead_request(dev, req); + cc_unmap_aead_request(dev, req); return rc; } -int ssi_buffer_mgr_map_hash_request_final( - struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update) +int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + bool do_update) { struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; struct device *dev = drvdata_to_dev(drvdata); @@ -1507,31 +1465,28 @@ int ssi_buffer_mgr_map_hash_request_final( sg_data.num_of_buffers = 0; areq_ctx->in_nents = 0; - if (unlikely(nbytes == 0 && *curr_buff_cnt == 0)) { + if (nbytes == 0 && *curr_buff_cnt == 0) { /* nothing to do */ return 0; } /*TODO: copy data in case that buffer is enough for operation */ /* map the previous buffer */ - if (*curr_buff_cnt != 0) { + if (*curr_buff_cnt) { if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff, - *curr_buff_cnt, &sg_data) != 0) { + *curr_buff_cnt, &sg_data)) { return -ENOMEM; } } - if (src && (nbytes > 0) && do_update) { - if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, nbytes, - DMA_TO_DEVICE, - &areq_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dummy, - &mapped_nents))){ + if (src && nbytes > 0 && do_update) { + if (cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE, + &areq_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, + &dummy, &mapped_nents)) { goto unmap_curr_buff; } - if (src && (mapped_nents == 1) - && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) { + if (src && mapped_nents == 1 && + areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist)); areq_ctx->buff_sg->length = nbytes; @@ -1543,36 +1498,33 @@ int ssi_buffer_mgr_map_hash_request_final( } /*build mlli */ - if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) { + if (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; /* add the src data to the sg_data */ - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - areq_ctx->in_nents, - src, nbytes, 0, true, - &areq_ctx->mlli_nents); - if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data, - mlli_params) != 0)) { + cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes, + 0, true, &areq_ctx->mlli_nents); + if (cc_generate_mlli(dev, &sg_data, mlli_params)) goto fail_unmap_din; - } } /* change the buffer index for the unmap function */ areq_ctx->buff_index = (areq_ctx->buff_index ^ 1); dev_dbg(dev, "areq_ctx->data_dma_buf_type = %s\n", - GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type)); + cc_dma_buf_type(areq_ctx->data_dma_buf_type)); return 0; fail_unmap_din: dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); unmap_curr_buff: - if (*curr_buff_cnt != 0) + if (*curr_buff_cnt) dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); return -ENOMEM; } -int ssi_buffer_mgr_map_hash_request_update( - struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size) +int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + unsigned int block_size) { struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; struct device *dev = drvdata_to_dev(drvdata); @@ -1602,12 +1554,11 @@ int ssi_buffer_mgr_map_hash_request_update( sg_data.num_of_buffers = 0; areq_ctx->in_nents = 0; - if (unlikely(total_in_len < block_size)) { + if (total_in_len < block_size) { dev_dbg(dev, " less than one block: curr_buff=%pK *curr_buff_cnt=0x%X copy_to=%pK\n", curr_buff, *curr_buff_cnt, &curr_buff[*curr_buff_cnt]); areq_ctx->in_nents = - ssi_buffer_mgr_get_sgl_nents(dev, src, nbytes, &dummy, - NULL); + cc_get_sgl_nents(dev, src, nbytes, &dummy, NULL); sg_copy_to_buffer(src, areq_ctx->in_nents, &curr_buff[*curr_buff_cnt], nbytes); *curr_buff_cnt += nbytes; @@ -1623,20 +1574,20 @@ int ssi_buffer_mgr_map_hash_request_update( *next_buff_cnt, update_data_len); /* Copy the new residue to next buffer */ - if (*next_buff_cnt != 0) { + if (*next_buff_cnt) { dev_dbg(dev, " handle residue: next buff %pK skip data %u residue %u\n", next_buff, (update_data_len - *curr_buff_cnt), *next_buff_cnt); - ssi_buffer_mgr_copy_scatterlist_portion(dev, next_buff, src, - (update_data_len - *curr_buff_cnt), - nbytes, SSI_SG_TO_BUF); + cc_copy_sg_portion(dev, next_buff, src, + (update_data_len - *curr_buff_cnt), + nbytes, SSI_SG_TO_BUF); /* change the buffer index for next operation */ swap_index = 1; } - if (*curr_buff_cnt != 0) { + if (*curr_buff_cnt) { if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff, - *curr_buff_cnt, &sg_data) != 0) { + *curr_buff_cnt, &sg_data)) { return -ENOMEM; } /* change the buffer index for next operation */ @@ -1644,17 +1595,14 @@ int ssi_buffer_mgr_map_hash_request_update( } if (update_data_len > *curr_buff_cnt) { - if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, - (update_data_len - *curr_buff_cnt), - DMA_TO_DEVICE, - &areq_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dummy, - &mapped_nents))){ + if (cc_map_sg(dev, src, (update_data_len - *curr_buff_cnt), + DMA_TO_DEVICE, &areq_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, + &mapped_nents)) { goto unmap_curr_buff; } - if ((mapped_nents == 1) - && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) { + if (mapped_nents == 1 && + areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { /* only one entry in the SG and no previous data */ memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist)); @@ -1666,20 +1614,14 @@ int ssi_buffer_mgr_map_hash_request_update( } } - if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) { + if (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; /* add the src data to the sg_data */ - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - areq_ctx->in_nents, - src, - (update_data_len - *curr_buff_cnt), - 0, - true, - &areq_ctx->mlli_nents); - if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data, - mlli_params) != 0)) { + cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, + (update_data_len - *curr_buff_cnt), 0, true, + &areq_ctx->mlli_nents); + if (cc_generate_mlli(dev, &sg_data, mlli_params)) goto fail_unmap_din; - } } areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index); @@ -1689,14 +1631,14 @@ fail_unmap_din: dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); unmap_curr_buff: - if (*curr_buff_cnt != 0) + if (*curr_buff_cnt) dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); return -ENOMEM; } -void ssi_buffer_mgr_unmap_hash_request( - struct device *dev, void *ctx, struct scatterlist *src, bool do_revert) +void cc_unmap_hash_request(struct device *dev, void *ctx, + struct scatterlist *src, bool do_revert) { struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; u32 *prev_len = areq_ctx->buff_index ? &areq_ctx->buff0_cnt : @@ -1714,21 +1656,23 @@ void ssi_buffer_mgr_unmap_hash_request( areq_ctx->mlli_params.mlli_dma_addr); } - if ((src) && likely(areq_ctx->in_nents != 0)) { + if (src && areq_ctx->in_nents) { dev_dbg(dev, "Unmapped sg src: virt=%pK dma=%pad len=0x%X\n", sg_virt(src), &sg_dma_address(src), sg_dma_len(src)); dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); } - if (*prev_len != 0) { + if (*prev_len) { dev_dbg(dev, "Unmapped buffer: areq_ctx->buff_sg=%pK dma=%pad len 0x%X\n", sg_virt(areq_ctx->buff_sg), &sg_dma_address(areq_ctx->buff_sg), sg_dma_len(areq_ctx->buff_sg)); dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); if (!do_revert) { - /* clean the previous data length for update operation */ + /* clean the previous data length for update + * operation + */ *prev_len = 0; } else { areq_ctx->buff_index ^= 1; @@ -1736,7 +1680,7 @@ void ssi_buffer_mgr_unmap_hash_request( } } -int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata) +int cc_buffer_mgr_init(struct ssi_drvdata *drvdata) { struct buff_mgr_handle *buff_mgr_handle; struct device *dev = drvdata_to_dev(drvdata); @@ -1753,17 +1697,17 @@ int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata) LLI_ENTRY_BYTE_SIZE, MLLI_TABLE_MIN_ALIGNMENT, 0); - if (unlikely(!buff_mgr_handle->mlli_buffs_pool)) + if (!buff_mgr_handle->mlli_buffs_pool) goto error; return 0; error: - ssi_buffer_mgr_fini(drvdata); + cc_buffer_mgr_fini(drvdata); return -ENOMEM; } -int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata) +int cc_buffer_mgr_fini(struct ssi_drvdata *drvdata) { struct buff_mgr_handle *buff_mgr_handle = drvdata->buff_mgr_handle; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.h b/drivers/staging/ccree/ssi_buffer_mgr.h index 1032f25edcab..f6411de3f8de 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.h +++ b/drivers/staging/ccree/ssi_buffer_mgr.h @@ -50,42 +50,39 @@ struct mlli_params { u32 mlli_len; }; -int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata); +int cc_buffer_mgr_init(struct ssi_drvdata *drvdata); -int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata); +int cc_buffer_mgr_fini(struct ssi_drvdata *drvdata); -int ssi_buffer_mgr_map_blkcipher_request( - struct ssi_drvdata *drvdata, - void *ctx, - unsigned int ivsize, - unsigned int nbytes, - void *info, - struct scatterlist *src, - struct scatterlist *dst); +int cc_map_blkcipher_request(struct ssi_drvdata *drvdata, void *ctx, + unsigned int ivsize, unsigned int nbytes, + void *info, struct scatterlist *src, + struct scatterlist *dst); -void ssi_buffer_mgr_unmap_blkcipher_request( - struct device *dev, - void *ctx, - unsigned int ivsize, - struct scatterlist *src, - struct scatterlist *dst); +void cc_unmap_blkcipher_request(struct device *dev, void *ctx, + unsigned int ivsize, + struct scatterlist *src, + struct scatterlist *dst); -int ssi_buffer_mgr_map_aead_request(struct ssi_drvdata *drvdata, struct aead_request *req); +int cc_map_aead_request(struct ssi_drvdata *drvdata, struct aead_request *req); -void ssi_buffer_mgr_unmap_aead_request(struct device *dev, struct aead_request *req); +void cc_unmap_aead_request(struct device *dev, struct aead_request *req); -int ssi_buffer_mgr_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update); +int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + bool do_update); -int ssi_buffer_mgr_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size); +int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + unsigned int block_size); -void ssi_buffer_mgr_unmap_hash_request(struct device *dev, void *ctx, struct scatterlist *src, bool do_revert); +void cc_unmap_hash_request(struct device *dev, void *ctx, + struct scatterlist *src, bool do_revert); -void ssi_buffer_mgr_copy_scatterlist_portion(struct device *dev, u8 *dest, - struct scatterlist *sg, - u32 to_skip, u32 end, - enum ssi_sg_cpy_direct direct); +void cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg, + u32 to_skip, u32 end, enum ssi_sg_cpy_direct direct); -void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len); +void cc_zero_sgl(struct scatterlist *sgl, u32 data_len); #endif /*__BUFFER_MGR_H__*/ diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index ee85cbf7c9ae..7b484f111d12 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -67,7 +67,7 @@ struct ssi_ablkcipher_ctx { struct crypto_shash *shash_tfm; }; -static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base); +static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req); static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) { @@ -76,30 +76,30 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) switch (size) { case CC_AES_128_BIT_KEY_SIZE: case CC_AES_192_BIT_KEY_SIZE: - if (likely((ctx_p->cipher_mode != DRV_CIPHER_XTS) && - (ctx_p->cipher_mode != DRV_CIPHER_ESSIV) && - (ctx_p->cipher_mode != DRV_CIPHER_BITLOCKER))) + if (ctx_p->cipher_mode != DRV_CIPHER_XTS && + ctx_p->cipher_mode != DRV_CIPHER_ESSIV && + ctx_p->cipher_mode != DRV_CIPHER_BITLOCKER) return 0; break; case CC_AES_256_BIT_KEY_SIZE: return 0; case (CC_AES_192_BIT_KEY_SIZE * 2): case (CC_AES_256_BIT_KEY_SIZE * 2): - if (likely((ctx_p->cipher_mode == DRV_CIPHER_XTS) || - (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) || - (ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER))) + if (ctx_p->cipher_mode == DRV_CIPHER_XTS || + ctx_p->cipher_mode == DRV_CIPHER_ESSIV || + ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER) return 0; break; default: break; } case S_DIN_to_DES: - if (likely(size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE)) + if (size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE) return 0; break; #if SSI_CC_HAS_MULTI2 case S_DIN_to_MULTI2: - if (likely(size == CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE)) + if (size == CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE) return 0; break; #endif @@ -109,19 +109,20 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) return -EINVAL; } -static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int size) +static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, + unsigned int size) { switch (ctx_p->flow_mode) { case S_DIN_to_AES: switch (ctx_p->cipher_mode) { case DRV_CIPHER_XTS: - if ((size >= SSI_MIN_AES_XTS_SIZE) && - (size <= SSI_MAX_AES_XTS_SIZE) && + if (size >= SSI_MIN_AES_XTS_SIZE && + size <= SSI_MAX_AES_XTS_SIZE && IS_ALIGNED(size, AES_BLOCK_SIZE)) return 0; break; case DRV_CIPHER_CBC_CTS: - if (likely(size >= AES_BLOCK_SIZE)) + if (size >= AES_BLOCK_SIZE) return 0; break; case DRV_CIPHER_OFB: @@ -131,7 +132,7 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz case DRV_CIPHER_CBC: case DRV_CIPHER_ESSIV: case DRV_CIPHER_BITLOCKER: - if (likely(IS_ALIGNED(size, AES_BLOCK_SIZE))) + if (IS_ALIGNED(size, AES_BLOCK_SIZE)) return 0; break; default: @@ -139,14 +140,14 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz } break; case S_DIN_to_DES: - if (likely(IS_ALIGNED(size, DES_BLOCK_SIZE))) - return 0; + if (IS_ALIGNED(size, DES_BLOCK_SIZE)) + return 0; break; #if SSI_CC_HAS_MULTI2 case S_DIN_to_MULTI2: switch (ctx_p->cipher_mode) { case DRV_MULTI2_CBC: - if (likely(IS_ALIGNED(size, CC_MULTI2_BLOCK_SIZE))) + if (IS_ALIGNED(size, CC_MULTI2_BLOCK_SIZE)) return 0; break; case DRV_MULTI2_OFB: @@ -164,12 +165,16 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz static unsigned int get_max_keysize(struct crypto_tfm *tfm) { - struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg); + struct ssi_crypto_alg *ssi_alg = + container_of(tfm->__crt_alg, struct ssi_crypto_alg, + crypto_alg); - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_ABLKCIPHER) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_ABLKCIPHER) return ssi_alg->crypto_alg.cra_ablkcipher.max_keysize; - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_BLKCIPHER) return ssi_alg->crypto_alg.cra_blkcipher.max_keysize; return 0; @@ -267,8 +272,10 @@ static int ssi_verify_3des_keys(const u8 *key, unsigned int keylen) struct tdes_keys *tdes_key = (struct tdes_keys *)key; /* verify key1 != key2 and key3 != key2*/ - if (unlikely((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, sizeof(tdes_key->key1)) == 0) || - (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) { + if ((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, + sizeof(tdes_key->key1)) == 0) || + (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, + sizeof(tdes_key->key3)) == 0)) { return -ENOEXEC; } @@ -306,12 +313,14 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, /* STAT_PHASE_0: Init and sanity checks */ #if SSI_CC_HAS_MULTI2 - /*last byte of key buffer is round number and should not be a part of key size*/ + /* last byte of key buffer is round number and should not be a part + * of key size + */ if (ctx_p->flow_mode == S_DIN_to_MULTI2) keylen -= 1; #endif /*SSI_CC_HAS_MULTI2*/ - if (unlikely(validate_keys_sizes(ctx_p, keylen) != 0)) { + if (validate_keys_sizes(ctx_p, keylen)) { dev_err(dev, "Unsupported key size %d.\n", keylen); crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; @@ -321,28 +330,29 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, /* setting HW key slots */ struct arm_hw_key_info *hki = (struct arm_hw_key_info *)key; - if (unlikely(ctx_p->flow_mode != S_DIN_to_AES)) { + if (ctx_p->flow_mode != S_DIN_to_AES) { dev_err(dev, "HW key not supported for non-AES flows\n"); return -EINVAL; } ctx_p->hw.key1_slot = hw_key_to_cc_hw_key(hki->hw_key1); - if (unlikely(ctx_p->hw.key1_slot == END_OF_KEYS)) { + if (ctx_p->hw.key1_slot == END_OF_KEYS) { dev_err(dev, "Unsupported hw key1 number (%d)\n", hki->hw_key1); return -EINVAL; } - if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) || - (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) || - (ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)) { - if (unlikely(hki->hw_key1 == hki->hw_key2)) { + if (ctx_p->cipher_mode == DRV_CIPHER_XTS || + ctx_p->cipher_mode == DRV_CIPHER_ESSIV || + ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER) { + if (hki->hw_key1 == hki->hw_key2) { dev_err(dev, "Illegal hw key numbers (%d,%d)\n", hki->hw_key1, hki->hw_key2); return -EINVAL; } - ctx_p->hw.key2_slot = hw_key_to_cc_hw_key(hki->hw_key2); - if (unlikely(ctx_p->hw.key2_slot == END_OF_KEYS)) { + ctx_p->hw.key2_slot = + hw_key_to_cc_hw_key(hki->hw_key2); + if (ctx_p->hw.key2_slot == END_OF_KEYS) { dev_err(dev, "Unsupported hw key2 number (%d)\n", hki->hw_key2); return -EINVAL; @@ -357,21 +367,21 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, // verify weak keys if (ctx_p->flow_mode == S_DIN_to_DES) { - if (unlikely(!des_ekey(tmp, key)) && + if (!des_ekey(tmp, key) && (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_WEAK_KEY)) { tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; dev_dbg(dev, "weak DES key"); return -EINVAL; } } - if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) && - xts_check_key(tfm, key, keylen) != 0) { + if (ctx_p->cipher_mode == DRV_CIPHER_XTS && + xts_check_key(tfm, key, keylen)) { dev_dbg(dev, "weak XTS key"); return -EINVAL; } - if ((ctx_p->flow_mode == S_DIN_to_DES) && - (keylen == DES3_EDE_KEY_SIZE) && - ssi_verify_3des_keys(key, keylen) != 0) { + if (ctx_p->flow_mode == S_DIN_to_DES && + keylen == DES3_EDE_KEY_SIZE && + ssi_verify_3des_keys(key, keylen)) { dev_dbg(dev, "weak 3DES key"); return -EINVAL; } @@ -383,7 +393,8 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, if (ctx_p->flow_mode == S_DIN_to_MULTI2) { #if SSI_CC_HAS_MULTI2 memcpy(ctx_p->user.key, key, CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE); - ctx_p->key_round_number = key[CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE]; + ctx_p->key_round_number = + key[CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE]; if (ctx_p->key_round_number < CC_MULTI2_MIN_NUM_ROUNDS || ctx_p->key_round_number > CC_MULTI2_MAX_NUM_ROUNDS) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); @@ -393,7 +404,8 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, } else { memcpy(ctx_p->user.key, key, keylen); if (keylen == 24) - memset(ctx_p->user.key + 24, 0, CC_AES_KEY_SIZE_MAX - 24); + memset(ctx_p->user.key + 24, 0, + CC_AES_KEY_SIZE_MAX - 24); if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { /* sha256 for key2 - use sw implementation */ @@ -403,7 +415,9 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, desc->tfm = ctx_p->shash_tfm; - err = crypto_shash_digest(desc, ctx_p->user.key, key_len, ctx_p->user.key + key_len); + err = crypto_shash_digest(desc, ctx_p->user.key, + key_len, + ctx_p->user.key + key_len); if (err) { dev_err(dev, "Failed to hash ESSIV key.\n"); return err; @@ -418,7 +432,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, return 0; } -static inline void +static void ssi_blkcipher_create_setup_desc( struct crypto_tfm *tfm, struct blkcipher_req_ctx *req_ctx, @@ -437,11 +451,15 @@ ssi_blkcipher_create_setup_desc( dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr; unsigned int du_size = nbytes; - struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg); + struct ssi_crypto_alg *ssi_alg = + container_of(tfm->__crt_alg, struct ssi_crypto_alg, + crypto_alg); - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == CRYPTO_ALG_BULK_DU_512) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == + CRYPTO_ALG_BULK_DU_512) du_size = 512; - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == CRYPTO_ALG_BULK_DU_4096) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == + CRYPTO_ALG_BULK_DU_4096) du_size = 4096; switch (cipher_mode) { @@ -456,8 +474,8 @@ ssi_blkcipher_create_setup_desc( set_cipher_config0(&desc[*seq_size], direction); set_flow_mode(&desc[*seq_size], flow_mode); set_cipher_mode(&desc[*seq_size], cipher_mode); - if ((cipher_mode == DRV_CIPHER_CTR) || - (cipher_mode == DRV_CIPHER_OFB)) { + if (cipher_mode == DRV_CIPHER_CTR || + cipher_mode == DRV_CIPHER_OFB) { set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1); } else { set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0); @@ -544,7 +562,7 @@ ssi_blkcipher_create_setup_desc( } #if SSI_CC_HAS_MULTI2 -static inline void ssi_blkcipher_create_multi2_setup_desc( +static void ssi_blkcipher_create_multi2_setup_desc( struct crypto_tfm *tfm, struct blkcipher_req_ctx *req_ctx, unsigned int ivsize, @@ -588,7 +606,7 @@ static inline void ssi_blkcipher_create_multi2_setup_desc( } #endif /*SSI_CC_HAS_MULTI2*/ -static inline void +static void ssi_blkcipher_create_data_desc( struct crypto_tfm *tfm, struct blkcipher_req_ctx *req_ctx, @@ -619,7 +637,7 @@ ssi_blkcipher_create_data_desc( return; } /* Process */ - if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)) { + if (req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI) { dev_dbg(dev, " data params addr %pad length 0x%X\n", &sg_dma_address(src), nbytes); dev_dbg(dev, " data params addr %pad length 0x%X\n", @@ -688,13 +706,12 @@ static int ssi_blkcipher_complete(struct device *dev, struct scatterlist *dst, struct scatterlist *src, unsigned int ivsize, - void *areq, - void __iomem *cc_base) + void *areq) { int completion_error = 0; struct ablkcipher_request *req = (struct ablkcipher_request *)areq; - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); kfree(req_ctx->iv); if (areq) { @@ -743,7 +760,7 @@ static int ssi_blkcipher_process( /* STAT_PHASE_0: Init and sanity checks */ /* TODO: check data length according to mode */ - if (unlikely(validate_data_size(ctx_p, nbytes))) { + if (validate_data_size(ctx_p, nbytes)) { dev_err(dev, "Unsupported data size %d.\n", nbytes); crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN); rc = -EINVAL; @@ -766,7 +783,8 @@ static int ssi_blkcipher_process( memcpy(req_ctx->iv, info, ivsize); /*For CTS in case of data size aligned to 16 use CBC mode*/ - if (((nbytes % AES_BLOCK_SIZE) == 0) && (ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS)) { + if (((nbytes % AES_BLOCK_SIZE) == 0) && + ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS) { ctx_p->cipher_mode = DRV_CIPHER_CBC; cts_restore_flag = 1; } @@ -786,10 +804,9 @@ static int ssi_blkcipher_process( /* STAT_PHASE_1: Map buffers */ - rc = ssi_buffer_mgr_map_blkcipher_request(ctx_p->drvdata, req_ctx, - ivsize, nbytes, req_ctx->iv, - src, dst); - if (unlikely(rc != 0)) { + rc = cc_map_blkcipher_request(ctx_p->drvdata, req_ctx, ivsize, nbytes, + req_ctx->iv, src, dst); + if (rc) { dev_err(dev, "map_request() failed\n"); goto exit_process; } @@ -819,25 +836,29 @@ static int ssi_blkcipher_process( /* STAT_PHASE_3: Lock HW and push sequence */ - rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, (!areq) ? 0 : 1); + rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, + (!areq) ? 0 : 1); if (areq) { - if (unlikely(rc != -EINPROGRESS)) { - /* Failed to send the request or request completed synchronously */ - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + if (rc != -EINPROGRESS) { + /* Failed to send the request or request completed + * synchronously + */ + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, + dst); } } else { - if (rc != 0) { - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + if (rc) { + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, + dst); } else { rc = ssi_blkcipher_complete(dev, ctx_p, req_ctx, dst, - src, ivsize, NULL, - ctx_p->drvdata->cc_base); + src, ivsize, NULL); } } exit_process: - if (cts_restore_flag != 0) + if (cts_restore_flag) ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS; if (rc != -EINPROGRESS) { @@ -848,7 +869,7 @@ exit_process: return rc; } -static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req) { struct ablkcipher_request *areq = (struct ablkcipher_request *)ssi_req; struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(areq); @@ -857,7 +878,7 @@ static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __io unsigned int ivsize = crypto_ablkcipher_ivsize(tfm); ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src, - ivsize, areq, cc_base); + ivsize, areq); } /* Async wrap functions */ @@ -886,8 +907,12 @@ static int ssi_ablkcipher_encrypt(struct ablkcipher_request *req) unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm); req_ctx->is_giv = false; + req_ctx->backup_info = NULL; - return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_ENCRYPT); + return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, + req->nbytes, req->info, ivsize, + (void *)req, + DRV_CRYPTO_DIRECTION_ENCRYPT); } static int ssi_ablkcipher_decrypt(struct ablkcipher_request *req) @@ -909,7 +934,10 @@ static int ssi_ablkcipher_decrypt(struct ablkcipher_request *req) (req->nbytes - ivsize), ivsize, 0); req_ctx->is_giv = false; - return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_DECRYPT); + return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, + req->nbytes, req->info, ivsize, + (void *)req, + DRV_CRYPTO_DIRECTION_DECRYPT); } /* DX Block cipher alg */ @@ -1337,7 +1365,7 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata) rc = crypto_register_alg(&t_alg->crypto_alg); dev_dbg(dev, "%s alg registration rc = %x\n", t_alg->crypto_alg.cra_driver_name, rc); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "%s alg registration failed\n", t_alg->crypto_alg.cra_driver_name); kfree(t_alg); diff --git a/drivers/staging/ccree/ssi_cipher.h b/drivers/staging/ccree/ssi_cipher.h index 25e6335c0d94..14c0ad99c0c5 100644 --- a/drivers/staging/ccree/ssi_cipher.h +++ b/drivers/staging/ccree/ssi_cipher.h @@ -33,7 +33,10 @@ #define CC_CRYPTO_CIPHER_KEY_KFDE3 BIT(3) #define CC_CRYPTO_CIPHER_DU_SIZE_512B BIT(4) -#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | CC_CRYPTO_CIPHER_KEY_KFDE1 | CC_CRYPTO_CIPHER_KEY_KFDE2 | CC_CRYPTO_CIPHER_KEY_KFDE3) +#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | \ + CC_CRYPTO_CIPHER_KEY_KFDE1 | \ + CC_CRYPTO_CIPHER_KEY_KFDE2 | \ + CC_CRYPTO_CIPHER_KEY_KFDE3) struct blkcipher_req_ctx { struct async_gen_req_ctx gen_ctx; diff --git a/drivers/staging/ccree/ssi_config.h b/drivers/staging/ccree/ssi_config.h index ff7597c2d77e..ea7484514645 100644 --- a/drivers/staging/ccree/ssi_config.h +++ b/drivers/staging/ccree/ssi_config.h @@ -28,9 +28,11 @@ //#define DX_DUMP_DESCS // #define DX_DUMP_BYTES // #define CC_DEBUG -#define ENABLE_CC_SYSFS /* Enable sysfs interface for debugging REE driver */ +/* Enable sysfs interface for debugging REE driver */ +#define ENABLE_CC_SYSFS //#define DX_IRQ_DELAY 100000 -#define DMA_BIT_MASK_LEN 48 /* was 32 bit, but for juno's sake it was enlarged to 48 bit */ +/* was 32 bit, but for juno's sake it was enlarged to 48 bit */ +#define DMA_BIT_MASK_LEN 48 #endif /*__DX_CONFIG_H__*/ diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 1a3c481fa92a..041624f78214 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -100,7 +100,7 @@ static irqreturn_t cc_isr(int irq, void *dev_id) /* read the interrupt status */ irr = cc_ioread(drvdata, CC_REG(HOST_IRR)); dev_dbg(dev, "Got IRR=0x%08X\n", irr); - if (unlikely(irr == 0)) { /* Probably shared interrupt line */ + if (irr == 0) { /* Probably shared interrupt line */ dev_err(dev, "Got interrupt with empty IRR\n"); return IRQ_NONE; } @@ -111,23 +111,27 @@ static irqreturn_t cc_isr(int irq, void *dev_id) drvdata->irq = irr; /* Completion interrupt - most probable */ - if (likely((irr & SSI_COMP_IRQ_MASK) != 0)) { - /* Mask AXI completion interrupt - will be unmasked in Deferred service handler */ + if (irr & SSI_COMP_IRQ_MASK) { + /* Mask AXI completion interrupt - will be unmasked in + * Deferred service handler + */ cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_COMP_IRQ_MASK); irr &= ~SSI_COMP_IRQ_MASK; complete_request(drvdata); } #ifdef CC_SUPPORT_FIPS /* TEE FIPS interrupt */ - if (likely((irr & SSI_GPR0_IRQ_MASK) != 0)) { - /* Mask interrupt - will be unmasked in Deferred service handler */ + if (irr & SSI_GPR0_IRQ_MASK) { + /* Mask interrupt - will be unmasked in Deferred service + * handler + */ cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_GPR0_IRQ_MASK); irr &= ~SSI_GPR0_IRQ_MASK; fips_handler(drvdata); } #endif /* AXI error interrupt */ - if (unlikely((irr & SSI_AXI_ERR_IRQ_MASK) != 0)) { + if (irr & SSI_AXI_ERR_IRQ_MASK) { u32 axi_err; /* Read the AXI error ID */ @@ -138,7 +142,7 @@ static irqreturn_t cc_isr(int irq, void *dev_id) irr &= ~SSI_AXI_ERR_IRQ_MASK; } - if (unlikely(irr != 0)) { + if (irr) { dev_dbg(dev, "IRR includes unknown cause bits (0x%08X)\n", irr); /* Just warning */ @@ -199,7 +203,6 @@ int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe) static int init_cc_resources(struct platform_device *plat_dev) { struct resource *req_mem_cc_regs = NULL; - void __iomem *cc_base = NULL; struct ssi_drvdata *new_drvdata; struct device *dev = &plat_dev->dev; struct device_node *np = dev->of_node; @@ -232,8 +235,6 @@ static int init_cc_resources(struct platform_device *plat_dev) dev_dbg(dev, "CC registers mapped from %pa to 0x%p\n", &req_mem_cc_regs->start, new_drvdata->cc_base); - cc_base = new_drvdata->cc_base; - /* Then IRQ */ new_drvdata->irq = platform_get_irq(plat_dev, 0); if (new_drvdata->irq < 0) { @@ -250,6 +251,8 @@ static int init_cc_resources(struct platform_device *plat_dev) } dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq); + init_completion(&new_drvdata->hw_queue_avail); + if (!plat_dev->dev.dma_mask) plat_dev->dev.dma_mask = &plat_dev->dev.coherent_dma_mask; @@ -292,79 +295,79 @@ static int init_cc_resources(struct platform_device *plat_dev) DRV_MODULE_VERSION); rc = init_cc_regs(new_drvdata, true); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "init_cc_regs failed\n"); goto post_clk_err; } #ifdef ENABLE_CC_SYSFS rc = ssi_sysfs_init(&dev->kobj, new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "init_stat_db failed\n"); goto post_regs_err; } #endif rc = ssi_fips_init(new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "SSI_FIPS_INIT failed 0x%x\n", rc); goto post_sysfs_err; } rc = ssi_sram_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "ssi_sram_mgr_init failed\n"); goto post_fips_init_err; } new_drvdata->mlli_sram_addr = - ssi_sram_mgr_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE); - if (unlikely(new_drvdata->mlli_sram_addr == NULL_SRAM_ADDR)) { + cc_sram_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE); + if (new_drvdata->mlli_sram_addr == NULL_SRAM_ADDR) { dev_err(dev, "Failed to alloc MLLI Sram buffer\n"); rc = -ENOMEM; goto post_sram_mgr_err; } rc = request_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "request_mgr_init failed\n"); goto post_sram_mgr_err; } - rc = ssi_buffer_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + rc = cc_buffer_mgr_init(new_drvdata); + if (rc) { dev_err(dev, "buffer_mgr_init failed\n"); goto post_req_mgr_err; } - rc = ssi_power_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + rc = cc_pm_init(new_drvdata); + if (rc) { dev_err(dev, "ssi_power_mgr_init failed\n"); goto post_buf_mgr_err; } rc = ssi_ivgen_init(new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "ssi_ivgen_init failed\n"); goto post_power_mgr_err; } /* Allocate crypto algs */ rc = ssi_ablkcipher_alloc(new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "ssi_ablkcipher_alloc failed\n"); goto post_ivgen_err; } /* hash must be allocated before aead since hash exports APIs */ rc = ssi_hash_alloc(new_drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "ssi_hash_alloc failed\n"); goto post_cipher_err; } - rc = ssi_aead_alloc(new_drvdata); - if (unlikely(rc != 0)) { - dev_err(dev, "ssi_aead_alloc failed\n"); + rc = cc_aead_alloc(new_drvdata); + if (rc) { + dev_err(dev, "cc_aead_alloc failed\n"); goto post_hash_err; } @@ -383,9 +386,9 @@ post_cipher_err: post_ivgen_err: ssi_ivgen_fini(new_drvdata); post_power_mgr_err: - ssi_power_mgr_fini(new_drvdata); + cc_pm_fini(new_drvdata); post_buf_mgr_err: - ssi_buffer_mgr_fini(new_drvdata); + cc_buffer_mgr_fini(new_drvdata); post_req_mgr_err: request_mgr_fini(new_drvdata); post_sram_mgr_err: @@ -414,12 +417,12 @@ static void cleanup_cc_resources(struct platform_device *plat_dev) struct ssi_drvdata *drvdata = (struct ssi_drvdata *)platform_get_drvdata(plat_dev); - ssi_aead_free(drvdata); + cc_aead_free(drvdata); ssi_hash_free(drvdata); ssi_ablkcipher_free(drvdata); ssi_ivgen_fini(drvdata); - ssi_power_mgr_fini(drvdata); - ssi_buffer_mgr_fini(drvdata); + cc_pm_fini(drvdata); + cc_buffer_mgr_fini(drvdata); request_mgr_fini(drvdata); ssi_sram_mgr_fini(drvdata); ssi_fips_fini(drvdata); @@ -477,7 +480,7 @@ static int cc7x_probe(struct platform_device *plat_dev) /* Map registers space */ rc = init_cc_resources(plat_dev); - if (rc != 0) + if (rc) return rc; dev_info(dev, "ARM ccree device initialized\n"); @@ -498,13 +501,13 @@ static int cc7x_remove(struct platform_device *plat_dev) return 0; } -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) static const struct dev_pm_ops arm_cc7x_driver_pm = { - SET_RUNTIME_PM_OPS(ssi_power_mgr_runtime_suspend, ssi_power_mgr_runtime_resume, NULL) + SET_RUNTIME_PM_OPS(cc_pm_suspend, cc_pm_resume, NULL) }; #endif -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) #define DX_DRIVER_RUNTIME_PM (&arm_cc7x_driver_pm) #else #define DX_DRIVER_RUNTIME_PM NULL diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index 94c755cafb47..f92867b76073 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -63,8 +63,10 @@ #define SSI_CC_HAS_MULTI2 0 #define SSI_CC_HAS_CMAC 1 -#define SSI_AXI_IRQ_MASK ((1 << DX_AXIM_CFG_BRESPMASK_BIT_SHIFT) | (1 << DX_AXIM_CFG_RRESPMASK_BIT_SHIFT) | \ - (1 << DX_AXIM_CFG_INFLTMASK_BIT_SHIFT) | (1 << DX_AXIM_CFG_COMPMASK_BIT_SHIFT)) +#define SSI_AXI_IRQ_MASK ((1 << DX_AXIM_CFG_BRESPMASK_BIT_SHIFT) | \ + (1 << DX_AXIM_CFG_RRESPMASK_BIT_SHIFT) | \ + (1 << DX_AXIM_CFG_INFLTMASK_BIT_SHIFT) | \ + (1 << DX_AXIM_CFG_COMPMASK_BIT_SHIFT)) #define SSI_AXI_ERR_IRQ_MASK BIT(DX_HOST_IRR_AXI_ERR_INT_BIT_SHIFT) @@ -95,20 +97,19 @@ * field in the HW descriptor. The DMA engine +8 that value. */ -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - #define SSI_MAX_IVGEN_DMA_ADDRESSES 3 struct ssi_crypto_req { - void (*user_cb)(struct device *dev, void *req, void __iomem *cc_base); + void (*user_cb)(struct device *dev, void *req); void *user_arg; dma_addr_t ivgen_dma_addr[SSI_MAX_IVGEN_DMA_ADDRESSES]; /* For the first 'ivgen_dma_addr_len' addresses of this array, * generated IV would be placed in it by send_request(). * Same generated IV for all addresses! */ - unsigned int ivgen_dma_addr_len; /* Amount of 'ivgen_dma_addr' elements to be filled. */ - unsigned int ivgen_size; /* The generated IV size required, 8/16 B allowed. */ + /* Amount of 'ivgen_dma_addr' elements to be filled. */ + unsigned int ivgen_dma_addr_len; + /* The generated IV size required, 8/16 B allowed. */ + unsigned int ivgen_size; struct completion seq_compl; /* request completion */ }; @@ -124,10 +125,7 @@ struct ssi_drvdata { int irq; u32 irq_mask; u32 fw_ver; - /* Calibration time of start/stop - * monitor descriptors - */ - u32 monitor_null_cycles; + struct completion hw_queue_avail; /* wait for HW queue availability */ struct platform_device *plat_dev; ssi_sram_addr_t mlli_sram_addr; void *buff_mgr_handle; @@ -181,7 +179,8 @@ static inline struct device *drvdata_to_dev(struct ssi_drvdata *drvdata) } #ifdef DX_DUMP_BYTES -void dump_byte_array(const char *name, const u8 *the_array, unsigned long size); +void dump_byte_array(const char *name, const u8 *the_array, + unsigned long size); #else static inline void dump_byte_array(const char *name, const u8 *the_array, unsigned long size) {}; diff --git a/drivers/staging/ccree/ssi_fips.h b/drivers/staging/ccree/ssi_fips.h index 63bcca7f3af9..8cb1893536a5 100644 --- a/drivers/staging/ccree/ssi_fips.h +++ b/drivers/staging/ccree/ssi_fips.h @@ -40,7 +40,8 @@ static inline int ssi_fips_init(struct ssi_drvdata *p_drvdata) } static inline void ssi_fips_fini(struct ssi_drvdata *drvdata) {} -static inline void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool ok) {} +static inline void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, + bool ok) {} static inline void fips_handler(struct ssi_drvdata *drvdata) {} #endif /* CONFIG_CRYPTO_FIPS */ diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 1799d3f26a9e..27f49a28c241 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -32,7 +32,7 @@ #include "ssi_sram_mgr.h" #define SSI_MAX_AHASH_SEQ_LEN 12 -#define SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE MAX(SSI_MAX_HASH_BLCK_SIZE, 3 * AES_BLOCK_SIZE) +#define SSI_MAX_OPAD_KEYS_SIZE SSI_MAX_HASH_BLCK_SIZE struct ssi_hash_handle { ssi_sram_addr_t digest_len_sram_addr; /* const value in SRAM*/ @@ -94,7 +94,7 @@ struct ssi_hash_ctx { * the initial digest if HASH. */ u8 digest_buff[SSI_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned; - u8 opad_tmp_keys_buff[SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE] ____cacheline_aligned; + u8 opad_tmp_keys_buff[SSI_MAX_OPAD_KEYS_SIZE] ____cacheline_aligned; dma_addr_t opad_tmp_keys_dma_addr ____cacheline_aligned; dma_addr_t digest_buff_dma_addr; @@ -114,11 +114,10 @@ static void ssi_hash_create_data_desc( bool is_not_last_data, unsigned int *seq_size); -static inline void ssi_set_hash_endianity(u32 mode, struct cc_hw_desc *desc) +static void ssi_set_hash_endianity(u32 mode, struct cc_hw_desc *desc) { - if (unlikely((mode == DRV_HASH_MD5) || - (mode == DRV_HASH_SHA384) || - (mode == DRV_HASH_SHA512))) { + if (mode == DRV_HASH_MD5 || mode == DRV_HASH_SHA384 || + mode == DRV_HASH_SHA512) { set_bytes_swap(desc, 1); } else { set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN); @@ -133,7 +132,7 @@ static int ssi_hash_map_result(struct device *dev, dma_map_single(dev, (void *)state->digest_result_buff, digestsize, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, state->digest_result_dma_addr))) { + if (dma_mapping_error(dev, state->digest_result_dma_addr)) { dev_err(dev, "Mapping digest result buffer %u B for DMA failed\n", digestsize); return -ENOMEM; @@ -150,8 +149,8 @@ static int ssi_hash_map_request(struct device *dev, struct ssi_hash_ctx *ctx) { bool is_hmac = ctx->is_hmac; - ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->hash_mode); + ssi_sram_addr_t larval_digest_addr = + cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); struct ssi_crypto_req ssi_req = {}; struct cc_hw_desc desc; int rc = -ENOMEM; @@ -164,18 +163,21 @@ static int ssi_hash_map_request(struct device *dev, if (!state->buff1) goto fail_buff0; - state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE, GFP_KERNEL | GFP_DMA); + state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE, + GFP_KERNEL | GFP_DMA); if (!state->digest_result_buff) goto fail_buff1; - state->digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA); + state->digest_buff = kzalloc(ctx->inter_digestsize, + GFP_KERNEL | GFP_DMA); if (!state->digest_buff) goto fail_digest_result_buff; dev_dbg(dev, "Allocated digest-buffer in context ctx->digest_buff=@%p\n", state->digest_buff); if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) { - state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, GFP_KERNEL | GFP_DMA); + state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, + GFP_KERNEL | GFP_DMA); if (!state->digest_bytes_len) goto fail1; @@ -185,14 +187,17 @@ static int ssi_hash_map_request(struct device *dev, state->digest_bytes_len = NULL; } - state->opad_digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA); + state->opad_digest_buff = kzalloc(ctx->inter_digestsize, + GFP_KERNEL | GFP_DMA); if (!state->opad_digest_buff) goto fail2; dev_dbg(dev, "Allocated opad-digest-buffer in context state->digest_bytes_len=@%p\n", state->opad_digest_buff); - state->digest_buff_dma_addr = dma_map_single(dev, (void *)state->digest_buff, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + state->digest_buff_dma_addr = + dma_map_single(dev, (void *)state->digest_buff, + ctx->inter_digestsize, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, state->digest_buff_dma_addr)) { dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n", ctx->inter_digestsize, state->digest_buff); @@ -203,25 +208,39 @@ static int ssi_hash_map_request(struct device *dev, &state->digest_buff_dma_addr); if (is_hmac) { - dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - if ((ctx->hw_mode == DRV_CIPHER_XCBC_MAC) || (ctx->hw_mode == DRV_CIPHER_CMAC)) { + dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); + if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC || + ctx->hw_mode == DRV_CIPHER_CMAC) { memset(state->digest_buff, 0, ctx->inter_digestsize); } else { /*sha*/ - memcpy(state->digest_buff, ctx->digest_buff, ctx->inter_digestsize); + memcpy(state->digest_buff, ctx->digest_buff, + ctx->inter_digestsize); #if (DX_DEV_SHA_MAX > 256) - if (unlikely((ctx->hash_mode == DRV_HASH_SHA512) || (ctx->hash_mode == DRV_HASH_SHA384))) - memcpy(state->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE); + if (ctx->hash_mode == DRV_HASH_SHA512 || + ctx->hash_mode == DRV_HASH_SHA384) + memcpy(state->digest_bytes_len, + digest_len_sha512_init, HASH_LEN_SIZE); else - memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); + memcpy(state->digest_bytes_len, + digest_len_init, HASH_LEN_SIZE); #else - memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); + memcpy(state->digest_bytes_len, digest_len_init, + HASH_LEN_SIZE); #endif } - dma_sync_single_for_device(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + dma_sync_single_for_device(dev, state->digest_buff_dma_addr, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); if (ctx->hash_mode != DRV_HASH_NULL) { - dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - memcpy(state->opad_digest_buff, ctx->opad_tmp_keys_buff, ctx->inter_digestsize); + dma_sync_single_for_cpu(dev, + ctx->opad_tmp_keys_dma_addr, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); + memcpy(state->opad_digest_buff, + ctx->opad_tmp_keys_buff, ctx->inter_digestsize); } } else { /*hash*/ /* Copy the initial digests if hash flow. The SRAM contains the @@ -234,14 +253,16 @@ static int ssi_hash_map_request(struct device *dev, set_flow_mode(&desc, BYPASS); rc = send_request(ctx->drvdata, &ssi_req, &desc, 1, 0); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); goto fail4; } } if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) { - state->digest_bytes_len_dma_addr = dma_map_single(dev, (void *)state->digest_bytes_len, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); + state->digest_bytes_len_dma_addr = + dma_map_single(dev, (void *)state->digest_bytes_len, + HASH_LEN_SIZE, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) { dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n", HASH_LEN_SIZE, state->digest_bytes_len); @@ -255,7 +276,10 @@ static int ssi_hash_map_request(struct device *dev, } if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) { - state->opad_digest_dma_addr = dma_map_single(dev, (void *)state->opad_digest_buff, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + state->opad_digest_dma_addr = + dma_map_single(dev, (void *)state->opad_digest_buff, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, state->opad_digest_dma_addr)) { dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n", ctx->inter_digestsize, @@ -276,13 +300,15 @@ static int ssi_hash_map_request(struct device *dev, return 0; fail5: - if (state->digest_bytes_len_dma_addr != 0) { - dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); + if (state->digest_bytes_len_dma_addr) { + dma_unmap_single(dev, state->digest_bytes_len_dma_addr, + HASH_LEN_SIZE, DMA_BIDIRECTIONAL); state->digest_bytes_len_dma_addr = 0; } fail4: - if (state->digest_buff_dma_addr != 0) { - dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + if (state->digest_buff_dma_addr) { + dma_unmap_single(dev, state->digest_buff_dma_addr, + ctx->inter_digestsize, DMA_BIDIRECTIONAL); state->digest_buff_dma_addr = 0; } fail3: @@ -308,21 +334,21 @@ static void ssi_hash_unmap_request(struct device *dev, struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx) { - if (state->digest_buff_dma_addr != 0) { + if (state->digest_buff_dma_addr) { dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", &state->digest_buff_dma_addr); state->digest_buff_dma_addr = 0; } - if (state->digest_bytes_len_dma_addr != 0) { + if (state->digest_bytes_len_dma_addr) { dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n", &state->digest_bytes_len_dma_addr); state->digest_bytes_len_dma_addr = 0; } - if (state->opad_digest_dma_addr != 0) { + if (state->opad_digest_dma_addr) { dma_unmap_single(dev, state->opad_digest_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n", @@ -342,7 +368,7 @@ static void ssi_hash_unmap_result(struct device *dev, struct ahash_req_ctx *state, unsigned int digestsize, u8 *result) { - if (state->digest_result_dma_addr != 0) { + if (state->digest_result_dma_addr) { dma_unmap_single(dev, state->digest_result_dma_addr, digestsize, @@ -357,18 +383,18 @@ static void ssi_hash_unmap_result(struct device *dev, state->digest_result_dma_addr = 0; } -static void ssi_hash_update_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_hash_update_complete(struct device *dev, void *ssi_req) { struct ahash_request *req = (struct ahash_request *)ssi_req; struct ahash_req_ctx *state = ahash_request_ctx(req); dev_dbg(dev, "req=%pK\n", req); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false); + cc_unmap_hash_request(dev, state, req->src, false); req->base.complete(&req->base, 0); } -static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_hash_digest_complete(struct device *dev, void *ssi_req) { struct ahash_request *req = (struct ahash_request *)ssi_req; struct ahash_req_ctx *state = ahash_request_ctx(req); @@ -378,13 +404,13 @@ static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __i dev_dbg(dev, "req=%pK\n", req); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false); + cc_unmap_hash_request(dev, state, req->src, false); ssi_hash_unmap_result(dev, state, digestsize, req->result); ssi_hash_unmap_request(dev, state, ctx); req->base.complete(&req->base, 0); } -static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_hash_complete(struct device *dev, void *ssi_req) { struct ahash_request *req = (struct ahash_request *)ssi_req; struct ahash_req_ctx *state = ahash_request_ctx(req); @@ -394,7 +420,7 @@ static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *c dev_dbg(dev, "req=%pK\n", req); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false); + cc_unmap_hash_request(dev, state, req->src, false); ssi_hash_unmap_result(dev, state, digestsize, req->result); ssi_hash_unmap_request(dev, state, ctx); req->base.complete(&req->base, 0); @@ -411,25 +437,25 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, bool is_hmac = ctx->is_hmac; struct ssi_crypto_req ssi_req = {}; struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN]; - ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->hash_mode); + ssi_sram_addr_t larval_digest_addr = + cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); int idx = 0; int rc = 0; dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) { + if (ssi_hash_map_request(dev, state, ctx)) { dev_err(dev, "map_ahash_source() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (ssi_hash_map_result(dev, state, digestsize)) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) { + if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -440,7 +466,9 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, ssi_req.user_arg = (void *)async_req; } - /* If HMAC then load hash IPAD xor key, if HASH then load initial digest */ + /* If HMAC then load hash IPAD xor key, if HASH then load initial + * digest + */ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], ctx->hw_mode); if (is_hmac) { @@ -464,7 +492,7 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, NS_BIT); } else { set_din_const(&desc[idx], 0, HASH_LEN_SIZE); - if (likely(nbytes != 0)) + if (nbytes) set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); else set_cipher_do(&desc[idx], DO_PAD); @@ -546,19 +574,19 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); if (async_req) { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); } ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); @@ -587,8 +615,9 @@ static int ssi_hash_update(struct ahash_req_ctx *state, return 0; } - rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, src, nbytes, block_size); - if (unlikely(rc)) { + rc = cc_map_hash_request_update(ctx->drvdata, state, src, nbytes, + block_size); + if (rc) { if (rc == 1) { dev_dbg(dev, " data size not require HW update %x\n", nbytes); @@ -646,17 +675,17 @@ static int ssi_hash_update(struct ahash_req_ctx *state, if (async_req) { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); } } return rc; @@ -680,11 +709,11 @@ static int ssi_hash_finup(struct ahash_req_ctx *state, dev_dbg(dev, "===== %s-finup (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) { + if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (ssi_hash_map_result(dev, state, digestsize)) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -777,19 +806,19 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); if (async_req) { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); } @@ -815,12 +844,12 @@ static int ssi_hash_final(struct ahash_req_ctx *state, dev_dbg(dev, "===== %s-final (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 0) != 0)) { + if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (ssi_hash_map_result(dev, state, digestsize)) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -922,19 +951,19 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); if (async_req) { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); } @@ -953,10 +982,8 @@ static int ssi_hash_init(struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx) return 0; } -static int ssi_hash_setkey(void *hash, - const u8 *key, - unsigned int keylen, - bool synchronize) +static int ssi_ahash_setkey(struct crypto_ahash *ahash, const u8 *key, + unsigned int keylen) { unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; struct ssi_crypto_req ssi_req = {}; @@ -968,15 +995,14 @@ static int ssi_hash_setkey(void *hash, ssi_sram_addr_t larval_addr; struct device *dev; - ctx = crypto_ahash_ctx(((struct crypto_ahash *)hash)); + ctx = crypto_ahash_ctx(ahash); dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "start keylen: %d", keylen); - blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base); - digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash)); + blocksize = crypto_tfm_alg_blocksize(&ahash->base); + digestsize = crypto_ahash_digestsize(ahash); - larval_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->hash_mode); + larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); /* The keylen value distinguishes HASH in case keylen is ZERO bytes, * any NON-ZERO value utilizes HMAC flow @@ -985,12 +1011,11 @@ static int ssi_hash_setkey(void *hash, ctx->key_params.key_dma_addr = 0; ctx->is_hmac = true; - if (keylen != 0) { + if (keylen) { ctx->key_params.key_dma_addr = dma_map_single( dev, (void *)key, keylen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, - ctx->key_params.key_dma_addr))) { + if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) { dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", key, keylen); return -ENOMEM; @@ -1038,8 +1063,9 @@ static int ssi_hash_setkey(void *hash, hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0, (blocksize - digestsize)); set_flow_mode(&desc[idx], BYPASS); - set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr + - digestsize), + set_dout_dlli(&desc[idx], + (ctx->opad_tmp_keys_dma_addr + + digestsize), (blocksize - digestsize), NS_BIT, 0); idx++; } else { @@ -1052,7 +1078,7 @@ static int ssi_hash_setkey(void *hash, keylen, NS_BIT, 0); idx++; - if ((blocksize - keylen) != 0) { + if ((blocksize - keylen)) { hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0, (blocksize - keylen)); @@ -1074,7 +1100,7 @@ static int ssi_hash_setkey(void *hash, } rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); goto out; } @@ -1114,7 +1140,9 @@ static int ssi_hash_setkey(void *hash, set_flow_mode(&desc[idx], DIN_HASH); idx++; - /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest of the first HASH "update" state) */ + /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest + * of the first HASH "update" state) + */ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], ctx->hw_mode); if (i > 0) /* Not first iteration */ @@ -1132,7 +1160,7 @@ static int ssi_hash_setkey(void *hash, out: if (rc) - crypto_ahash_set_flags((struct crypto_ahash *)hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); if (ctx->key_params.key_dma_addr) { dma_unmap_single(dev, ctx->key_params.key_dma_addr, @@ -1168,7 +1196,7 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, ctx->key_params.key_dma_addr = dma_map_single( dev, (void *)key, keylen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, ctx->key_params.key_dma_addr))) { + if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) { dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", key, keylen); return -ENOMEM; @@ -1214,7 +1242,7 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) + if (rc) crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); dma_unmap_single(dev, ctx->key_params.key_dma_addr, @@ -1253,8 +1281,10 @@ static int ssi_cmac_setkey(struct crypto_ahash *ahash, keylen, DMA_TO_DEVICE); memcpy(ctx->opad_tmp_keys_buff, key, keylen); - if (keylen == 24) - memset(ctx->opad_tmp_keys_buff + 24, 0, CC_AES_KEY_SIZE_MAX - 24); + if (keylen == 24) { + memset(ctx->opad_tmp_keys_buff + 24, 0, + CC_AES_KEY_SIZE_MAX - 24); + } dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr, keylen, DMA_TO_DEVICE); @@ -1269,14 +1299,14 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx) { struct device *dev = drvdata_to_dev(ctx->drvdata); - if (ctx->digest_buff_dma_addr != 0) { + if (ctx->digest_buff_dma_addr) { dma_unmap_single(dev, ctx->digest_buff_dma_addr, sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", &ctx->digest_buff_dma_addr); ctx->digest_buff_dma_addr = 0; } - if (ctx->opad_tmp_keys_dma_addr != 0) { + if (ctx->opad_tmp_keys_dma_addr) { dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr, sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL); @@ -1294,7 +1324,9 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx) ctx->key_params.keylen = 0; - ctx->digest_buff_dma_addr = dma_map_single(dev, (void *)ctx->digest_buff, sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); + ctx->digest_buff_dma_addr = + dma_map_single(dev, (void *)ctx->digest_buff, + sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) { dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n", sizeof(ctx->digest_buff), ctx->digest_buff); @@ -1304,7 +1336,10 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx) sizeof(ctx->digest_buff), ctx->digest_buff, &ctx->digest_buff_dma_addr); - ctx->opad_tmp_keys_dma_addr = dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff, sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL); + ctx->opad_tmp_keys_dma_addr = + dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff, + sizeof(ctx->opad_tmp_keys_buff), + DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) { dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n", sizeof(ctx->opad_tmp_keys_buff), @@ -1331,7 +1366,8 @@ static int ssi_ahash_cra_init(struct crypto_tfm *tfm) struct ahash_alg *ahash_alg = container_of(hash_alg_common, struct ahash_alg, halg); struct ssi_hash_alg *ssi_alg = - container_of(ahash_alg, struct ssi_hash_alg, ahash_alg); + container_of(ahash_alg, struct ssi_hash_alg, + ahash_alg); crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), sizeof(struct ahash_req_ctx)); @@ -1372,8 +1408,9 @@ static int ssi_mac_update(struct ahash_request *req) state->xcbc_count++; - rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, req->src, req->nbytes, block_size); - if (unlikely(rc)) { + rc = cc_map_hash_request_update(ctx->drvdata, state, req->src, + req->nbytes, block_size); + if (rc) { if (rc == 1) { dev_dbg(dev, " data size not require HW update %x\n", req->nbytes); @@ -1406,9 +1443,9 @@ static int ssi_mac_update(struct ahash_request *req) ssi_req.user_arg = (void *)req; rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); } return rc; } @@ -1440,12 +1477,13 @@ static int ssi_mac_final(struct ahash_request *req) dev_dbg(dev, "===== final xcbc reminder (%d) ====\n", rem_cnt); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 0) != 0)) { + if (cc_map_hash_request_final(ctx->drvdata, state, req->src, + req->nbytes, 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (ssi_hash_map_result(dev, state, digestsize)) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -1454,7 +1492,7 @@ static int ssi_mac_final(struct ahash_request *req) ssi_req.user_cb = (void *)ssi_hash_complete; ssi_req.user_arg = (void *)req; - if (state->xcbc_count && (rem_cnt == 0)) { + if (state->xcbc_count && rem_cnt == 0) { /* Load key for ECB decryption */ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); @@ -1467,7 +1505,9 @@ static int ssi_mac_final(struct ahash_request *req) set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); idx++; - /* Initiate decryption of block state to previous block_state-XOR-M[n] */ + /* Initiate decryption of block state to previous + * block_state-XOR-M[n] + */ hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT); @@ -1496,7 +1536,8 @@ static int ssi_mac_final(struct ahash_request *req) set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; } else if (rem_cnt > 0) { - ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); + ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, + false, &idx); } else { hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE); @@ -1516,9 +1557,9 @@ static int ssi_mac_final(struct ahash_request *req) idx++; rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); ssi_hash_unmap_result(dev, state, digestsize, req->result); } return rc; @@ -1543,11 +1584,12 @@ static int ssi_mac_finup(struct ahash_request *req) return ssi_mac_final(req); } - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) { + if (cc_map_hash_request_final(ctx->drvdata, state, req->src, + req->nbytes, 1)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (ssi_hash_map_result(dev, state, digestsize)) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -1572,7 +1614,8 @@ static int ssi_mac_finup(struct ahash_request *req) set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; } else { - ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); + ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, + false, &idx); } /* Get final MAC result */ @@ -1587,9 +1630,9 @@ static int ssi_mac_finup(struct ahash_request *req) idx++; rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); ssi_hash_unmap_result(dev, state, digestsize, req->result); } return rc; @@ -1610,16 +1653,17 @@ static int ssi_mac_digest(struct ahash_request *req) dev_dbg(dev, "===== -digest mac (%d) ====\n", req->nbytes); - if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) { + if (ssi_hash_map_request(dev, state, ctx)) { dev_err(dev, "map_ahash_source() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (ssi_hash_map_result(dev, state, digestsize)) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) { + if (cc_map_hash_request_final(ctx->drvdata, state, req->src, + req->nbytes, 1)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -1644,7 +1688,8 @@ static int ssi_mac_digest(struct ahash_request *req) set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; } else { - ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); + ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, + false, &idx); } /* Get final MAC result */ @@ -1659,9 +1704,9 @@ static int ssi_mac_digest(struct ahash_request *req) idx++; rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); - if (unlikely(rc != -EINPROGRESS)) { + if (rc != -EINPROGRESS) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); ssi_hash_unmap_result(dev, state, digestsize, req->result); ssi_hash_unmap_request(dev, state, ctx); } @@ -1676,7 +1721,8 @@ static int ssi_ahash_digest(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 digestsize = crypto_ahash_digestsize(tfm); - return ssi_hash_digest(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req); + return ssi_hash_digest(state, ctx, digestsize, req->src, req->nbytes, + req->result, (void *)req); } static int ssi_ahash_update(struct ahash_request *req) @@ -1686,7 +1732,8 @@ static int ssi_ahash_update(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base); - return ssi_hash_update(state, ctx, block_size, req->src, req->nbytes, (void *)req); + return ssi_hash_update(state, ctx, block_size, req->src, req->nbytes, + (void *)req); } static int ssi_ahash_finup(struct ahash_request *req) @@ -1696,7 +1743,8 @@ static int ssi_ahash_finup(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 digestsize = crypto_ahash_digestsize(tfm); - return ssi_hash_finup(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req); + return ssi_hash_finup(state, ctx, digestsize, req->src, req->nbytes, + req->result, (void *)req); } static int ssi_ahash_final(struct ahash_request *req) @@ -1706,7 +1754,8 @@ static int ssi_ahash_final(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 digestsize = crypto_ahash_digestsize(tfm); - return ssi_hash_final(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req); + return ssi_hash_final(state, ctx, digestsize, req->src, req->nbytes, + req->result, (void *)req); } static int ssi_ahash_init(struct ahash_request *req) @@ -1822,12 +1871,6 @@ out: return rc; } -static int ssi_ahash_setkey(struct crypto_ahash *ahash, - const u8 *key, unsigned int keylen) -{ - return ssi_hash_setkey((void *)ahash, key, keylen, false); -} - struct ssi_hash_template { char name[CRYPTO_MAX_ALG_NAME]; char driver_name[CRYPTO_MAX_ALG_NAME]; @@ -2056,7 +2099,6 @@ ssi_hash_create_alg(struct ssi_hash_template *template, struct device *dev, if (!t_crypto_alg) return ERR_PTR(-ENOMEM); - t_crypto_alg->ahash_alg = template->template_ahash; halg = &t_crypto_alg->ahash_alg; alg = &halg->halg.base; @@ -2105,11 +2147,11 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) #endif /* Copy-to-sram digest-len */ - ssi_sram_mgr_const2sram_desc(digest_len_init, sram_buff_ofs, - ARRAY_SIZE(digest_len_init), - larval_seq, &larval_seq_len); + cc_set_sram_desc(digest_len_init, sram_buff_ofs, + ARRAY_SIZE(digest_len_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (rc) goto init_digest_const_err; sram_buff_ofs += sizeof(digest_len_init); @@ -2117,11 +2159,11 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) #if (DX_DEV_SHA_MAX > 256) /* Copy-to-sram digest-len for sha384/512 */ - ssi_sram_mgr_const2sram_desc(digest_len_sha512_init, sram_buff_ofs, - ARRAY_SIZE(digest_len_sha512_init), - larval_seq, &larval_seq_len); + cc_set_sram_desc(digest_len_sha512_init, sram_buff_ofs, + ARRAY_SIZE(digest_len_sha512_init), + larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (rc) goto init_digest_const_err; sram_buff_ofs += sizeof(digest_len_sha512_init); @@ -2132,57 +2174,59 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) hash_handle->larval_digest_sram_addr = sram_buff_ofs; /* Copy-to-sram initial SHA* digests */ - ssi_sram_mgr_const2sram_desc(md5_init, sram_buff_ofs, - ARRAY_SIZE(md5_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(md5_init, sram_buff_ofs, + ARRAY_SIZE(md5_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (rc) goto init_digest_const_err; sram_buff_ofs += sizeof(md5_init); larval_seq_len = 0; - ssi_sram_mgr_const2sram_desc(sha1_init, sram_buff_ofs, - ARRAY_SIZE(sha1_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(sha1_init, sram_buff_ofs, + ARRAY_SIZE(sha1_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (rc) goto init_digest_const_err; sram_buff_ofs += sizeof(sha1_init); larval_seq_len = 0; - ssi_sram_mgr_const2sram_desc(sha224_init, sram_buff_ofs, - ARRAY_SIZE(sha224_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(sha224_init, sram_buff_ofs, + ARRAY_SIZE(sha224_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (rc) goto init_digest_const_err; sram_buff_ofs += sizeof(sha224_init); larval_seq_len = 0; - ssi_sram_mgr_const2sram_desc(sha256_init, sram_buff_ofs, - ARRAY_SIZE(sha256_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(sha256_init, sram_buff_ofs, + ARRAY_SIZE(sha256_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (rc) goto init_digest_const_err; sram_buff_ofs += sizeof(sha256_init); larval_seq_len = 0; #if (DX_DEV_SHA_MAX > 256) - /* We are forced to swap each double-word larval before copying to sram */ + /* We are forced to swap each double-word larval before copying to + * sram + */ for (i = 0; i < ARRAY_SIZE(sha384_init); i++) { const u32 const0 = ((u32 *)((u64 *)&sha384_init[i]))[1]; const u32 const1 = ((u32 *)((u64 *)&sha384_init[i]))[0]; - ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const0, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); - ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const1, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); } rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "send_request() failed (rc = %d)\n", rc); goto init_digest_const_err; } @@ -2192,15 +2236,15 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) const u32 const0 = ((u32 *)((u64 *)&sha512_init[i]))[1]; const u32 const1 = ((u32 *)((u64 *)&sha512_init[i]))[0]; - ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const0, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); - ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const1, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); } rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "send_request() failed (rc = %d)\n", rc); goto init_digest_const_err; } @@ -2237,7 +2281,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) sizeof(sha224_init) + sizeof(sha256_init); - sram_buff = ssi_sram_mgr_alloc(drvdata, sram_size_to_alloc); + sram_buff = cc_sram_alloc(drvdata, sram_size_to_alloc); if (sram_buff == NULL_SRAM_ADDR) { dev_err(dev, "SRAM pool exhausted\n"); rc = -ENOMEM; @@ -2249,7 +2293,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) /*must be set before the alg registration as it is being used there*/ rc = ssi_hash_init_sram_digest_consts(drvdata); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc); goto fail; } @@ -2270,7 +2314,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) t_alg->drvdata = drvdata; rc = crypto_register_ahash(&t_alg->ahash_alg); - if (unlikely(rc)) { + if (rc) { dev_err(dev, "%s alg registration failed\n", driver_hash[alg].driver_name); kfree(t_alg); @@ -2280,8 +2324,8 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) &hash_handle->hash_list); } - if ((hw_mode == DRV_CIPHER_XCBC_MAC) || - (hw_mode == DRV_CIPHER_CMAC)) + if (hw_mode == DRV_CIPHER_XCBC_MAC || + hw_mode == DRV_CIPHER_CMAC) continue; /* register hash version */ @@ -2295,7 +2339,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) t_alg->drvdata = drvdata; rc = crypto_register_ahash(&t_alg->ahash_alg); - if (unlikely(rc)) { + if (rc) { dev_err(dev, "%s alg registration failed\n", driver_hash[alg].driver_name); kfree(t_alg); @@ -2319,7 +2363,8 @@ int ssi_hash_free(struct ssi_drvdata *drvdata) struct ssi_hash_handle *hash_handle = drvdata->hash_handle; if (hash_handle) { - list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list, entry) { + list_for_each_entry_safe(t_hash_alg, hash_n, + &hash_handle->hash_list, entry) { crypto_unregister_ahash(&t_hash_alg->ahash_alg); list_del(&t_hash_alg->entry); kfree(t_hash_alg); @@ -2433,7 +2478,7 @@ static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx, unsigned int idx = *seq_size; struct device *dev = drvdata_to_dev(ctx->drvdata); - if (likely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_DLLI)) { + if (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_DLLI) { hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq_ctx->curr_sg), @@ -2476,9 +2521,9 @@ static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx, * \param drvdata * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256 * - * \return u32 The address of the inital digest in SRAM + * \return u32 The address of the initial digest in SRAM */ -ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode) +ssi_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode) { struct ssi_drvdata *_drvdata = (struct ssi_drvdata *)drvdata; struct ssi_hash_handle *hash_handle = _drvdata->hash_handle; diff --git a/drivers/staging/ccree/ssi_hash.h b/drivers/staging/ccree/ssi_hash.h index 2400e389d65a..32eb47388f93 100644 --- a/drivers/staging/ccree/ssi_hash.h +++ b/drivers/staging/ccree/ssi_hash.h @@ -41,7 +41,9 @@ #define CC_EXPORT_MAGIC 0xC2EE1070U -// this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used for xcbc/cmac statesize +/* this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used + * for xcbc/cmac statesize + */ struct aeshash_state { u8 state[AES_BLOCK_SIZE]; unsigned int count; @@ -81,7 +83,8 @@ int ssi_hash_free(struct ssi_drvdata *drvdata); * Gets the initial digest length * * \param drvdata - * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512 + * \param mode The Hash mode. Supported modes: + * MD5/SHA1/SHA224/SHA256/SHA384/SHA512 * * \return u32 returns the address of the initial digest length in SRAM */ @@ -93,11 +96,12 @@ ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode); * according to the given hash mode * * \param drvdata - * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512 + * \param mode The Hash mode. Supported modes: + * MD5/SHA1/SHA224/SHA256/SHA384/SHA512 * - * \return u32 The address of the inital digest in SRAM + * \return u32 The address of the initial digest in SRAM */ -ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode); +ssi_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode); #endif /*__SSI_HASH_H__*/ diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 3f082f41ae8f..febee22e9c56 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -143,7 +143,7 @@ int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata) /* Generate initial pool */ rc = ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, &iv_seq_len); - if (unlikely(rc != 0)) + if (rc) return rc; /* Fire-and-forget */ @@ -198,7 +198,7 @@ int ssi_ivgen_init(struct ssi_drvdata *drvdata) ivgen_ctx = drvdata->ivgen_handle; - /* Allocate pool's header for intial enc. key/IV */ + /* Allocate pool's header for initial enc. key/IV */ ivgen_ctx->pool_meta = dma_alloc_coherent(device, SSI_IVPOOL_META_SIZE, &ivgen_ctx->pool_meta_dma, GFP_KERNEL); @@ -209,7 +209,7 @@ int ssi_ivgen_init(struct ssi_drvdata *drvdata) goto out; } /* Allocate IV pool in SRAM */ - ivgen_ctx->pool = ssi_sram_mgr_alloc(drvdata, SSI_IVPOOL_SIZE); + ivgen_ctx->pool = cc_sram_alloc(drvdata, SSI_IVPOOL_SIZE); if (ivgen_ctx->pool == NULL_SRAM_ADDR) { dev_err(device, "SRAM pool exhausted\n"); rc = -ENOMEM; @@ -228,7 +228,8 @@ out: * * \param drvdata Driver private context * \param iv_out_dma Array of physical IV out addresses - * \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore) + * \param iv_out_dma_len Length of iv_out_dma array (additional elements + * of iv_out_dma array are ignore) * \param iv_out_size May be 8 or 16 bytes long * \param iv_seq IN/OUT array to the descriptors sequence * \param iv_seq_len IN/OUT pointer to the sequence length @@ -248,8 +249,8 @@ int ssi_ivgen_getiv( struct device *dev = drvdata_to_dev(drvdata); unsigned int t; - if ((iv_out_size != CC_AES_IV_SIZE) && - (iv_out_size != CTR_RFC3686_IV_SIZE)) { + if (iv_out_size != CC_AES_IV_SIZE && + iv_out_size != CTR_RFC3686_IV_SIZE) { return -EINVAL; } if ((iv_out_dma_len + 1) > SSI_IVPOOL_SEQ_LEN) { @@ -257,7 +258,9 @@ int ssi_ivgen_getiv( return -EINVAL; } - //check that number of generated IV is limited to max dma address iv buffer size + /* check that number of generated IV is limited to max dma address + * iv buffer size + */ if (iv_out_dma_len > SSI_MAX_IVGEN_DMA_ADDRESSES) { /* The sequence will be longer than allowed */ return -EINVAL; diff --git a/drivers/staging/ccree/ssi_ivgen.h b/drivers/staging/ccree/ssi_ivgen.h index 961aea411cb3..fd28309adac6 100644 --- a/drivers/staging/ccree/ssi_ivgen.h +++ b/drivers/staging/ccree/ssi_ivgen.h @@ -53,7 +53,8 @@ int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata); * * \param drvdata Driver private context * \param iv_out_dma Array of physical IV out addresses - * \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore) + * \param iv_out_dma_len Length of iv_out_dma array (additional elements of + * iv_out_dma array are ignore) * \param iv_out_size May be 8 or 16 bytes long * \param iv_seq IN/OUT array to the descriptors sequence * \param iv_seq_len IN/OUT pointer to the sequence length diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c index 36a498098a70..5e2ef5e1226c 100644 --- a/drivers/staging/ccree/ssi_pm.c +++ b/drivers/staging/ccree/ssi_pm.c @@ -29,22 +29,21 @@ #include "ssi_hash.h" #include "ssi_pm.h" -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) #define POWER_DOWN_ENABLE 0x01 #define POWER_DOWN_DISABLE 0x00 -int ssi_power_mgr_runtime_suspend(struct device *dev) +int cc_pm_suspend(struct device *dev) { - struct ssi_drvdata *drvdata = - (struct ssi_drvdata *)dev_get_drvdata(dev); + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); int rc; dev_dbg(dev, "set HOST_POWER_DOWN_EN\n"); cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE); - rc = ssi_request_mgr_runtime_suspend_queue(drvdata); - if (rc != 0) { - dev_err(dev, "ssi_request_mgr_runtime_suspend_queue (%x)\n", + rc = cc_suspend_req_queue(drvdata); + if (rc) { + dev_err(dev, "cc_suspend_req_queue (%x)\n", rc); return rc; } @@ -53,11 +52,10 @@ int ssi_power_mgr_runtime_suspend(struct device *dev) return 0; } -int ssi_power_mgr_runtime_resume(struct device *dev) +int cc_pm_resume(struct device *dev) { int rc; - struct ssi_drvdata *drvdata = - (struct ssi_drvdata *)dev_get_drvdata(dev); + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); dev_dbg(dev, "unset HOST_POWER_DOWN_EN\n"); cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE); @@ -69,14 +67,14 @@ int ssi_power_mgr_runtime_resume(struct device *dev) } rc = init_cc_regs(drvdata, false); - if (rc != 0) { + if (rc) { dev_err(dev, "init_cc_regs (%x)\n", rc); return rc; } - rc = ssi_request_mgr_runtime_resume_queue(drvdata); - if (rc != 0) { - dev_err(dev, "ssi_request_mgr_runtime_resume_queue (%x)\n", rc); + rc = cc_resume_req_queue(drvdata); + if (rc) { + dev_err(dev, "cc_resume_req_queue (%x)\n", rc); return rc; } @@ -87,25 +85,25 @@ int ssi_power_mgr_runtime_resume(struct device *dev) return 0; } -int ssi_power_mgr_runtime_get(struct device *dev) +int cc_pm_get(struct device *dev) { int rc = 0; + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); - if (ssi_request_mgr_is_queue_runtime_suspend( - (struct ssi_drvdata *)dev_get_drvdata(dev))) { + if (cc_req_queue_suspended(drvdata)) rc = pm_runtime_get_sync(dev); - } else { + else pm_runtime_get_noresume(dev); - } + return rc; } -int ssi_power_mgr_runtime_put_suspend(struct device *dev) +int cc_pm_put_suspend(struct device *dev) { int rc = 0; + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); - if (!ssi_request_mgr_is_queue_runtime_suspend( - (struct ssi_drvdata *)dev_get_drvdata(dev))) { + if (!cc_req_queue_suspended(drvdata)) { pm_runtime_mark_last_busy(dev); rc = pm_runtime_put_autosuspend(dev); } else { @@ -118,10 +116,10 @@ int ssi_power_mgr_runtime_put_suspend(struct device *dev) #endif -int ssi_power_mgr_init(struct ssi_drvdata *drvdata) +int cc_pm_init(struct ssi_drvdata *drvdata) { int rc = 0; -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) struct device *dev = drvdata_to_dev(drvdata); /* must be before the enabling to avoid resdundent suspending */ @@ -129,7 +127,7 @@ int ssi_power_mgr_init(struct ssi_drvdata *drvdata) pm_runtime_use_autosuspend(dev); /* activate the PM module */ rc = pm_runtime_set_active(dev); - if (rc != 0) + if (rc) return rc; /* enable the PM module*/ pm_runtime_enable(dev); @@ -137,9 +135,9 @@ int ssi_power_mgr_init(struct ssi_drvdata *drvdata) return rc; } -void ssi_power_mgr_fini(struct ssi_drvdata *drvdata) +void cc_pm_fini(struct ssi_drvdata *drvdata) { -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) pm_runtime_disable(drvdata_to_dev(drvdata)); #endif } diff --git a/drivers/staging/ccree/ssi_pm.h b/drivers/staging/ccree/ssi_pm.h index 63673f60d2d8..50bcf037dead 100644 --- a/drivers/staging/ccree/ssi_pm.h +++ b/drivers/staging/ccree/ssi_pm.h @@ -25,18 +25,18 @@ #define SSI_SUSPEND_TIMEOUT 3000 -int ssi_power_mgr_init(struct ssi_drvdata *drvdata); +int cc_pm_init(struct ssi_drvdata *drvdata); -void ssi_power_mgr_fini(struct ssi_drvdata *drvdata); +void cc_pm_fini(struct ssi_drvdata *drvdata); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) -int ssi_power_mgr_runtime_suspend(struct device *dev); +#if defined(CONFIG_PM) +int cc_pm_suspend(struct device *dev); -int ssi_power_mgr_runtime_resume(struct device *dev); +int cc_pm_resume(struct device *dev); -int ssi_power_mgr_runtime_get(struct device *dev); +int cc_pm_get(struct device *dev); -int ssi_power_mgr_runtime_put_suspend(struct device *dev); +int cc_pm_put_suspend(struct device *dev); #endif #endif /*__POWER_MGR_H__*/ diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index a8a7dc672d4c..5f3433620970 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -43,6 +43,9 @@ struct ssi_request_mgr_handle { u32 req_queue_tail; u32 axi_completed; u32 q_free_slots; + /* This lock protects access to HW register + * that must be single request at a time + */ spinlock_t hw_lock; struct cc_hw_desc compl_desc; u8 *dummy_comp_buff; @@ -55,7 +58,7 @@ struct ssi_request_mgr_handle { #else struct tasklet_struct comptask; #endif -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) bool is_runtime_suspended; #endif }; @@ -73,7 +76,7 @@ void request_mgr_fini(struct ssi_drvdata *drvdata) if (!req_mgr_h) return; /* Not allocated */ - if (req_mgr_h->dummy_comp_buff_dma != 0) { + if (req_mgr_h->dummy_comp_buff_dma) { dma_free_coherent(dev, sizeof(u32), req_mgr_h->dummy_comp_buff, req_mgr_h->dummy_comp_buff_dma); } @@ -112,7 +115,7 @@ int request_mgr_init(struct ssi_drvdata *drvdata) #ifdef COMP_IN_WQ dev_dbg(dev, "Initializing completion workqueue\n"); req_mgr_h->workq = create_singlethread_workqueue("arm_cc7x_wq"); - if (unlikely(!req_mgr_h->workq)) { + if (!req_mgr_h->workq) { dev_err(dev, "Failed creating work queue\n"); rc = -ENOMEM; goto req_mgr_init_err; @@ -120,7 +123,8 @@ int request_mgr_init(struct ssi_drvdata *drvdata) INIT_DELAYED_WORK(&req_mgr_h->compwork, comp_work_handler); #else dev_dbg(dev, "Initializing completion tasklet\n"); - tasklet_init(&req_mgr_h->comptask, comp_handler, (unsigned long)drvdata); + tasklet_init(&req_mgr_h->comptask, comp_handler, + (unsigned long)drvdata); #endif req_mgr_h->hw_queue_size = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_SRAM_SIZE)); @@ -135,9 +139,10 @@ int request_mgr_init(struct ssi_drvdata *drvdata) req_mgr_h->max_used_sw_slots = 0; /* Allocate DMA word for "dummy" completion descriptor use */ - req_mgr_h->dummy_comp_buff = dma_alloc_coherent(dev, sizeof(u32), - &req_mgr_h->dummy_comp_buff_dma, - GFP_KERNEL); + req_mgr_h->dummy_comp_buff = + dma_alloc_coherent(dev, sizeof(u32), + &req_mgr_h->dummy_comp_buff_dma, + GFP_KERNEL); if (!req_mgr_h->dummy_comp_buff) { dev_err(dev, "Not enough memory to allocate DMA (%zu) dropped buffer\n", sizeof(u32)); @@ -160,20 +165,21 @@ req_mgr_init_err: return rc; } -static inline void enqueue_seq( +static void enqueue_seq( void __iomem *cc_base, struct cc_hw_desc seq[], unsigned int seq_len) { - int i; + int i, w; + void * __iomem reg = cc_base + CC_REG(DSCRPTR_QUEUE_WORD0); + + /* + * We do indeed write all 6 command words to the same + * register. The HW supports this. + */ for (i = 0; i < seq_len; i++) { - writel_relaxed(seq[i].word[0], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[1], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[2], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[3], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[4], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - wmb(); - writel_relaxed(seq[i].word[5], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + for (w = 0; w <= 5; w++) + writel_relaxed(seq[i].word[w], reg); #ifdef DX_DUMP_DESCS dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n", i, seq[i].word[0], seq[i].word[1], seq[i].word[2], @@ -189,14 +195,14 @@ static inline void enqueue_seq( * \param dev * \param dx_compl_h The completion event to signal */ -static void request_mgr_complete(struct device *dev, void *dx_compl_h, void __iomem *cc_base) +static void request_mgr_complete(struct device *dev, void *dx_compl_h) { struct completion *this_compl = dx_compl_h; complete(this_compl); } -static inline int request_mgr_queues_status_check( +static int request_mgr_queues_status_check( struct ssi_drvdata *drvdata, struct ssi_request_mgr_handle *req_mgr_h, unsigned int total_seq_len) @@ -205,30 +211,27 @@ static inline int request_mgr_queues_status_check( struct device *dev = drvdata_to_dev(drvdata); /* SW queue is checked only once as it will not - * be chaned during the poll becasue the spinlock_bh + * be chaned during the poll because the spinlock_bh * is held by the thread */ - if (unlikely(((req_mgr_h->req_queue_head + 1) & - (MAX_REQUEST_QUEUE_SIZE - 1)) == - req_mgr_h->req_queue_tail)) { + if (((req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1)) == + req_mgr_h->req_queue_tail) { dev_err(dev, "SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n", req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE); return -EBUSY; } - if ((likely(req_mgr_h->q_free_slots >= total_seq_len))) + if (req_mgr_h->q_free_slots >= total_seq_len) return 0; /* Wait for space in HW queue. Poll constant num of iterations. */ for (poll_queue = 0; poll_queue < SSI_MAX_POLL_ITER ; poll_queue++) { req_mgr_h->q_free_slots = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT)); - if (unlikely(req_mgr_h->q_free_slots < - req_mgr_h->min_free_hw_slots)) { + if (req_mgr_h->q_free_slots < req_mgr_h->min_free_hw_slots) req_mgr_h->min_free_hw_slots = req_mgr_h->q_free_slots; - } - if (likely(req_mgr_h->q_free_slots >= total_seq_len)) { + if (req_mgr_h->q_free_slots >= total_seq_len) { /* If there is enough place return */ return 0; } @@ -268,14 +271,14 @@ int send_request( struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN]; struct device *dev = drvdata_to_dev(drvdata); int rc; - unsigned int max_required_seq_len = (total_seq_len + - ((ssi_req->ivgen_dma_addr_len == 0) ? 0 : - SSI_IVPOOL_SEQ_LEN) + - (!is_dout ? 1 : 0)); - -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - rc = ssi_power_mgr_runtime_get(dev); - if (rc != 0) { + unsigned int max_required_seq_len = + (total_seq_len + + ((ssi_req->ivgen_dma_addr_len == 0) ? 0 : + SSI_IVPOOL_SEQ_LEN) + (!is_dout ? 1 : 0)); + +#if defined(CONFIG_PM) + rc = cc_pm_get(dev); + if (rc) { dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc); return rc; } @@ -290,7 +293,7 @@ int send_request( */ rc = request_mgr_queues_status_check(drvdata, req_mgr_h, max_required_seq_len); - if (likely(rc == 0)) + if (rc == 0) /* There is enough place in the queue */ break; /* something wrong release the spinlock*/ @@ -300,14 +303,15 @@ int send_request( /* Any error other than HW queue full * (SW queue is full) */ -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - ssi_power_mgr_runtime_put_suspend(dev); +#if defined(CONFIG_PM) + cc_pm_put_suspend(dev); #endif return rc; } - /* HW queue is full - short sleep */ - msleep(1); + /* HW queue is full - wait for it to clear up */ + wait_for_completion_interruptible(&drvdata->hw_queue_avail); + reinit_completion(&drvdata->hw_queue_avail); } while (1); /* Additional completion descriptor is needed incase caller did not @@ -333,11 +337,11 @@ int send_request( ssi_req->ivgen_dma_addr_len, ssi_req->ivgen_size, iv_seq, &iv_seq_len); - if (unlikely(rc != 0)) { + if (rc) { dev_err(dev, "Failed to generate IV (rc=%d)\n", rc); spin_unlock_bh(&req_mgr_h->hw_lock); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - ssi_power_mgr_runtime_put_suspend(dev); +#if defined(CONFIG_PM) + cc_pm_put_suspend(dev); #endif return rc; } @@ -345,13 +349,16 @@ int send_request( total_seq_len += iv_seq_len; } - used_sw_slots = ((req_mgr_h->req_queue_head - req_mgr_h->req_queue_tail) & (MAX_REQUEST_QUEUE_SIZE - 1)); - if (unlikely(used_sw_slots > req_mgr_h->max_used_sw_slots)) + used_sw_slots = ((req_mgr_h->req_queue_head - + req_mgr_h->req_queue_tail) & + (MAX_REQUEST_QUEUE_SIZE - 1)); + if (used_sw_slots > req_mgr_h->max_used_sw_slots) req_mgr_h->max_used_sw_slots = used_sw_slots; /* Enqueue request - must be locked with HW lock*/ req_mgr_h->req_queue[req_mgr_h->req_queue_head] = *ssi_req; - req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); + req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) & + (MAX_REQUEST_QUEUE_SIZE - 1); /* TODO: Use circ_buf.h ? */ dev_dbg(dev, "Enqueue request head=%u\n", req_mgr_h->req_queue_head); @@ -359,13 +366,19 @@ int send_request( #ifdef FLUSH_CACHE_ALL flush_cache_all(); #endif + /* + * We are about to push command to the HW via the command registers + * that may refernece hsot memory. We need to issue a memory barrier + * to make sure there are no outstnading memory writes + */ + wmb(); /* STAT_PHASE_4: Push sequence */ enqueue_seq(cc_base, iv_seq, iv_seq_len); enqueue_seq(cc_base, desc, len); enqueue_seq(cc_base, &req_mgr_h->compl_desc, (is_dout ? 0 : 1)); - if (unlikely(req_mgr_h->q_free_slots < total_seq_len)) { + if (req_mgr_h->q_free_slots < total_seq_len) { /* This situation should never occur. Maybe indicating problem * with resuming power. Set the free slot count to 0 and hope * for the best. @@ -409,14 +422,21 @@ int send_request_init( unsigned int total_seq_len = len; /*initial sequence length*/ int rc = 0; - /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. */ + /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. + */ rc = request_mgr_queues_status_check(drvdata, req_mgr_h, total_seq_len); - if (unlikely(rc != 0)) + if (rc) return rc; set_queue_last_ind(&desc[(len - 1)]); + /* + * We are about to push command to the HW via the command registers + * that may refernece hsot memory. We need to issue a memory barrier + * to make sure there are no outstnading memory writes + */ + wmb(); enqueue_seq(cc_base, desc, len); /* Update the free slots in HW queue */ @@ -430,8 +450,11 @@ void complete_request(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; + + complete(&drvdata->hw_queue_avail); #ifdef COMP_IN_WQ - queue_delayed_work(request_mgr_handle->workq, &request_mgr_handle->compwork, 0); + queue_delayed_work(request_mgr_handle->workq, + &request_mgr_handle->compwork, 0); #else tasklet_schedule(&request_mgr_handle->comptask); #endif @@ -453,7 +476,9 @@ static void proc_completions(struct ssi_drvdata *drvdata) struct device *dev = drvdata_to_dev(drvdata); struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) + unsigned int *tail = &request_mgr_handle->req_queue_tail; + unsigned int *head = &request_mgr_handle->req_queue_head; +#if defined(CONFIG_PM) int rc = 0; #endif @@ -461,17 +486,17 @@ static void proc_completions(struct ssi_drvdata *drvdata) request_mgr_handle->axi_completed--; /* Dequeue request */ - if (unlikely(request_mgr_handle->req_queue_head == request_mgr_handle->req_queue_tail)) { + if (*head == *tail) { /* We are supposed to handle a completion but our * queue is empty. This is not normal. Return and * hope for the best. */ dev_err(dev, "Request queue is empty head == tail %u\n", - request_mgr_handle->req_queue_head); + *head); break; } - ssi_req = &request_mgr_handle->req_queue[request_mgr_handle->req_queue_tail]; + ssi_req = &request_mgr_handle->req_queue[*tail]; #ifdef FLUSH_CACHE_ALL flush_cache_all(); @@ -490,17 +515,15 @@ static void proc_completions(struct ssi_drvdata *drvdata) } #endif /* COMPLETION_DELAY */ - if (likely(ssi_req->user_cb)) - ssi_req->user_cb(dev, ssi_req->user_arg, - drvdata->cc_base); - request_mgr_handle->req_queue_tail = (request_mgr_handle->req_queue_tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); - dev_dbg(dev, "Dequeue request tail=%u\n", - request_mgr_handle->req_queue_tail); + if (ssi_req->user_cb) + ssi_req->user_cb(dev, ssi_req->user_arg); + *tail = (*tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); + dev_dbg(dev, "Dequeue request tail=%u\n", *tail); dev_dbg(dev, "Request completed. axi_completed=%d\n", request_mgr_handle->axi_completed); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - rc = ssi_power_mgr_runtime_put_suspend(dev); - if (rc != 0) +#if defined(CONFIG_PM) + rc = cc_pm_put_suspend(dev); + if (rc) dev_err(dev, "Failed to set runtime suspension %d\n", rc); #endif @@ -561,13 +584,14 @@ static void comp_handler(unsigned long devarg) } /* - * resume the queue configuration - no need to take the lock as this happens inside - * the spin lock protection + * resume the queue configuration - no need to take the lock as this happens + * inside the spin lock protection */ -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) -int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata) +#if defined(CONFIG_PM) +int cc_resume_req_queue(struct ssi_drvdata *drvdata) { - struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; + struct ssi_request_mgr_handle *request_mgr_handle = + drvdata->request_mgr_handle; spin_lock_bh(&request_mgr_handle->hw_lock); request_mgr_handle->is_runtime_suspended = false; @@ -580,7 +604,7 @@ int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata) * suspend the queue configuration. Since it is used for the runtime suspend * only verify that the queue can be suspended. */ -int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata) +int cc_suspend_req_queue(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; @@ -598,7 +622,7 @@ int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata) return 0; } -bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata) +bool cc_req_queue_suspended(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; diff --git a/drivers/staging/ccree/ssi_request_mgr.h b/drivers/staging/ccree/ssi_request_mgr.h index bdbbf89e5367..53eed5f10ae9 100644 --- a/drivers/staging/ccree/ssi_request_mgr.h +++ b/drivers/staging/ccree/ssi_request_mgr.h @@ -36,7 +36,7 @@ int request_mgr_init(struct ssi_drvdata *drvdata); * If "false": this function adds a dummy descriptor completion * and waits upon completion signal. * - * \return int Returns -EINPROGRESS if "is_dout=ture"; "0" if "is_dout=false" + * \return int Returns -EINPROGRESS if "is_dout=true"; "0" if "is_dout=false" */ int send_request( struct ssi_drvdata *drvdata, struct ssi_crypto_req *ssi_req, @@ -49,12 +49,12 @@ void complete_request(struct ssi_drvdata *drvdata); void request_mgr_fini(struct ssi_drvdata *drvdata); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) -int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata); +#if defined(CONFIG_PM) +int cc_resume_req_queue(struct ssi_drvdata *drvdata); -int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata); +int cc_suspend_req_queue(struct ssi_drvdata *drvdata); -bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata); +bool cc_req_queue_suspended(struct ssi_drvdata *drvdata); #endif #endif /*__REQUEST_MGR_H__*/ diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c index 07260d168c91..07040310fe4d 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.c +++ b/drivers/staging/ccree/ssi_sram_mgr.c @@ -51,7 +51,7 @@ void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata) int ssi_sram_mgr_init(struct ssi_drvdata *drvdata) { /* Allocate "this" context */ - drvdata->sram_mgr_handle = kzalloc(sizeof(struct ssi_sram_mgr_ctx), + drvdata->sram_mgr_handle = kzalloc(sizeof(*drvdata->sram_mgr_handle), GFP_KERNEL); if (!drvdata->sram_mgr_handle) @@ -69,18 +69,18 @@ int ssi_sram_mgr_init(struct ssi_drvdata *drvdata) * \param drvdata * \param size The requested bytes to allocate */ -ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) +ssi_sram_addr_t cc_sram_alloc(struct ssi_drvdata *drvdata, u32 size) { struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle; struct device *dev = drvdata_to_dev(drvdata); ssi_sram_addr_t p; - if (unlikely((size & 0x3) != 0)) { + if ((size & 0x3)) { dev_err(dev, "Requested buffer size (%u) is not multiple of 4", size); return NULL_SRAM_ADDR; } - if (unlikely(size > (SSI_CC_SRAM_SIZE - smgr_ctx->sram_free_offset))) { + if (size > (SSI_CC_SRAM_SIZE - smgr_ctx->sram_free_offset)) { dev_err(dev, "Not enough space to allocate %u B (at offset %llu)\n", size, smgr_ctx->sram_free_offset); return NULL_SRAM_ADDR; @@ -93,7 +93,7 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) } /** - * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to + * cc_set_sram_desc() - Create const descriptors sequence to * set values in given array into SRAM. * Note: each const value can't exceed word size. * @@ -103,10 +103,9 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) * @seq: A pointer to the given IN/OUT descriptor sequence * @seq_len: A pointer to the given IN/OUT sequence length */ -void ssi_sram_mgr_const2sram_desc( - const u32 *src, ssi_sram_addr_t dst, - unsigned int nelement, - struct cc_hw_desc *seq, unsigned int *seq_len) +void cc_set_sram_desc(const u32 *src, ssi_sram_addr_t dst, + unsigned int nelement, struct cc_hw_desc *seq, + unsigned int *seq_len) { u32 i; unsigned int idx = *seq_len; diff --git a/drivers/staging/ccree/ssi_sram_mgr.h b/drivers/staging/ccree/ssi_sram_mgr.h index 9ba1d59a0bae..9e392622962a 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.h +++ b/drivers/staging/ccree/ssi_sram_mgr.h @@ -58,10 +58,10 @@ void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata); * \param drvdata * \param size The requested bytes to allocate */ -ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size); +ssi_sram_addr_t cc_sram_alloc(struct ssi_drvdata *drvdata, u32 size); /** - * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to + * cc_set_sram_desc() - Create const descriptors sequence to * set values in given array into SRAM. * Note: each const value can't exceed word size. * @@ -71,7 +71,7 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size); * @seq: A pointer to the given IN/OUT descriptor sequence * @seq_len: A pointer to the given IN/OUT sequence length */ -void ssi_sram_mgr_const2sram_desc( +void cc_set_sram_desc( const u32 *src, ssi_sram_addr_t dst, unsigned int nelement, struct cc_hw_desc *seq, unsigned int *seq_len); diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 5d39f15cdb59..08858a4e9d24 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -32,29 +32,44 @@ static ssize_t ssi_sys_regdump_show(struct kobject *kobj, int offset = 0; register_value = cc_ioread(drvdata, CC_REG(HOST_SIGNATURE)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE ", DX_HOST_SIGNATURE_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE ", + DX_HOST_SIGNATURE_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(HOST_IRR)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR ", DX_HOST_IRR_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR ", + DX_HOST_IRR_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(HOST_POWER_DOWN_EN)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN ", DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN ", + DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(AXIM_MON_ERR)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR ", DX_AXIM_MON_ERR_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR ", + DX_AXIM_MON_ERR_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", + DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, + register_value); return offset; } static ssize_t ssi_sys_help_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - char *help_str[] = { - "cat reg_dump ", "Print several of CC register values", + static const char * const help_str[] = { + "cat reg_dump ", + "Print several of CC register values", }; int i = 0, offset = 0; offset += scnprintf(buf + offset, PAGE_SIZE - offset, "Usage:\n"); - for (i = 0; i < ARRAY_SIZE(help_str); i += 2) - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s\t\t%s\n", help_str[i], help_str[i + 1]); + for (i = 0; i < ARRAY_SIZE(help_str); i += 2) { + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s\t\t%s\n", help_str[i], + help_str[i + 1]); + } return offset; } @@ -82,8 +97,10 @@ static struct kobj_attribute ssi_sys_top_level_attrs[] = { __ATTR(dump_regs, 0444, ssi_sys_regdump_show, NULL), __ATTR(help, 0444, ssi_sys_help_show, NULL), #if defined CC_CYCLE_COUNT - __ATTR(stats_host, 0664, ssi_sys_stat_host_db_show, ssi_sys_stats_host_db_clear), - __ATTR(stats_cc, 0664, ssi_sys_stat_cc_db_show, ssi_sys_stats_cc_db_clear), + __ATTR(stats_host, 0664, ssi_sys_stat_host_db_show, + ssi_sys_stats_host_db_clear), + __ATTR(stats_cc, 0664, ssi_sys_stat_cc_db_show, + ssi_sys_stats_cc_db_clear), #endif }; @@ -145,8 +162,11 @@ static void sys_free_dir(struct sys_dir *sys_dir) kfree(sys_dir->sys_dir_attr_list); - if (sys_dir->sys_dir_kobj) + if (sys_dir->sys_dir_kobj) { + sysfs_remove_group(sys_dir->sys_dir_kobj, + &sys_dir->sys_dir_attr_group); kobject_put(sys_dir->sys_dir_kobj); + } } int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata) diff --git a/drivers/staging/ccree/ssi_sysfs.h b/drivers/staging/ccree/ssi_sysfs.h index 44ae3d4c40b3..512452841694 100644 --- a/drivers/staging/ccree/ssi_sysfs.h +++ b/drivers/staging/ccree/ssi_sysfs.h @@ -26,30 +26,7 @@ /* forward declaration */ struct ssi_drvdata; -enum stat_phase { - STAT_PHASE_0 = 0, - STAT_PHASE_1, - STAT_PHASE_2, - STAT_PHASE_3, - STAT_PHASE_4, - STAT_PHASE_5, - STAT_PHASE_6, - MAX_STAT_PHASES, -}; - -enum stat_op { - STAT_OP_TYPE_NULL = 0, - STAT_OP_TYPE_ENCODE, - STAT_OP_TYPE_DECODE, - STAT_OP_TYPE_SETKEY, - STAT_OP_TYPE_GENERIC, - MAX_STAT_OP_TYPES, -}; - int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata); void ssi_sysfs_fini(void); -void update_host_stat(unsigned int op_type, unsigned int phase, cycles_t result); -void update_cc_stat(unsigned int op_type, unsigned int phase, unsigned int elapsed_cycles); -void display_all_stat_db(void); #endif /*__SSI_SYSFS_H__*/ diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index a1c1081906c5..c0bc413f7fe0 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: LGPL-2.0+ /* * comedi.h * header file for COMEDI user API * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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. */ #ifndef _COMEDI_H diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index b455ff6714eb..f693c2c0bec3 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_buf.c * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ #include <linux/vmalloc.h> diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index f356386d833a..97fb9388bc22 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/comedi_compat32.c * 32-bit ioctl compatibility for 64-bit comedi kernel module. @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.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. */ #include <linux/uaccess.h> diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 0127c1f98bbf..3980e6e1bd0d 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/comedi_compat32.h * 32-bit ioctl compatibility for 64-bit comedi kernel module. @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.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. */ #ifndef _COMEDI_COMPAT32_H diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e19e395b0e44..4dbefc767e1b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/comedi_fops.c * comedi kernel module * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c index 51e023a1c0ee..126048b03f43 100644 --- a/drivers/staging/comedi/comedi_pci.c +++ b/drivers/staging/comedi/comedi_pci.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pci.c * Comedi PCI driver specific functions. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/comedi_pci.h b/drivers/staging/comedi/comedi_pci.h index 7dfd892c74b0..647a72441b8a 100644 --- a/drivers/staging/comedi/comedi_pci.h +++ b/drivers/staging/comedi/comedi_pci.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pci.h * header file for Comedi PCI drivers * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #ifndef _COMEDI_PCI_H diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index cd4742851c08..e16f35eae343 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pcmcia.c * Comedi PCMCIA driver specific functions. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index 9e45c7c93278..c7d37b38e730 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pcmcia.h * header file for Comedi PCMCIA drivers * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #ifndef _COMEDI_PCMCIA_H diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c index 9c946d40b894..c632c2bae722 100644 --- a/drivers/staging/comedi/comedi_usb.c +++ b/drivers/staging/comedi/comedi_usb.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_usb.c * Comedi USB driver specific functions. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/comedi_usb.h b/drivers/staging/comedi/comedi_usb.h index 132154ec792f..50287de7a239 100644 --- a/drivers/staging/comedi/comedi_usb.h +++ b/drivers/staging/comedi/comedi_usb.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_usb.h * header file for USB Comedi drivers * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #ifndef _COMEDI_USB_H diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 1bb9986f865e..fb1f07fa6fcf 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedidev.h * header file for kernel-only structures, variables, and constants * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #ifndef _COMEDIDEV_H diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h index f9b56396e161..e98cb9752dbc 100644 --- a/drivers/staging/comedi/comedilib.h +++ b/drivers/staging/comedi/comedilib.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedilib.h * Header file for kcomedilib * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-2001 David A. Schleef <ds@schleef.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. */ #ifndef _LINUX_COMEDILIB_H diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 0b43db6371c6..e618a87521a3 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * module/drivers.c * functions for manipulating drivers @@ -5,16 +6,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ #include <linux/device.h> diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index b79d3764a8a0..3d6105b5a11b 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/8255.c * Driver for 8255 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 55a67af5152d..6cd1339ab83e 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * module/8255.h * Header file for 8255 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ #ifndef _8255_H diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 38c05d1ec647..9ed05f962fdb 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for generic PCI based 8255 digital i/o boards * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com> @@ -9,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index ccd1a91290bf..560649be9d13 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1032.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 63991c49ff23..45ad4ba92f94 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1500.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -9,16 +10,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index f1f8b1c422a7..6c8213ee1a74 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1516.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 9bfb79c2e5c8..10501fe6bb25 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1564.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -9,16 +10,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index c63133a12a4e..050d0b4b3209 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_16xx.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 50f9eb25d7cb..a122f3f3f5ec 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_2032.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index 2b382a52d80d..140d1514a106 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_2200.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 3630d75e36e8..d2810fdd5e63 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_3120.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -9,16 +10,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 1fdc0f8d7e1a..a38267928e5e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_3501.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index be1f6133ff1c..55784f24e2a7 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_3xxx.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. @@ -10,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c index 9d9853fe54a0..69b323fb869f 100644 --- a/drivers/staging/comedi/drivers/addi_watchdog.c +++ b/drivers/staging/comedi/drivers/addi_watchdog.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for the watchdog subdevice found on some addi-data boards * Copyright (c) 2013 H Hartley Sweeten <hsweeten@visionengravers.com> @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index ad7e7c4a5232..d39b4eabce8d 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adl_pci6208.c * Comedi driver for ADLink 6208 series cards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index b0fc027cf485..d0081897fe47 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for the ADLINK PCI-723x/743x series boards. * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com> @@ -9,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index da901c8dec0e..3022793b1bc5 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/adl_pci8164.c * * Hardware comedi driver for PCI-8164 Adlink card * Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 01d2ee931b28..f4dba6271d0d 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adl_pci9111.c * Hardware driver for PCI9111 ADLink cards: PCI-9111HR * Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 1cc9b7ef1ff9..2528ca0ede6d 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/adl_pci9118.c * diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 315050454c26..5d431573bcca 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adq12b.c * Driver for MicroAxial ADQ12-B data acquisition and control card @@ -9,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 2c1b6de30da8..6a93b04f1fdf 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * adv_pci1710.c * Comedi driver for Advantech PCI-1710 series boards diff --git a/drivers/staging/comedi/drivers/adv_pci1720.c b/drivers/staging/comedi/drivers/adv_pci1720.c index 4830a1c93d15..2fcd7e8e7d85 100644 --- a/drivers/staging/comedi/drivers/adv_pci1720.c +++ b/drivers/staging/comedi/drivers/adv_pci1720.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for Advantech PCI-1720U * Copyright (c) 2015 H Hartley Sweeten <hsweeten@visionengravers.com> @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index f82afd947310..771d61f87427 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adv_pci1723.c * Comedi driver for the Advantech PCI-1723 card. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index bf6a8f10118c..e8ab573c839f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adv_pci1724.c * Comedi driver for the Advantech PCI-1724U card. @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1760.c b/drivers/staging/comedi/drivers/adv_pci1760.c index 9f525ff7290c..e692be371f29 100644 --- a/drivers/staging/comedi/drivers/adv_pci1760.c +++ b/drivers/staging/comedi/drivers/adv_pci1760.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for the Advantech PCI-1760 * Copyright (C) 2015 H Hartley Sweeten <hsweeten@visionengravers.com> @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index a8186687ca2c..5fef2aef7e03 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/adv_pci_dio.c * diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 43a0ce5721d3..f4beda1ed640 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * aio_aio12_8.c * Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board * Copyright (C) 2006 C&C Technologies, Inc. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 35b2f98f0de9..41c9c56816ef 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * aio_iiro_16.c * Comedi driver for Access I/O Products 104-IIRO-16 board * Copyright (C) 2006 C&C Technologies, Inc. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index f5cfa71a90c6..26e63d64ffc6 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_dio200.c * @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h index 53fb86d59fc3..88c1d1063d5d 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_dio.h * @@ -8,16 +9,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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. */ #ifndef AMPLC_DIO200_H_INCLUDED diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index f6e4e984235d..82bd41d92509 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_dio200_common.c * @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index 2598e6e7d47d..30d239731e0b 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* comedi/drivers/amplc_dio200_pci.c * * Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 875cc19cb969..b7dd15f5ec63 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pc236.c * Driver for Amplicon PC36AT DIO boards. @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* * Driver: amplc_pc236 diff --git a/drivers/staging/comedi/drivers/amplc_pc236.h b/drivers/staging/comedi/drivers/amplc_pc236.h index 91d6d9c065b5..4b67090aab54 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.h +++ b/drivers/staging/comedi/drivers/amplc_pc236.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pc236.h * Header for "amplc_pc236", "amplc_pci236" and "amplc_pc236_common". @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ #ifndef AMPLC_PC236_H_INCLUDED diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c index 0c02d3245679..01b90e4eca8a 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236_common.c +++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pc236_common.c * Common support code for "amplc_pc236" and "amplc_pci236". @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 58b0b6b1a693..84c989f12faf 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Amplicon PC263 relay board. * @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 4e554944bc71..657b736ef46d 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pci224.c * Driver for Amplicon PCI224 and PCI234 AO boards. @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 48c7890c3007..15fc7f19051a 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pci230.c * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards. @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pci236.c b/drivers/staging/comedi/drivers/amplc_pci236.c index 31cc38b4bcad..86ea876a11be 100644 --- a/drivers/staging/comedi/drivers/amplc_pci236.c +++ b/drivers/staging/comedi/drivers/amplc_pci236.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pci236.c * Driver for Amplicon PCI236 DIO boards. @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* * Driver: amplc_pci236 diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index 8d4069bc5716..c3efe14020a8 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Amplicon PCI263 relay board. * @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 8ee732571588..41cc784320a9 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * c6xdigio.c * Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card. @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Dan Block - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 78d098f9e1f2..a5d171e71c33 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * cb_das16_cs.c * Driver for Computer Boards PC-CARD DAS16/16. @@ -5,16 +6,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.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. - * * PCMCIA support code for this driver is adapted from the dummy_cs.c * driver of the Linux PCMCIA Card Services package. * diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 3cd008acb657..8429d57087fd 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * cb_pcidas.c * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from @@ -8,16 +9,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index b761f000c1dc..b657beedd5ff 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcidas64.c * This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS @@ -18,16 +19,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 987414741605..807a31e75883 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcidda.c * Driver for the ComputerBoards / MeasurementComputing PCI-DDA series. @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 47e38398921e..4e72a0778086 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcimdas.c * Comedi driver for Computer Boards PCIM-DAS1602/16 and PCIe-DAS1602/16 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index 84ef45457c60..b33203f6a990 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcimdda.c * Computer Boards PCIM-DDA06-16 Comedi driver @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* * Driver: cb_pcimdda diff --git a/drivers/staging/comedi/drivers/comedi_8254.c b/drivers/staging/comedi/drivers/comedi_8254.c index 0d5d56b61f60..d1d509e9add9 100644 --- a/drivers/staging/comedi/drivers/comedi_8254.c +++ b/drivers/staging/comedi/drivers/comedi_8254.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_8254.c * Generic 8254 timer/counter support @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_8254.h b/drivers/staging/comedi/drivers/comedi_8254.h index 326bd44b063e..7faa2185282e 100644 --- a/drivers/staging/comedi/drivers/comedi_8254.h +++ b/drivers/staging/comedi/drivers/comedi_8254.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_8254.h * Generic 8254 timer/counter support @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ #ifndef _COMEDI_8254_H diff --git a/drivers/staging/comedi/drivers/comedi_8255.c b/drivers/staging/comedi/drivers/comedi_8255.c index b2441efc61cc..62baa0d79302 100644 --- a/drivers/staging/comedi/drivers/comedi_8255.c +++ b/drivers/staging/comedi/drivers/comedi_8255.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_8255.c * Generic 8255 digital I/O support @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 64a5ea3810d4..4392b5927a99 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_bond.c * A Comedi driver to 'bond' or merge multiple drivers and devices as one. @@ -5,16 +6,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2005 Calin A. Culianu <calin@ajvar.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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_isadma.c b/drivers/staging/comedi/drivers/comedi_isadma.c index 68ef9b1750be..b77dc8d5d3ff 100644 --- a/drivers/staging/comedi/drivers/comedi_isadma.c +++ b/drivers/staging/comedi/drivers/comedi_isadma.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI ISA DMA support functions * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.com> - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/comedi_isadma.h b/drivers/staging/comedi/drivers/comedi_isadma.h index a193d3e8d185..ccef7c9c0a4d 100644 --- a/drivers/staging/comedi/drivers/comedi_isadma.h +++ b/drivers/staging/comedi/drivers/comedi_isadma.h @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI ISA DMA support functions * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.com> - * - * 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. */ #ifndef _COMEDI_ISADMA_H diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 1bf8ddc6f07c..efaa57372aeb 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_parport.c * Comedi driver for standard parallel port @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2001 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index c7e8194984e5..d437af721bd8 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/comedi_test.c * @@ -11,16 +12,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 5f848396c2f7..49be795b4971 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/contec_pci_dio.c * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c index a562df498b01..5ef8114c2c85 100644 --- a/drivers/staging/comedi/drivers/dac02.c +++ b/drivers/staging/comedi/drivers/dac02.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dac02.c * Comedi driver for DAC02 compatible boards @@ -9,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 32dd8a857b6b..03f98b0287c8 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/daqboard2000.c * hardware driver for IOtech DAQboard/2000 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> - * - * 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. */ /* * Driver: daqboard2000 diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 3d8fc6ad44df..327ecf9aea30 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/das08.c * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) @@ -6,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index d27044cb7158..235d32f7c817 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das08.h * * Header for common DAS08 support (used by ISA/PCI/PCMCIA drivers) * * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ #ifndef _DAS08_H diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 317a9b5e4a3b..223479f9ea3c 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for DAS008 PCMCIA boards * @@ -5,16 +6,6 @@ * Copyright (C) 2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> * - * 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. - * * PCMCIA support code for this driver is adapted from the dummy_cs.c * driver of the Linux PCMCIA Card Services package. * diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index cdefc99b6db3..b22a45bd21d1 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das08_isa.c * comedi driver for DAS08 ISA/PC-104 boards @@ -6,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.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. */ /* diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index d8d27fa44491..7856fc13466a 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das08_pci.c * comedi driver for DAS08 PCI boards @@ -6,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.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. */ /* diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index ddd4aeab6365..74ff204b585d 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das16.c * DAS16 driver @@ -6,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef <ds@schleef.org> * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com> * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index bb8d6ec0632e..72f8ed2c5008 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for CIO-DAS16/M1 * Author: Frank Mori Hess, based on code from the das16 driver. @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index e0a34c2687a8..f16aa7e9f4f3 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for Keithley DAS-1700/DAS-1800 series boards * Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net> * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 0fdf5e02182f..f99211ec46de 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das6402.c * Comedi driver for DAS6402 compatible boards @@ -5,16 +6,6 @@ * * Rewrite of an experimental driver by: * Copyright (C) 1999 Oystein Svendsen <svendsen@pvv.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. */ /* diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index fd4cb4911671..8cf09ef3012f 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/das800.c * Driver for Keitley das800 series boards and compatibles @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* * Driver: das800 diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 771cceb71069..75693cdde313 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dmm32at.c * Diamond Systems Diamond-MM-32-AT Comedi driver * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 30805797a957..a29880981d81 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/dt2801.c * Device Driver for DataTranslation DT2801 diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index fcd85475e429..fea0a1baf10b 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for Data Translation DT2811 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 09984a66dba3..d2c715737361 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt2814.c * Hardware driver for Data Translation DT2814 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* * Driver: dt2814 diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index ce5571971194..83026ba63d1c 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt2815.c * Hardware driver for Data Translation DT2815 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> - * - * 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. */ /* * Driver: dt2815 diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 39d2566e49bf..9babb2a5196a 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt2817.c * Hardware driver for Data Translation DT2817 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* * Driver: dt2817 diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 217a4b884689..3be927f1d3a9 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dt282x.c * Comedi driver for Data Translation DT2821 series * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 19e0b7be8495..2edf3ee91300 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dt3000.c * Data Translation DT3000 series driver * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 7ebca862ecaa..75cc9e8e5b94 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt9812.c * COMEDI driver for DataTranslation DT9812 USB module @@ -5,16 +6,6 @@ * Copyright (C) 2005 Anders Blomdell <anders.blomdell@control.lth.se> * * COMEDI - Linux Control and Measurement Device Interface - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index bab7ac9e6237..e50536731d11 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dyna_pci10xx.c * Copyright (C) 2011 Prashant Shah, pshah.mumbai@gmail.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 0f278ffdad76..41c50c7a8f59 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * fl512.c * Anders Gnistrup <ex18@kalman.iau.dtu.dk> * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index e5b948405fd9..4bdf44d82879 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * gsc_hpdi.c * Comedi driver the General Standards Corporation @@ -8,16 +9,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 28cf53e48b8d..b14aaed6b525 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * icp_multi.c * Comedi driver for Inova ICP_MULTI board * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 77e1d891f232..3eaf7c59de75 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ii_pci20kc.c * Driver for Intelligent Instruments PCI-20001C carrier board and modules. diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index cbff3b41bb45..201f4f96c182 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/jr3_pci.c * hardware driver for JR3/PCI force sensor board * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2007 Anders Blomdell <anders.blomdell@control.lth.se> - * - * 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. */ /* * Driver: jr3_pci diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 93198abf0ee5..e612cf605700 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ke_counter.c * Comedi driver for Kolter-Electronic PCI Counter 1 Card * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 15a53204a36a..ee53571a8969 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * me4000.c * Source code for the Meilhaus ME-4000 board family. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index c0b7a300e428..169742be17b8 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/me_daq.c * Hardware driver for Meilhaus data acquisition cards: * ME-2000i, ME-2600i, ME-3000vm1 * * Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index fbdf181d8ccc..ea430237efa7 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/mf6x4.c * Driver for Humusoft MF634 and MF624 Data acquisition cards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* * Driver: mf6x4 diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 05126ba4ba51..61e03ad84123 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/mite.c * Hardware driver for NI Mite PCI interface chip * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 02a627d3969d..d5e27ac25df8 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * module/mite.h * Hardware driver for NI Mite PCI interface chip * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 David A. Schleef <ds@schleef.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. */ #ifndef _MITE_H_ diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 9bda761433c2..bf3a3a08c7ab 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * mpc624.c * Hardware driver for a Micro/sys inc. MPC-624 PC/104 board * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index b5a26f7b4332..c85c9ab3655f 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * multiq3.c * Hardware driver for Quanser Consulting MultiQ-3 board * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 84c62e256094..4d1eccb5041d 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ni_6527.c * Comedi driver for National Instruments PCI-6527 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 07f38e385469..996074e471d3 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ni_65xx.c * Comedi driver for National Instruments PCI-65xx static dio boards @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 6aa755ad3953..e521ed9d0887 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1,15 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Hardware driver for NI 660x devices - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 1d3ff60efcb8..4e4ae31c8d0b 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI 670x devices * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index c69cd676f357..76e8d047f71e 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments AT-A2150 boards * Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net> * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 158fa29374fc..aad0b295ee2b 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ni_at_ao.c * Driver for NI AT-AO-6/10 boards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000,2002 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index ae6ed96d7874..b9e9ab548c4b 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI AT-MIO E series cards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index fb59b0ffbba6..68ad9676f962 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments AT-MIO16D board * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 8f6396edd21c..b9e525b9beb9 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_daq_700.c * Driver for DAQCard-700 DIO/AI @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 733d3fbafa4d..44fb65afc218 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments PCMCIA DAQ-Card DIO-24 * Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es> @@ -7,16 +8,6 @@ * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 51e5e942b442..c6cf37ccbc92 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc.c * Driver for National Instruments Lab-PC series boards and compatibles * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index c2edadc7b3c6..f685047efb67 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Header for ni_labpc ISA/PCMCIA/PCI drivers * * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ #ifndef _NI_LABPC_H diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index b0dfb8eed16d..7fa2d39562db 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc_common.c * * Common support code for "ni_labpc", "ni_labpc_pci" and "ni_labpc_cs". * * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 3d4d0b9ad4e1..4f7e2fe21254 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for National Instruments daqcard-1200 boards * Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net> @@ -7,16 +8,6 @@ * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. - * - * 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 - * General Public License for more details. */ /* diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 29dbdf5ec25d..5657736a9408 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc_isadma.c * ISA DMA support for National Instruments Lab-PC series boards and @@ -5,16 +6,6 @@ * * Extracted from ni_labpc.c: * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index cac089193121..d7d5a7973558 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc_pci.c * Driver for National Instruments Lab-PC PCI-1200 * Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 398347fedc47..5d610af6799f 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Hardware driver for DAQ-STC based boards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> * Copyright (C) 2002-2006 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 21f823179356..4f37b4e58f09 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI PCMCIA MIO E series cards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index b27345abebe1..6692af5ff79b 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments PCI-DIO-32HS * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999,2002 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 3a96913c025e..f9e466d18b3f 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI PCI-MIO E series cards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 61138e86a455..cb9d4c3a1926 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Register descriptions for NI DAQ-STC chip * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-9 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 15cb4088467b..ef919b21b7d9 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Support for NI general purpose counters * * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 2012033414d3..23221cead8ca 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Header file for NI general purpose counter support code (ni_tio.c) * * COMEDI - Linux Control and Measurement Device Interface - * - * 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. */ #ifndef _COMEDI_NI_TIO_H diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 4e024eb5656b..f4d99d78208a 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Header file for NI general purpose counter support code (ni_tio.c and * ni_tiocmd.c) * * COMEDI - Linux Control and Measurement Device Interface - * - * 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. */ #ifndef _COMEDI_NI_TIO_INTERNAL_H diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 9007c57544bf..050bee0b9515 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Command support for NI general purpose counters * * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 9a0a96329a55..808ed92ed66f 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_usb6501.c * Comedi driver for National Instruments USB-6501 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2014 Luca Ellero <luca.ellero@brickedbrain.com> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 3774daa9d661..a5937206bf1c 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcl711.c * Comedi driver for PC-LabCard PCL-711 and AdSys ACL-8112 and compatibles @@ -7,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 74b07e1744c7..9c174f1f2fcf 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * pcl724.c * Comedi driver for 8255 based ISA and PC/104 DIO boards diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 256850ccb6fa..0963d85873a9 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcl726.c * Comedi driver for 6/12-Channel D/A Output and DIO cards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index ce958eef2a61..3d1e9150e5b5 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/pcl730.c * Driver for Advantech PCL-730 and clones diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 9c75065dd26a..aefc1b849cf7 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/pcl812.c * diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index c00a71f538ef..d722079f3327 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * pcl816.c * Comedi driver for Advantech PCL-816 cards diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 5b5df0596ad9..eebb49751713 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/pcl818.c * diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 588ae5ecec66..5779e005c0cb 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * pcm3724.c * Comedi driver for Advantech PCM-3724 Digital I/O board diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 12f94fe82f5b..fe5449bb1716 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmad.c * Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000,2001 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index d86c5e2cd0c7..33e463b193a1 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmda12.c * Driver for Winsystems PC-104 based PCM-D/A-12 8-channel AO board. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 70ad497dd20b..72af1776f785 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmmio.c * Driver for Winsystems PC-104 based multifunction IO board. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2007 Calin A. Culianu <calin@ajvar.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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 8ad64f2625fe..743fb226e2e4 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmuio.c * Comedi driver for Winsystems PC-104 based 48/96-channel DIO boards. * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.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. */ /* diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index 2892e6528967..7950d1f57db6 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Definitions for the PLX-9052 PCI interface chip * @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ #ifndef _PLX9052_H_ diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index e23e63a097b5..469a9573acdc 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * plx9080.h * @@ -9,11 +10,6 @@ * Written by Krzysztof Halasa <khc@rgstudio.com.pl> * * Portions (C) SBE Inc., used by permission. - * - * 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. */ #ifndef __COMEDI_PLX9080_H diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index e00e9c6268ae..bb400e08f0bc 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/rtd520.c * Comedi driver for Real Time Devices (RTD) PCI4520/DM7520 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2001 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index cd61d2645af4..f7c320c89ee6 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/rti800.c * Hardware driver for Analog Devices RTI-800/815 board * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 6db58fcfd496..c6cf92bfff73 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * rti802.c * Comedi driver for Analog Devices RTI-802 board * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index e226275972c0..5d567ae78f28 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * s526.c * Sensoray s526 Comedi driver * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index c906c9a5d944..8d9187025d51 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/s626.c * Sensoray s626 Comedi driver @@ -7,16 +8,6 @@ * * Based on Sensoray Model 626 Linux driver Version 0.2 * Copyright (C) 2002-2004 Sensoray Co., Inc. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 4cef45263267..4bdc4fba736f 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/s626.h * Sensoray s626 Comedi driver, header file @@ -7,16 +8,6 @@ * * Based on Sensoray Model 626 Linux driver Version 0.2 * Copyright (C) 2002-2004 Sensoray Co., Inc. - * - * 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. */ #ifndef S626_H_INCLUDED diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index cc18e25103ca..1f52fd1c1c08 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * serial2002.c * Comedi driver for serial connected hardware * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se> - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index f9f634fd53cf..0628060e42ca 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ssv_dnp.c * generic comedi driver for SSV Embedded Systems' DIL/Net-PCs @@ -5,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index f4f05d29d30d..de177418190f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * usbdux.c * Copyright (C) 2003-2014 Bernd Porr, mail@berndporr.me.uk - * - * 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. */ /* @@ -809,7 +800,6 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, { struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int val = s->readback[chan]; __le16 *p = (__le16 *)&devpriv->dux_commands[2]; int ret = -EBUSY; int i; @@ -825,7 +815,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, devpriv->dux_commands[4] = chan << 6; for (i = 0; i < insn->n; i++) { - val = data[i]; + unsigned int val = data[i]; /* one 16 bit value */ *p = cpu_to_le16(val); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 608403c7586b..e18c0723b760 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1,15 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 456e9f13becb..af5605a875e2 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * usbduxsigma.c * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index a004aed0147a..6234b649d887 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vmk80xx.c * Velleman USB Board Low-Level Driver @@ -6,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 55d43c076b1c..df9bba1b69ed 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * kcomedilib/kcomedilib.c * a comedlib interface for kernel modules * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.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. */ #include <linux/module.h> diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c index 2644dd4d6143..50d38938ac6f 100644 --- a/drivers/staging/comedi/proc.c +++ b/drivers/staging/comedi/proc.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * /proc interface for comedi * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef <ds@schleef.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. */ /* diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index ce3a58a7a171..89d599877445 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/range.c * comedi routines for voltage ranges * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef <ds@schleef.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. */ #include <linux/uaccess.h> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 9639035fddd1..e264fe11cba4 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -397,7 +397,7 @@ static void cls_assert_modem_signals(struct channel_t *ch) writeb(out, &ch->ch_cls_uart->mcr); /* Give time for the UART to actually drop the signals */ - udelay(10); + usleep_range(10, 20); } static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index efdb11a5e27f..924357120b0c 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -88,12 +88,12 @@ struct board_ops { void (*flush_uart_read)(struct channel_t *ch); void (*disable_receiver)(struct channel_t *ch); void (*enable_receiver)(struct channel_t *ch); - void (*send_break)(struct channel_t *ch, int); + void (*send_break)(struct channel_t *ch, int msec); void (*send_start_character)(struct channel_t *ch); void (*send_stop_character)(struct channel_t *ch); void (*copy_data_from_queue_to_uart)(struct channel_t *ch); uint (*get_uart_bytes_left)(struct channel_t *ch); - void (*send_immediate_char)(struct channel_t *ch, unsigned char); + void (*send_immediate_char)(struct channel_t *ch, unsigned char c); }; /* Device flag definitions for bd_flags. */ diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index 363730a80cbb..fc76e900e8c4 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -77,7 +77,7 @@ int dpbp_open(struct fsl_mc_io *mc_io, return err; } -EXPORT_SYMBOL(dpbp_open); +EXPORT_SYMBOL_GPL(dpbp_open); /** * dpbp_close() - Close the control session of the object @@ -103,7 +103,7 @@ int dpbp_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_close); +EXPORT_SYMBOL_GPL(dpbp_close); /** * dpbp_enable() - Enable the DPBP. @@ -126,7 +126,7 @@ int dpbp_enable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_enable); +EXPORT_SYMBOL_GPL(dpbp_enable); /** * dpbp_disable() - Disable the DPBP. @@ -149,7 +149,7 @@ int dpbp_disable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_disable); +EXPORT_SYMBOL_GPL(dpbp_disable); /** * dpbp_is_enabled() - Check if the DPBP is enabled. @@ -183,7 +183,7 @@ int dpbp_is_enabled(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpbp_is_enabled); +EXPORT_SYMBOL_GPL(dpbp_is_enabled); /** * dpbp_reset() - Reset the DPBP, returns the object to initial state. @@ -206,7 +206,7 @@ int dpbp_reset(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_reset); +EXPORT_SYMBOL_GPL(dpbp_reset); /** * dpbp_get_attributes - Retrieve DPBP attributes. @@ -243,7 +243,7 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpbp_get_attributes); +EXPORT_SYMBOL_GPL(dpbp_get_attributes); /** * dpbp_get_api_version - Get Data Path Buffer Pool API version @@ -276,4 +276,4 @@ int dpbp_get_api_version(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpbp_get_api_version); +EXPORT_SYMBOL_GPL(dpbp_get_api_version); diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/staging/fsl-mc/bus/dpcon-cmd.h index 2bb66988ecf6..d2ba8193fdef 100644 --- a/drivers/staging/fsl-mc/bus/dpcon-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h @@ -45,13 +45,11 @@ /* Command IDs */ #define DPCON_CMDID_CLOSE DPCON_CMD(0x800) #define DPCON_CMDID_OPEN DPCON_CMD(0x808) -#define DPCON_CMDID_GET_API_VERSION DPCON_CMD(0xa08) #define DPCON_CMDID_ENABLE DPCON_CMD(0x002) #define DPCON_CMDID_DISABLE DPCON_CMD(0x003) #define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004) #define DPCON_CMDID_RESET DPCON_CMD(0x005) -#define DPCON_CMDID_IS_ENABLED DPCON_CMD(0x006) #define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100) @@ -61,10 +59,6 @@ struct dpcon_cmd_open { #define DPCON_ENABLE 1 -struct dpcon_rsp_is_enabled { - u8 enabled; -}; - struct dpcon_rsp_get_attr { /* response word 0 */ __le32 id; diff --git a/drivers/staging/fsl-mc/bus/dpcon.c b/drivers/staging/fsl-mc/bus/dpcon.c index ca1da85c6dda..5ba1a0f58a41 100644 --- a/drivers/staging/fsl-mc/bus/dpcon.c +++ b/drivers/staging/fsl-mc/bus/dpcon.c @@ -78,7 +78,7 @@ int dpcon_open(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpcon_open); +EXPORT_SYMBOL_GPL(dpcon_open); /** * dpcon_close() - Close the control session of the object @@ -105,7 +105,7 @@ int dpcon_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_close); +EXPORT_SYMBOL_GPL(dpcon_close); /** * dpcon_enable() - Enable the DPCON @@ -129,7 +129,7 @@ int dpcon_enable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_enable); +EXPORT_SYMBOL_GPL(dpcon_enable); /** * dpcon_disable() - Disable the DPCON @@ -153,43 +153,7 @@ int dpcon_disable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_disable); - -/** - * dpcon_is_enabled() - Check if the DPCON is enabled. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPCON object - * @en: Returns '1' if object is enabled; '0' otherwise - * - * Return: '0' on Success; Error code otherwise. - */ -int dpcon_is_enabled(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *en) -{ - struct mc_command cmd = { 0 }; - struct dpcon_rsp_is_enabled *dpcon_rsp; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, - cmd_flags, - token); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params; - *en = dpcon_rsp->enabled & DPCON_ENABLE; - - return 0; -} -EXPORT_SYMBOL(dpcon_is_enabled); +EXPORT_SYMBOL_GPL(dpcon_disable); /** * dpcon_reset() - Reset the DPCON, returns the object to initial state. @@ -212,7 +176,7 @@ int dpcon_reset(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_reset); +EXPORT_SYMBOL_GPL(dpcon_reset); /** * dpcon_get_attributes() - Retrieve DPCON attributes. @@ -250,7 +214,7 @@ int dpcon_get_attributes(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpcon_get_attributes); +EXPORT_SYMBOL_GPL(dpcon_get_attributes); /** * dpcon_set_notification() - Set DPCON notification destination @@ -281,37 +245,4 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_set_notification); - -/** - * dpcon_get_api_version - Get Data Path Concentrator API version - * @mc_io: Pointer to MC portal's DPCON object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @major_ver: Major version of DPCON API - * @minor_ver: Minor version of DPCON API - * - * Return: '0' on Success; Error code otherwise - */ -int dpcon_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION, - cmd_flags, 0); - - /* send command to mc */ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - mc_cmd_read_api_version(&cmd, major_ver, minor_ver); - - return 0; -} -EXPORT_SYMBOL(dpcon_get_api_version); +EXPORT_SYMBOL_GPL(dpcon_set_notification); diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c index a609ec82daf3..a8a8e1578770 100644 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c @@ -43,7 +43,6 @@ #include "qbman-portal.h" struct dpaa2_io { - atomic_t refs; struct dpaa2_io_desc dpio_desc; struct qbman_swp_desc swp_desc; struct qbman_swp *swp; @@ -126,7 +125,6 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) return NULL; } - atomic_set(&obj->refs, 1); obj->dpio_desc = *desc; obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena; obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh; @@ -158,7 +156,6 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) return obj; } -EXPORT_SYMBOL(dpaa2_io_create); /** * dpaa2_io_down() - release the dpaa2_io object. @@ -171,11 +168,8 @@ EXPORT_SYMBOL(dpaa2_io_create); */ void dpaa2_io_down(struct dpaa2_io *d) { - if (!atomic_dec_and_test(&d->refs)) - return; kfree(d); } -EXPORT_SYMBOL(dpaa2_io_down); #define DPAA_POLL_MAX 32 @@ -222,7 +216,6 @@ done: qbman_swp_interrupt_set_inhibit(swp, 0); return IRQ_HANDLED; } -EXPORT_SYMBOL(dpaa2_io_irq); /** * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN @@ -265,7 +258,7 @@ int dpaa2_io_service_register(struct dpaa2_io *d, ctx->qman64); return 0; } -EXPORT_SYMBOL(dpaa2_io_service_register); +EXPORT_SYMBOL_GPL(dpaa2_io_service_register); /** * dpaa2_io_service_deregister - The opposite of 'register'. @@ -288,7 +281,7 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service, list_del(&ctx->node); spin_unlock_irqrestore(&d->lock_notifications, irqflags); } -EXPORT_SYMBOL(dpaa2_io_service_deregister); +EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); /** * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service. @@ -322,38 +315,7 @@ int dpaa2_io_service_rearm(struct dpaa2_io *d, return err; } -EXPORT_SYMBOL(dpaa2_io_service_rearm); - -/** - * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq. - * @d: the given DPIO service. - * @fqid: the given frame queue id. - * @s: the dpaa2_io_store object for the result. - * - * Return 0 for success, or error code for failure. - */ -int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, - struct dpaa2_io_store *s) -{ - struct qbman_pull_desc pd; - int err; - - qbman_pull_desc_clear(&pd); - qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1); - qbman_pull_desc_set_numframes(&pd, (u8)s->max); - qbman_pull_desc_set_fq(&pd, fqid); - - d = service_select(d); - if (!d) - return -ENODEV; - s->swp = d->swp; - err = qbman_swp_pull(d->swp, &pd); - if (err) - s->swp = NULL; - - return err; -} -EXPORT_SYMBOL(dpaa2_io_service_pull_fq); +EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm); /** * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel. @@ -385,34 +347,7 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, return err; } -EXPORT_SYMBOL(dpaa2_io_service_pull_channel); - -/** - * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue. - * @d: the given DPIO service. - * @fqid: the given frame queue id. - * @fd: the frame descriptor which is enqueued. - * - * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, - * or -ENODEV if there is no dpio service. - */ -int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, - u32 fqid, - const struct dpaa2_fd *fd) -{ - struct qbman_eq_desc ed; - - d = service_select(d); - if (!d) - return -ENODEV; - - qbman_eq_desc_clear(&ed); - qbman_eq_desc_set_no_orp(&ed, 0); - qbman_eq_desc_set_fq(&ed, fqid); - - return qbman_swp_enqueue(d->swp, &ed, fd); -} -EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq); +EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel); /** * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. @@ -441,7 +376,7 @@ int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, return qbman_swp_enqueue(d->swp, &ed, fd); } -EXPORT_SYMBOL(dpaa2_io_service_enqueue_qd); +EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); /** * dpaa2_io_service_release() - Release buffers to a buffer pool. @@ -468,7 +403,7 @@ int dpaa2_io_service_release(struct dpaa2_io *d, return qbman_swp_release(d->swp, &rd, buffers, num_buffers); } -EXPORT_SYMBOL(dpaa2_io_service_release); +EXPORT_SYMBOL_GPL(dpaa2_io_service_release); /** * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool. @@ -499,7 +434,7 @@ int dpaa2_io_service_acquire(struct dpaa2_io *d, return err; } -EXPORT_SYMBOL(dpaa2_io_service_acquire); +EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); /* * 'Stores' are reusable memory blocks for holding dequeue results, and to @@ -553,7 +488,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, return ret; } -EXPORT_SYMBOL(dpaa2_io_store_create); +EXPORT_SYMBOL_GPL(dpaa2_io_store_create); /** * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue @@ -567,7 +502,7 @@ void dpaa2_io_store_destroy(struct dpaa2_io_store *s) kfree(s->alloced_addr); kfree(s); } -EXPORT_SYMBOL(dpaa2_io_store_destroy); +EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy); /** * dpaa2_io_store_next() - Determine when the next dequeue result is available. @@ -615,4 +550,4 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last) return ret; } -EXPORT_SYMBOL(dpaa2_io_store_next); +EXPORT_SYMBOL_GPL(dpaa2_io_store_next); diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 06df528f4cfc..131c71545a25 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -39,8 +39,6 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) struct fsl_mc_child_objs *objs; struct fsl_mc_device *mc_dev; - WARN_ON(!dev); - WARN_ON(!data); mc_dev = to_fsl_mc_device(dev); objs = data; @@ -60,8 +58,6 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) static int __fsl_mc_device_remove(struct device *dev, void *data) { - WARN_ON(!dev); - WARN_ON(data); fsl_mc_device_remove(to_fsl_mc_device(dev)); return 0; } @@ -386,11 +382,11 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", irq_num, smp_processor_id()); - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) + if (!(mc_dev->flags & FSL_MC_IS_DPRC)) return IRQ_HANDLED; mutex_lock(&mc_bus->scan_mutex); - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) + if (!msi_desc || msi_desc->irq != (u32)irq_num) goto out; status = 0; @@ -453,8 +449,6 @@ static int disable_dprc_irq(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_io *mc_io = mc_dev->mc_io; - WARN_ON(mc_dev->obj_desc.irq_count != 1); - /* * Disable generation of interrupt, while we configure it: */ @@ -496,8 +490,6 @@ static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; - WARN_ON(mc_dev->obj_desc.irq_count != 1); - /* * NOTE: devm_request_threaded_irq() invokes the device-specific * function that programs the MSI physically in the device @@ -601,20 +593,20 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) bool msi_domain_set = false; u16 major_ver, minor_ver; - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) + if (!is_fsl_mc_bus_dprc(mc_dev)) return -EINVAL; - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) + if (dev_get_msi_domain(&mc_dev->dev)) return -EINVAL; if (!mc_dev->mc_io) { /* * This is a child DPRC: */ - if (WARN_ON(!dev_is_fsl_mc(parent_dev))) + if (!dev_is_fsl_mc(parent_dev)) return -EINVAL; - if (WARN_ON(mc_dev->obj_desc.region_count == 0)) + if (mc_dev->obj_desc.region_count == 0) return -EINVAL; region_size = resource_size(mc_dev->regions); @@ -642,7 +634,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) */ struct irq_domain *mc_msi_domain; - if (WARN_ON(dev_is_fsl_mc(parent_dev))) + if (dev_is_fsl_mc(parent_dev)) return -EINVAL; error = fsl_mc_find_msi_domain(parent_dev, @@ -753,12 +745,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) + if (!is_fsl_mc_bus_dprc(mc_dev)) return -EINVAL; - if (WARN_ON(!mc_dev->mc_io)) + if (!mc_dev->mc_io) return -EINVAL; - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return -EINVAL; if (dev_get_msi_domain(&mc_dev->dev)) diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index 6f6c65a42166..f29ea3e1fd3e 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -71,7 +71,7 @@ int dprc_open(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_open); +EXPORT_SYMBOL_GPL(dprc_open); /** * dprc_close() - Close the control session of the object @@ -97,7 +97,7 @@ int dprc_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dprc_close); +EXPORT_SYMBOL_GPL(dprc_close); /** * dprc_get_irq() - Get IRQ information from the DPRC. @@ -475,7 +475,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_obj_count); +EXPORT_SYMBOL_GPL(dprc_get_obj_count); /** * dprc_get_obj() - Get general information on an object @@ -531,7 +531,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, obj_desc->label[15] = '\0'; return 0; } -EXPORT_SYMBOL(dprc_get_obj); +EXPORT_SYMBOL_GPL(dprc_get_obj); /** * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. @@ -572,7 +572,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dprc_set_obj_irq); +EXPORT_SYMBOL_GPL(dprc_set_obj_irq); /** * dprc_get_obj_irq() - Get IRQ information from object. @@ -626,7 +626,7 @@ int dprc_get_obj_irq(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_obj_irq); +EXPORT_SYMBOL_GPL(dprc_get_obj_irq); /** * dprc_get_res_count() - Obtains the number of free resources that are assigned @@ -669,7 +669,7 @@ int dprc_get_res_count(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_res_count); +EXPORT_SYMBOL_GPL(dprc_get_res_count); /** * dprc_get_obj_region() - Get region information for a specified object. @@ -717,7 +717,7 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_obj_region); +EXPORT_SYMBOL_GPL(dprc_get_obj_region); /** * dprc_get_api_version - Get Data Path Resource Container API version diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 8ea3920400a0..1000fb3fbff0 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -14,11 +14,11 @@ #include "fsl-mc-private.h" -static bool __must_check fsl_mc_is_allocatable(const char *obj_type) +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev) { - return strcmp(obj_type, "dpbp") == 0 || - strcmp(obj_type, "dpmcp") == 0 || - strcmp(obj_type, "dpcon") == 0; + return is_fsl_mc_bus_dpbp(mc_dev) || + is_fsl_mc_bus_dpmcp(mc_dev) || + is_fsl_mc_bus_dpcon(mc_dev); } /** @@ -41,25 +41,25 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; int error = -EINVAL; - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) goto out; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev)) goto out; - if (WARN_ON(mc_dev->resource)) + if (mc_dev->resource) goto out; res_pool = &mc_bus->resource_pools[pool_type]; - if (WARN_ON(res_pool->type != pool_type)) + if (res_pool->type != pool_type) goto out; - if (WARN_ON(res_pool->mc_bus != mc_bus)) + if (res_pool->mc_bus != mc_bus) goto out; mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->max_count < 0)) + if (res_pool->max_count < 0) goto out_unlock; - if (WARN_ON(res_pool->free_count < 0 || - res_pool->free_count > res_pool->max_count)) + if (res_pool->free_count < 0 || + res_pool->free_count > res_pool->max_count) goto out_unlock; resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), @@ -105,25 +105,25 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device struct fsl_mc_resource *resource; int error = -EINVAL; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev)) goto out; resource = mc_dev->resource; - if (WARN_ON(!resource || resource->data != mc_dev)) + if (!resource || resource->data != mc_dev) goto out; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); mc_bus = to_fsl_mc_bus(mc_bus_dev); res_pool = resource->parent_pool; - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) + if (res_pool != &mc_bus->resource_pools[resource->type]) goto out; mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->max_count <= 0)) + if (res_pool->max_count <= 0) goto out_unlock; - if (WARN_ON(res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count)) + if (res_pool->free_count <= 0 || + res_pool->free_count > res_pool->max_count) goto out_unlock; /* @@ -187,11 +187,11 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, FSL_MC_NUM_POOL_TYPES); *new_resource = NULL; - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) goto out; res_pool = &mc_bus->resource_pools[pool_type]; - if (WARN_ON(res_pool->mc_bus != mc_bus)) + if (res_pool->mc_bus != mc_bus) goto out; mutex_lock(&res_pool->mutex); @@ -199,7 +199,6 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, struct fsl_mc_resource, node); if (!resource) { - WARN_ON(res_pool->free_count != 0); error = -ENXIO; dev_err(&mc_bus_dev->dev, "No more resources of type %s left\n", @@ -207,12 +206,12 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, goto out_unlock; } - if (WARN_ON(resource->type != pool_type)) + if (resource->type != pool_type) goto out_unlock; - if (WARN_ON(resource->parent_pool != res_pool)) + if (resource->parent_pool != res_pool) goto out_unlock; - if (WARN_ON(res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count)) + if (res_pool->free_count <= 0 || + res_pool->free_count > res_pool->max_count) goto out_unlock; list_del_init(&resource->node); @@ -232,15 +231,15 @@ void fsl_mc_resource_free(struct fsl_mc_resource *resource) struct fsl_mc_resource_pool *res_pool; res_pool = resource->parent_pool; - if (WARN_ON(resource->type != res_pool->type)) + if (resource->type != res_pool->type) return; mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->free_count < 0 || - res_pool->free_count >= res_pool->max_count)) + if (res_pool->free_count < 0 || + res_pool->free_count >= res_pool->max_count) goto out_unlock; - if (WARN_ON(!list_empty(&resource->node))) + if (!list_empty(&resource->node)) goto out_unlock; list_add_tail(&resource->node, &res_pool->free_list); @@ -279,13 +278,13 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, struct fsl_mc_resource *resource = NULL; *new_mc_adev = NULL; - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) + if (mc_dev->flags & FSL_MC_IS_DPRC) goto error; - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + if (!dev_is_fsl_mc(mc_dev->dev.parent)) goto error; - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) + if (pool_type == FSL_MC_POOL_DPMCP) goto error; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -295,7 +294,7 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, goto error; mc_adev = resource->data; - if (WARN_ON(!mc_adev)) + if (!mc_adev) goto error; *new_mc_adev = mc_adev; @@ -318,9 +317,9 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev) struct fsl_mc_resource *resource; resource = mc_adev->resource; - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) + if (resource->type == FSL_MC_POOL_DPMCP) return; - if (WARN_ON(resource->data != mc_adev)) + if (resource->data != mc_adev) return; fsl_mc_resource_free(resource); @@ -349,8 +348,8 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, struct fsl_mc_resource_pool *res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - if (WARN_ON(irq_count == 0 || - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) + if (irq_count == 0 || + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) return -EINVAL; error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); @@ -406,13 +405,13 @@ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) struct fsl_mc_resource_pool *res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return; - if (WARN_ON(res_pool->max_count == 0)) + if (res_pool->max_count == 0) return; - if (WARN_ON(res_pool->free_count != res_pool->max_count)) + if (res_pool->free_count != res_pool->max_count) return; INIT_LIST_HEAD(&res_pool->free_list); @@ -436,19 +435,19 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; struct fsl_mc_resource_pool *res_pool; - if (WARN_ON(mc_dev->irqs)) + if (mc_dev->irqs) return -EINVAL; irq_count = mc_dev->obj_desc.irq_count; - if (WARN_ON(irq_count == 0)) + if (irq_count == 0) return -EINVAL; - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + if (is_fsl_mc_bus_dprc(mc_dev)) mc_bus = to_fsl_mc_bus(mc_dev); else mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return -EINVAL; res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; @@ -474,7 +473,6 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) irqs[i] = to_fsl_mc_irq(resource); res_allocated_count++; - WARN_ON(irqs[i]->mc_dev); irqs[i]->mc_dev = mc_dev; irqs[i]->dev_irq_index = i; } @@ -502,21 +500,20 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; struct fsl_mc_device_irq **irqs = mc_dev->irqs; - if (WARN_ON(!irqs)) + if (!irqs) return; irq_count = mc_dev->obj_desc.irq_count; - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + if (is_fsl_mc_bus_dprc(mc_dev)) mc_bus = to_fsl_mc_bus(mc_dev); else mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return; for (i = 0; i < irq_count; i++) { - WARN_ON(!irqs[i]->mc_dev); irqs[i]->mc_dev = NULL; fsl_mc_resource_free(&irqs[i]->resource); } @@ -553,17 +550,10 @@ static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, &mc_bus->resource_pools[pool_type]; int free_count = 0; - WARN_ON(res_pool->type != pool_type); - WARN_ON(res_pool->free_count != res_pool->max_count); - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { free_count++; - WARN_ON(resource->type != res_pool->type); - WARN_ON(resource->parent_pool != res_pool); devm_kfree(&mc_bus_dev->dev, resource); } - - WARN_ON(free_count != res_pool->free_count); } void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) @@ -585,11 +575,11 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; int error; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev)) return -EINVAL; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) + if (!dev_is_fsl_mc(&mc_bus_dev->dev)) return -EINVAL; mc_bus = to_fsl_mc_bus(mc_bus_dev); @@ -614,7 +604,7 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) { int error; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev)) return -EINVAL; if (mc_dev->resource) { diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 409f2b9e70ff..f15bab32fb2f 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -156,18 +156,75 @@ struct bus_type fsl_mc_bus_type = { }; EXPORT_SYMBOL_GPL(fsl_mc_bus_type); +struct device_type fsl_mc_bus_dprc_type = { + .name = "fsl_mc_bus_dprc" +}; + +struct device_type fsl_mc_bus_dpni_type = { + .name = "fsl_mc_bus_dpni" +}; + +struct device_type fsl_mc_bus_dpio_type = { + .name = "fsl_mc_bus_dpio" +}; + +struct device_type fsl_mc_bus_dpsw_type = { + .name = "fsl_mc_bus_dpsw" +}; + +struct device_type fsl_mc_bus_dpbp_type = { + .name = "fsl_mc_bus_dpbp" +}; + +struct device_type fsl_mc_bus_dpcon_type = { + .name = "fsl_mc_bus_dpcon" +}; + +struct device_type fsl_mc_bus_dpmcp_type = { + .name = "fsl_mc_bus_dpmcp" +}; + +struct device_type fsl_mc_bus_dpmac_type = { + .name = "fsl_mc_bus_dpmac" +}; + +struct device_type fsl_mc_bus_dprtc_type = { + .name = "fsl_mc_bus_dprtc" +}; + +static struct device_type *fsl_mc_get_device_type(const char *type) +{ + static const struct { + struct device_type *dev_type; + const char *type; + } dev_types[] = { + { &fsl_mc_bus_dprc_type, "dprc" }, + { &fsl_mc_bus_dpni_type, "dpni" }, + { &fsl_mc_bus_dpio_type, "dpio" }, + { &fsl_mc_bus_dpsw_type, "dpsw" }, + { &fsl_mc_bus_dpbp_type, "dpbp" }, + { &fsl_mc_bus_dpcon_type, "dpcon" }, + { &fsl_mc_bus_dpmcp_type, "dpmcp" }, + { &fsl_mc_bus_dpmac_type, "dpmac" }, + { &fsl_mc_bus_dprtc_type, "dprtc" }, + { NULL, NULL } + }; + int i; + + for (i = 0; dev_types[i].dev_type; i++) + if (!strcmp(dev_types[i].type, type)) + return dev_types[i].dev_type; + + return NULL; +} + static int fsl_mc_driver_probe(struct device *dev) { struct fsl_mc_driver *mc_drv; struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); int error; - if (WARN_ON(!dev->driver)) - return -EINVAL; - mc_drv = to_fsl_mc_driver(dev->driver); - if (WARN_ON(!mc_drv->probe)) - return -EINVAL; error = mc_drv->probe(mc_dev); if (error < 0) { @@ -184,9 +241,6 @@ static int fsl_mc_driver_remove(struct device *dev) struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); int error; - if (WARN_ON(!dev->driver)) - return -EINVAL; - error = mc_drv->remove(mc_dev); if (error < 0) { dev_err(dev, "%s failed: %d\n", __func__, error); @@ -292,9 +346,9 @@ static int mc_get_version(struct fsl_mc_io *mc_io, static void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev) { - if (WARN_ON(!dev)) { + if (!dev) { *root_dprc_dev = NULL; - } else if (WARN_ON(!dev_is_fsl_mc(dev))) { + } else if (!dev_is_fsl_mc(dev)) { *root_dprc_dev = NULL; } else { *root_dprc_dev = dev; @@ -352,8 +406,6 @@ static int translate_mc_addr(struct fsl_mc_device *mc_dev, struct fsl_mc *mc; fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); - if (WARN_ON(!root_dprc_dev)) - return -EINVAL; mc = dev_get_drvdata(root_dprc_dev->parent); if (mc->num_translation_ranges == 0) { @@ -390,10 +442,10 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, struct device *parent_dev = mc_dev->dev.parent; enum dprc_region_type mc_region_type; - if (strcmp(obj_desc->type, "dprc") == 0 || - strcmp(obj_desc->type, "dpmcp") == 0) { + if (is_fsl_mc_bus_dprc(mc_dev) || + is_fsl_mc_bus_dpmcp(mc_dev)) { mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; - } else if (strcmp(obj_desc->type, "dpio") == 0) { + } else if (is_fsl_mc_bus_dpio(mc_dev)) { mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; } else { /* @@ -401,7 +453,6 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, * type, as this object type is not supposed to have MMIO * regions */ - WARN_ON(true); return -EINVAL; } @@ -424,7 +475,6 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, goto error_cleanup_regions; } - WARN_ON(region_desc.size == 0); error = translate_mc_addr(mc_dev, mc_region_type, region_desc.base_offset, ®ions[i].start); @@ -470,7 +520,7 @@ static void fsl_mc_device_release(struct device *dev) kfree(mc_dev->regions); - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + if (is_fsl_mc_bus_dprc(mc_dev)) kfree(to_fsl_mc_bus(mc_dev)); else kfree(mc_dev); @@ -518,6 +568,12 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, mc_dev->dev.parent = parent_dev; mc_dev->dev.bus = &fsl_mc_bus_type; mc_dev->dev.release = fsl_mc_device_release; + mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type); + if (!mc_dev->dev.type) { + error = -ENODEV; + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type); + goto error_cleanup_dev; + } dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); if (strcmp(obj_desc->type, "dprc") == 0) { @@ -544,7 +600,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, /* * device being added is the root DPRC device */ - if (WARN_ON(!mc_io)) { + if (!mc_io) { error = -EINVAL; goto error_cleanup_dev; } @@ -826,7 +882,7 @@ static int fsl_mc_bus_remove(struct platform_device *pdev) { struct fsl_mc *mc = platform_get_drvdata(pdev); - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)) return -EINVAL; fsl_mc_device_remove(mc->root_mc_bus_dev); diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index f74a6f1764bb..625ba077f177 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -47,7 +47,7 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) { struct msi_domain_ops *ops = info->ops; - if (WARN_ON(!ops)) + if (!ops) return; /* @@ -73,7 +73,7 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) return; - if (WARN_ON(!owner_mc_dev)) + if (!owner_mc_dev) return; irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | @@ -124,7 +124,6 @@ static void fsl_mc_msi_write_msg(struct irq_data *irq_data, struct fsl_mc_device_irq *mc_dev_irq = &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; - WARN_ON(mc_dev_irq->msi_desc != msi_desc); msi_desc->msg = *msg; /* @@ -137,7 +136,7 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) { struct irq_chip *chip = info->chip; - if (WARN_ON(!chip)) + if (!chip) return; /* @@ -239,7 +238,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, struct irq_domain *msi_domain; int error; - if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) + if (!list_empty(dev_to_msi_list(dev))) return -EINVAL; error = fsl_mc_msi_alloc_descs(dev, irq_count); @@ -247,7 +246,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, return error; msi_domain = dev_get_msi_domain(dev); - if (WARN_ON(!msi_domain)) { + if (!msi_domain) { error = -EINVAL; goto cleanup_msi_descs; } @@ -275,12 +274,12 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev) struct irq_domain *msi_domain; msi_domain = dev_get_msi_domain(dev); - if (WARN_ON(!msi_domain)) + if (!msi_domain) return; msi_domain_free_irqs(msi_domain, dev); - if (WARN_ON(list_empty(dev_to_msi_list(dev)))) + if (list_empty(dev_to_msi_list(dev))) return; fsl_mc_msi_free_descs(dev); diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 123e4af58408..6d81ac022ef1 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -32,11 +32,11 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, struct fsl_mc_device *mc_bus_dev; struct msi_domain_info *msi_info; - if (WARN_ON(!dev_is_fsl_mc(dev))) + if (!dev_is_fsl_mc(dev)) return -EINVAL; mc_bus_dev = to_fsl_mc_device(dev); - if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC))) + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC)) return -EINVAL; /* @@ -93,9 +93,6 @@ int __init its_fsl_mc_msi_init(void) continue; } - WARN_ON(mc_msi_domain->host_data != - &its_fsl_mc_msi_domain_info); - pr_info("fsl-mc MSI: %pOF domain created\n", np); } diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index f65c23ce83f1..3cbf92d0862e 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -42,13 +42,10 @@ static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, { int error; - if (WARN_ON(!dpmcp_dev)) + if (mc_io->dpmcp_dev) return -EINVAL; - if (WARN_ON(mc_io->dpmcp_dev)) - return -EINVAL; - - if (WARN_ON(dpmcp_dev->mc_io)) + if (dpmcp_dev->mc_io) return -EINVAL; error = dpmcp_open(mc_io, @@ -68,12 +65,6 @@ static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) int error; struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; - - if (WARN_ON(dpmcp_dev->mc_io != mc_io)) - return; - error = dpmcp_close(mc_io, 0, dpmcp_dev->mc_handle); @@ -210,7 +201,7 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, if (mc_dev->flags & FSL_MC_IS_DPRC) { mc_bus_dev = mc_dev; } else { - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + if (!dev_is_fsl_mc(mc_dev->dev.parent)) return error; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -224,8 +215,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, error = -EINVAL; dpmcp_dev = resource->data; - if (WARN_ON(!dpmcp_dev)) - goto error_cleanup_resource; if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && @@ -238,15 +227,9 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, goto error_cleanup_resource; } - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) - goto error_cleanup_resource; - mc_portal_phys_addr = dpmcp_dev->regions[0].start; mc_portal_size = resource_size(dpmcp_dev->regions); - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) - goto error_cleanup_resource; - error = fsl_create_mc_io(&mc_bus_dev->dev, mc_portal_phys_addr, mc_portal_size, dpmcp_dev, @@ -279,14 +262,12 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io) * to have a DPMCP object associated with. */ dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; resource = dpmcp_dev->resource; - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) + if (!resource || resource->type != FSL_MC_POOL_DPMCP) return; - if (WARN_ON(resource->data != dpmcp_dev)) + if (resource->data != dpmcp_dev) return; fsl_destroy_mc_io(mc_io); @@ -304,9 +285,6 @@ int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) int error; struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); if (error < 0) { dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 7ce105bd3977..db3636da7bcb 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -85,7 +85,7 @@ static int mc_status_to_error(enum mc_cmd_status status) [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, }; - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map))) + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map)) return -EINVAL; return mc_status_to_error_map[status]; @@ -273,8 +273,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) enum mc_cmd_status status; unsigned long irq_flags = 0; - if (WARN_ON(in_irq() && - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) return -EINVAL; if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) @@ -320,4 +319,4 @@ common_exit: return error; } -EXPORT_SYMBOL(mc_send_command); +EXPORT_SYMBOL_GPL(mc_send_command); diff --git a/drivers/staging/fsl-mc/include/dpaa2-io.h b/drivers/staging/fsl-mc/include/dpaa2-io.h index afc2d060d077..07ad15ae9b7a 100644 --- a/drivers/staging/fsl-mc/include/dpaa2-io.h +++ b/drivers/staging/fsl-mc/include/dpaa2-io.h @@ -120,13 +120,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service, int dpaa2_io_service_rearm(struct dpaa2_io *service, struct dpaa2_io_notification_ctx *ctx); -int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, - struct dpaa2_io_store *s); int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, struct dpaa2_io_store *s); -int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid, - const struct dpaa2_fd *fd); int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio, u16 qdbin, const struct dpaa2_fd *fd); int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid, diff --git a/drivers/staging/fsl-mc/include/dpcon.h b/drivers/staging/fsl-mc/include/dpcon.h index efa23906b364..425749e7c681 100644 --- a/drivers/staging/fsl-mc/include/dpcon.h +++ b/drivers/staging/fsl-mc/include/dpcon.h @@ -62,11 +62,6 @@ int dpcon_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -int dpcon_is_enabled(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *en); - int dpcon_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); @@ -107,9 +102,4 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io, u16 token, struct dpcon_notification_cfg *cfg); -int dpcon_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver); - #endif /* __FSL_DPCON_H */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index aafe63a21f49..34d79a808b99 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -325,7 +325,7 @@ static inline void mc_cmd_read_api_version(struct mc_command *cmd, struct fsl_mc_io { struct device *dev; u16 flags; - u16 portal_size; + u32 portal_size; phys_addr_t portal_phys_addr; void __iomem *portal_virt_addr; struct fsl_mc_device *dpmcp_dev; @@ -398,4 +398,59 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); extern struct bus_type fsl_mc_bus_type; +extern struct device_type fsl_mc_bus_dprc_type; +extern struct device_type fsl_mc_bus_dpni_type; +extern struct device_type fsl_mc_bus_dpio_type; +extern struct device_type fsl_mc_bus_dpsw_type; +extern struct device_type fsl_mc_bus_dpbp_type; +extern struct device_type fsl_mc_bus_dpcon_type; +extern struct device_type fsl_mc_bus_dpmcp_type; +extern struct device_type fsl_mc_bus_dpmac_type; +extern struct device_type fsl_mc_bus_dprtc_type; + +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dprc_type; +} + +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpni_type; +} + +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpio_type; +} + +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type; +} + +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type; +} + +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type; +} + +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type; +} + +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type; +} + +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type; +} + #endif /* _FSL_MC_H_ */ diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 61377ca444de..59d1b35f6a4e 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -118,22 +118,23 @@ static inline ssize_t ad7152_start_calib(struct device *dev, mutex_lock(&chip->state_lock); ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG, regval); - if (ret < 0) { - mutex_unlock(&chip->state_lock); - return ret; - } + if (ret < 0) + goto unlock; do { mdelay(20); ret = i2c_smbus_read_byte_data(chip->client, AD7152_REG_CFG); - if (ret < 0) { - mutex_unlock(&chip->state_lock); - return ret; - } + if (ret < 0) + goto unlock; + } while ((ret == regval) && timeout--); mutex_unlock(&chip->state_lock); return len; + +unlock: + mutex_unlock(&chip->state_lock); + return ret; } static ssize_t ad7152_start_offset_calib(struct device *dev, diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index a124853a05f0..c4a864725376 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -302,23 +302,24 @@ static inline ssize_t ad7746_start_calib(struct device *dev, mutex_lock(&chip->lock); regval |= chip->config; ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); - if (ret < 0) { - mutex_unlock(&chip->lock); - return ret; - } + if (ret < 0) + goto unlock; do { msleep(20); ret = i2c_smbus_read_byte_data(chip->client, AD7746_REG_CFG); - if (ret < 0) { - mutex_unlock(&chip->lock); - return ret; - } + if (ret < 0) + goto unlock; + } while ((ret == regval) && timeout--); mutex_unlock(&chip->lock); return len; + +unlock: + mutex_unlock(&chip->lock); + return ret; } static ssize_t ad7746_start_offset_calib(struct device *dev, diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index d80dcf82eba9..f389f5cca99d 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -187,9 +187,9 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) return -ENOMEM; st->irq = platform_get_irq(pdev, 0); - if (!st->irq) { + if (st->irq < 0) { dev_err(&pdev->dev, "No IRQs specified"); - return -ENODEV; + return st->irq; } ret = iio_bfin_tmr_get_number(st->irq); diff --git a/drivers/staging/ipx/Kconfig b/drivers/staging/ipx/Kconfig new file mode 100644 index 000000000000..cdff083d0ee6 --- /dev/null +++ b/drivers/staging/ipx/Kconfig @@ -0,0 +1,61 @@ +# +# IPX configuration +# +config IPX + tristate "The IPX protocol" + depends on NET + select LLC + ---help--- + This is support for the Novell networking protocol, IPX, commonly + used for local networks of Windows machines. You need it if you + want to access Novell NetWare file or print servers using the Linux + Novell client ncpfs (available from + <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from + within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, + available from <http://www.tldp.org/docs.html#howto>). In order + to do the former, you'll also have to say Y to "NCP file system + support", below. + + IPX is similar in scope to IP, while SPX, which runs on top of IPX, + is similar to TCP. + + To turn your Linux box into a fully featured NetWare file server and + IPX router, say Y here and fetch either lwared from + <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or + mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more + information, read the IPX-HOWTO available from + <http://www.tldp.org/docs.html#howto>. + + The IPX driver would enlarge your kernel by about 16 KB. To compile + this driver as a module, choose M here: the module will be called ipx. + Unless you want to integrate your Linux box with a local Novell + network, say N. + +config IPX_INTERN + bool "IPX: Full internal IPX network" + depends on IPX + ---help--- + Every IPX network has an address that identifies it. Sometimes it is + useful to give an IPX "network" address to your Linux box as well + (for example if your box is acting as a file server for different + IPX networks: it will then be accessible from everywhere using the + same address). The way this is done is to create a virtual internal + "network" inside your box and to assign an IPX address to this + network. Say Y here if you want to do this; read the IPX-HOWTO at + <http://www.tldp.org/docs.html#howto> for details. + + The full internal IPX network enables you to allocate sockets on + different virtual nodes of the internal network. This is done by + evaluating the field sipx_node of the socket address given to the + bind call. So applications should always initialize the node field + to 0 when binding a socket on the primary network. In this case the + socket is assigned the default node that has been given to the + kernel when the internal network was created. By enabling the full + internal IPX network the cross-forwarding of packets targeted at + 'special' sockets to sockets listening on the primary network is + disabled. This might break existing applications, especially RIP/SAP + daemons. A RIP/SAP daemon that works well with the full internal net + can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>. + + If you don't know what you are doing, say N. + diff --git a/drivers/staging/ipx/Makefile b/drivers/staging/ipx/Makefile new file mode 100644 index 000000000000..440fafa9fd07 --- /dev/null +++ b/drivers/staging/ipx/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Linux IPX layer. +# + +obj-$(CONFIG_IPX) += ipx.o + +ipx-y := af_ipx.o ipx_route.o ipx_proc.o pe2.o +ipx-$(CONFIG_SYSCTL) += sysctl_net_ipx.o diff --git a/drivers/staging/ipx/TODO b/drivers/staging/ipx/TODO new file mode 100644 index 000000000000..80db5d968264 --- /dev/null +++ b/drivers/staging/ipx/TODO @@ -0,0 +1,4 @@ +The ipx code will be removed soon from the kernel tree as it is old and +obsolete and broken. + +Don't worry about fixing up anything here, it's not needed. diff --git a/drivers/staging/ipx/af_ipx.c b/drivers/staging/ipx/af_ipx.c new file mode 100644 index 000000000000..d21a9d128d3e --- /dev/null +++ b/drivers/staging/ipx/af_ipx.c @@ -0,0 +1,2084 @@ +/* + * Implements an IPX socket layer. + * + * This code is derived from work by + * Ross Biro : Writing the original IP stack + * Fred Van Kempen : Tidying up the TCP/IP + * + * Many thanks go to Keith Baker, Institute For Industrial Information + * Technology Ltd, Swansea University for allowing me to work on this + * in my own time even though it was in some ways related to commercial + * work I am currently employed to do there. + * + * All the material in this file is subject to the Gnu license version 2. + * Neither Alan Cox nor the Swansea University Computer Society admit + * liability nor provide warranty for any of this software. This material + * is provided as is and at no charge. + * + * Portions Copyright (c) 2000-2003 Conectiva, Inc. <acme@conectiva.com.br> + * Neither Arnaldo Carvalho de Melo nor Conectiva, Inc. admit liability nor + * provide warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com> + * Neither Greg Page nor Caldera, Inc. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * See net/ipx/ChangeLog. + */ + +#include <linux/capability.h> +#include <linux/errno.h> +#include <linux/if_arp.h> +#include <linux/if_ether.h> +#include <linux/init.h> +#include <linux/ipx.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/net.h> +#include <linux/netdevice.h> +#include <linux/uio.h> +#include <linux/slab.h> +#include <linux/skbuff.h> +#include <linux/socket.h> +#include <linux/sockios.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/termios.h> + +#include <net/ipx.h> +#include <net/p8022.h> +#include <net/psnap.h> +#include <net/sock.h> +#include <net/datalink.h> +#include <net/tcp_states.h> +#include <net/net_namespace.h> + +#include <linux/uaccess.h> + +/* Configuration Variables */ +static unsigned char ipxcfg_max_hops = 16; +static char ipxcfg_auto_select_primary; +static char ipxcfg_auto_create_interfaces; +int sysctl_ipx_pprop_broadcasting = 1; + +/* Global Variables */ +static struct datalink_proto *p8022_datalink; +static struct datalink_proto *pEII_datalink; +static struct datalink_proto *p8023_datalink; +static struct datalink_proto *pSNAP_datalink; + +static const struct proto_ops ipx_dgram_ops; + +LIST_HEAD(ipx_interfaces); +DEFINE_SPINLOCK(ipx_interfaces_lock); + +struct ipx_interface *ipx_primary_net; +struct ipx_interface *ipx_internal_net; + +struct ipx_interface *ipx_interfaces_head(void) +{ + struct ipx_interface *rc = NULL; + + if (!list_empty(&ipx_interfaces)) + rc = list_entry(ipx_interfaces.next, + struct ipx_interface, node); + return rc; +} + +static void ipxcfg_set_auto_select(char val) +{ + ipxcfg_auto_select_primary = val; + if (val && !ipx_primary_net) + ipx_primary_net = ipx_interfaces_head(); +} + +static int ipxcfg_get_config_data(struct ipx_config_data __user *arg) +{ + struct ipx_config_data vals; + + vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces; + vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary; + + return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0; +} + +/* + * Note: Sockets may not be removed _during_ an interrupt or inet_bh + * handler using this technique. They can be added although we do not + * use this facility. + */ + +static void ipx_remove_socket(struct sock *sk) +{ + /* Determine interface with which socket is associated */ + struct ipx_interface *intrfc = ipx_sk(sk)->intrfc; + + if (!intrfc) + goto out; + + ipxitf_hold(intrfc); + spin_lock_bh(&intrfc->if_sklist_lock); + sk_del_node_init(sk); + spin_unlock_bh(&intrfc->if_sklist_lock); + ipxitf_put(intrfc); +out: + return; +} + +static void ipx_destroy_socket(struct sock *sk) +{ + ipx_remove_socket(sk); + skb_queue_purge(&sk->sk_receive_queue); + sk_refcnt_debug_dec(sk); +} + +/* + * The following code is used to support IPX Interfaces (IPXITF). An + * IPX interface is defined by a physical device and a frame type. + */ + +/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */ + +static void ipxitf_clear_primary_net(void) +{ + ipx_primary_net = NULL; + if (ipxcfg_auto_select_primary) + ipx_primary_net = ipx_interfaces_head(); +} + +static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, + __be16 datalink) +{ + struct ipx_interface *i; + + list_for_each_entry(i, &ipx_interfaces, node) + if (i->if_dev == dev && i->if_dlink_type == datalink) + goto out; + i = NULL; +out: + return i; +} + +static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev, + __be16 datalink) +{ + struct ipx_interface *i; + + spin_lock_bh(&ipx_interfaces_lock); + i = __ipxitf_find_using_phys(dev, datalink); + if (i) + ipxitf_hold(i); + spin_unlock_bh(&ipx_interfaces_lock); + return i; +} + +struct ipx_interface *ipxitf_find_using_net(__be32 net) +{ + struct ipx_interface *i; + + spin_lock_bh(&ipx_interfaces_lock); + if (net) { + list_for_each_entry(i, &ipx_interfaces, node) + if (i->if_netnum == net) + goto hold; + i = NULL; + goto unlock; + } + + i = ipx_primary_net; + if (i) +hold: + ipxitf_hold(i); +unlock: + spin_unlock_bh(&ipx_interfaces_lock); + return i; +} + +/* Sockets are bound to a particular IPX interface. */ +static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk) +{ + ipxitf_hold(intrfc); + spin_lock_bh(&intrfc->if_sklist_lock); + ipx_sk(sk)->intrfc = intrfc; + sk_add_node(sk, &intrfc->if_sklist); + spin_unlock_bh(&intrfc->if_sklist_lock); + ipxitf_put(intrfc); +} + +/* caller must hold intrfc->if_sklist_lock */ +static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc, + __be16 port) +{ + struct sock *s; + + sk_for_each(s, &intrfc->if_sklist) + if (ipx_sk(s)->port == port) + goto found; + s = NULL; +found: + return s; +} + +/* caller must hold a reference to intrfc */ +static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc, + __be16 port) +{ + struct sock *s; + + spin_lock_bh(&intrfc->if_sklist_lock); + s = __ipxitf_find_socket(intrfc, port); + if (s) + sock_hold(s); + spin_unlock_bh(&intrfc->if_sklist_lock); + + return s; +} + +#ifdef CONFIG_IPX_INTERN +static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc, + unsigned char *ipx_node, + __be16 port) +{ + struct sock *s; + + ipxitf_hold(intrfc); + spin_lock_bh(&intrfc->if_sklist_lock); + + sk_for_each(s, &intrfc->if_sklist) { + struct ipx_sock *ipxs = ipx_sk(s); + + if (ipxs->port == port && + !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN)) + goto found; + } + s = NULL; +found: + spin_unlock_bh(&intrfc->if_sklist_lock); + ipxitf_put(intrfc); + return s; +} +#endif + +static void __ipxitf_down(struct ipx_interface *intrfc) +{ + struct sock *s; + struct hlist_node *t; + + /* Delete all routes associated with this interface */ + ipxrtr_del_routes(intrfc); + + spin_lock_bh(&intrfc->if_sklist_lock); + /* error sockets */ + sk_for_each_safe(s, t, &intrfc->if_sklist) { + struct ipx_sock *ipxs = ipx_sk(s); + + s->sk_err = ENOLINK; + s->sk_error_report(s); + ipxs->intrfc = NULL; + ipxs->port = 0; + sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */ + sk_del_node_init(s); + } + INIT_HLIST_HEAD(&intrfc->if_sklist); + spin_unlock_bh(&intrfc->if_sklist_lock); + + /* remove this interface from list */ + list_del(&intrfc->node); + + /* remove this interface from *special* networks */ + if (intrfc == ipx_primary_net) + ipxitf_clear_primary_net(); + if (intrfc == ipx_internal_net) + ipx_internal_net = NULL; + + if (intrfc->if_dev) + dev_put(intrfc->if_dev); + kfree(intrfc); +} + +void ipxitf_down(struct ipx_interface *intrfc) +{ + spin_lock_bh(&ipx_interfaces_lock); + __ipxitf_down(intrfc); + spin_unlock_bh(&ipx_interfaces_lock); +} + +static void __ipxitf_put(struct ipx_interface *intrfc) +{ + if (refcount_dec_and_test(&intrfc->refcnt)) + __ipxitf_down(intrfc); +} + +static int ipxitf_device_event(struct notifier_block *notifier, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct ipx_interface *i, *tmp; + + if (!net_eq(dev_net(dev), &init_net)) + return NOTIFY_DONE; + + if (event != NETDEV_DOWN && event != NETDEV_UP) + goto out; + + spin_lock_bh(&ipx_interfaces_lock); + list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) + if (i->if_dev == dev) { + if (event == NETDEV_UP) + ipxitf_hold(i); + else + __ipxitf_put(i); + } + spin_unlock_bh(&ipx_interfaces_lock); +out: + return NOTIFY_DONE; +} + + +static __exit void ipxitf_cleanup(void) +{ + struct ipx_interface *i, *tmp; + + spin_lock_bh(&ipx_interfaces_lock); + list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) + __ipxitf_put(i); + spin_unlock_bh(&ipx_interfaces_lock); +} + +static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb) +{ + if (sock_queue_rcv_skb(sock, skb) < 0) + kfree_skb(skb); +} + +/* + * On input skb->sk is NULL. Nobody is charged for the memory. + */ + +/* caller must hold a reference to intrfc */ + +#ifdef CONFIG_IPX_INTERN +static int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node, + IPX_NODE_LEN); + struct sock *s; + int rc; + + spin_lock_bh(&intrfc->if_sklist_lock); + + sk_for_each(s, &intrfc->if_sklist) { + struct ipx_sock *ipxs = ipx_sk(s); + + if (ipxs->port == ipx->ipx_dest.sock && + (is_broadcast || !memcmp(ipx->ipx_dest.node, + ipxs->node, IPX_NODE_LEN))) { + /* We found a socket to which to send */ + struct sk_buff *skb1; + + if (copy) { + skb1 = skb_clone(skb, GFP_ATOMIC); + rc = -ENOMEM; + if (!skb1) + goto out; + } else { + skb1 = skb; + copy = 1; /* skb may only be used once */ + } + ipxitf_def_skb_handler(s, skb1); + + /* On an external interface, one socket can listen */ + if (intrfc != ipx_internal_net) + break; + } + } + + /* skb was solely for us, and we did not make a copy, so free it. */ + if (!copy) + kfree_skb(skb); + + rc = 0; +out: + spin_unlock_bh(&intrfc->if_sklist_lock); + return rc; +} +#else +static struct sock *ncp_connection_hack(struct ipx_interface *intrfc, + struct ipxhdr *ipx) +{ + /* The packet's target is a NCP connection handler. We want to hand it + * to the correct socket directly within the kernel, so that the + * mars_nwe packet distribution process does not have to do it. Here we + * only care about NCP and BURST packets. + * + * You might call this a hack, but believe me, you do not want a + * complete NCP layer in the kernel, and this is VERY fast as well. */ + struct sock *sk = NULL; + int connection = 0; + u8 *ncphdr = (u8 *)(ipx + 1); + + if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */ + connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3); + else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */ + connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8); + + if (connection) { + /* Now we have to look for a special NCP connection handling + * socket. Only these sockets have ipx_ncp_conn != 0, set by + * SIOCIPXNCPCONN. */ + spin_lock_bh(&intrfc->if_sklist_lock); + sk_for_each(sk, &intrfc->if_sklist) + if (ipx_sk(sk)->ipx_ncp_conn == connection) { + sock_hold(sk); + goto found; + } + sk = NULL; + found: + spin_unlock_bh(&intrfc->if_sklist_lock); + } + return sk; +} + +static int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + struct sock *sock1 = NULL, *sock2 = NULL; + struct sk_buff *skb1 = NULL, *skb2 = NULL; + int rc; + + if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) + sock1 = ncp_connection_hack(intrfc, ipx); + if (!sock1) + /* No special socket found, forward the packet the normal way */ + sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock); + + /* + * We need to check if there is a primary net and if + * this is addressed to one of the *SPECIAL* sockets because + * these need to be propagated to the primary net. + * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and + * 0x456(Diagnostic). + */ + + if (ipx_primary_net && intrfc != ipx_primary_net) { + const int dsock = ntohs(ipx->ipx_dest.sock); + + if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456) + /* The appropriate thing to do here is to dup the + * packet and route to the primary net interface via + * ipxitf_send; however, we'll cheat and just demux it + * here. */ + sock2 = ipxitf_find_socket(ipx_primary_net, + ipx->ipx_dest.sock); + } + + /* + * If there is nothing to do return. The kfree will cancel any charging. + */ + rc = 0; + if (!sock1 && !sock2) { + if (!copy) + kfree_skb(skb); + goto out; + } + + /* + * This next segment of code is a little awkward, but it sets it up + * so that the appropriate number of copies of the SKB are made and + * that skb1 and skb2 point to it (them) so that it (they) can be + * demuxed to sock1 and/or sock2. If we are unable to make enough + * copies, we do as much as is possible. + */ + + if (copy) + skb1 = skb_clone(skb, GFP_ATOMIC); + else + skb1 = skb; + + rc = -ENOMEM; + if (!skb1) + goto out_put; + + /* Do we need 2 SKBs? */ + if (sock1 && sock2) + skb2 = skb_clone(skb1, GFP_ATOMIC); + else + skb2 = skb1; + + if (sock1) + ipxitf_def_skb_handler(sock1, skb1); + + if (!skb2) + goto out_put; + + if (sock2) + ipxitf_def_skb_handler(sock2, skb2); + + rc = 0; +out_put: + if (sock1) + sock_put(sock1); + if (sock2) + sock_put(sock2); +out: + return rc; +} +#endif /* CONFIG_IPX_INTERN */ + +static struct sk_buff *ipxitf_adjust_skbuff(struct ipx_interface *intrfc, + struct sk_buff *skb) +{ + struct sk_buff *skb2; + int in_offset = (unsigned char *)ipx_hdr(skb) - skb->head; + int out_offset = intrfc->if_ipx_offset; + int len; + + /* Hopefully, most cases */ + if (in_offset >= out_offset) + return skb; + + /* Need new SKB */ + len = skb->len + out_offset; + skb2 = alloc_skb(len, GFP_ATOMIC); + if (skb2) { + skb_reserve(skb2, out_offset); + skb_reset_network_header(skb2); + skb_reset_transport_header(skb2); + skb_put(skb2, skb->len); + memcpy(ipx_hdr(skb2), ipx_hdr(skb), skb->len); + memcpy(skb2->cb, skb->cb, sizeof(skb->cb)); + } + kfree_skb(skb); + return skb2; +} + +/* caller must hold a reference to intrfc and the skb has to be unshared */ +int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + struct net_device *dev = intrfc->if_dev; + struct datalink_proto *dl = intrfc->if_dlink; + char dest_node[IPX_NODE_LEN]; + int send_to_wire = 1; + int addr_len; + + ipx->ipx_tctrl = IPX_SKB_CB(skb)->ipx_tctrl; + ipx->ipx_dest.net = IPX_SKB_CB(skb)->ipx_dest_net; + ipx->ipx_source.net = IPX_SKB_CB(skb)->ipx_source_net; + + /* see if we need to include the netnum in the route list */ + if (IPX_SKB_CB(skb)->last_hop.index >= 0) { + __be32 *last_hop = (__be32 *)(((u8 *) skb->data) + + sizeof(struct ipxhdr) + + IPX_SKB_CB(skb)->last_hop.index * + sizeof(__be32)); + *last_hop = IPX_SKB_CB(skb)->last_hop.netnum; + IPX_SKB_CB(skb)->last_hop.index = -1; + } + + /* + * We need to know how many skbuffs it will take to send out this + * packet to avoid unnecessary copies. + */ + + if (!dl || !dev || dev->flags & IFF_LOOPBACK) + send_to_wire = 0; /* No non looped */ + + /* + * See if this should be demuxed to sockets on this interface + * + * We want to ensure the original was eaten or that we only use + * up clones. + */ + + if (ipx->ipx_dest.net == intrfc->if_netnum) { + /* + * To our own node, loop and free the original. + * The internal net will receive on all node address. + */ + if (intrfc == ipx_internal_net || + !memcmp(intrfc->if_node, node, IPX_NODE_LEN)) { + /* Don't charge sender */ + skb_orphan(skb); + + /* Will charge receiver */ + return ipxitf_demux_socket(intrfc, skb, 0); + } + + /* Broadcast, loop and possibly keep to send on. */ + if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) { + if (!send_to_wire) + skb_orphan(skb); + ipxitf_demux_socket(intrfc, skb, send_to_wire); + if (!send_to_wire) + goto out; + } + } + + /* + * If the originating net is not equal to our net; this is routed + * We are still charging the sender. Which is right - the driver + * free will handle this fairly. + */ + if (ipx->ipx_source.net != intrfc->if_netnum) { + /* + * Unshare the buffer before modifying the count in + * case it's a flood or tcpdump + */ + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (++ipx->ipx_tctrl > ipxcfg_max_hops) + send_to_wire = 0; + } + + if (!send_to_wire) { + kfree_skb(skb); + goto out; + } + + /* Determine the appropriate hardware address */ + addr_len = dev->addr_len; + if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) + memcpy(dest_node, dev->broadcast, addr_len); + else + memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len); + + /* Make any compensation for differing physical/data link size */ + skb = ipxitf_adjust_skbuff(intrfc, skb); + if (!skb) + goto out; + + /* set up data link and physical headers */ + skb->dev = dev; + skb->protocol = htons(ETH_P_IPX); + + /* Send it out */ + dl->request(dl, skb, dest_node); +out: + return 0; +} + +static int ipxitf_add_local_route(struct ipx_interface *intrfc) +{ + return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL); +} + +static void ipxitf_discover_netnum(struct ipx_interface *intrfc, + struct sk_buff *skb); +static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb); + +static int ipxitf_rcv(struct ipx_interface *intrfc, struct sk_buff *skb) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + int rc = 0; + + ipxitf_hold(intrfc); + + /* See if we should update our network number */ + if (!intrfc->if_netnum) /* net number of intrfc not known yet */ + ipxitf_discover_netnum(intrfc, skb); + + IPX_SKB_CB(skb)->last_hop.index = -1; + if (ipx->ipx_type == IPX_TYPE_PPROP) { + rc = ipxitf_pprop(intrfc, skb); + if (rc) + goto out_free_skb; + } + + /* local processing follows */ + if (!IPX_SKB_CB(skb)->ipx_dest_net) + IPX_SKB_CB(skb)->ipx_dest_net = intrfc->if_netnum; + if (!IPX_SKB_CB(skb)->ipx_source_net) + IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; + + /* it doesn't make sense to route a pprop packet, there's no meaning + * in the ipx_dest_net for such packets */ + if (ipx->ipx_type != IPX_TYPE_PPROP && + intrfc->if_netnum != IPX_SKB_CB(skb)->ipx_dest_net) { + /* We only route point-to-point packets. */ + if (skb->pkt_type == PACKET_HOST) { + skb = skb_unshare(skb, GFP_ATOMIC); + if (skb) + rc = ipxrtr_route_skb(skb); + goto out_intrfc; + } + + goto out_free_skb; + } + + /* see if we should keep it */ + if (!memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) || + !memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN)) { + rc = ipxitf_demux_socket(intrfc, skb, 0); + goto out_intrfc; + } + + /* we couldn't pawn it off so unload it */ +out_free_skb: + kfree_skb(skb); +out_intrfc: + ipxitf_put(intrfc); + return rc; +} + +static void ipxitf_discover_netnum(struct ipx_interface *intrfc, + struct sk_buff *skb) +{ + const struct ipx_cb *cb = IPX_SKB_CB(skb); + + /* see if this is an intra packet: source_net == dest_net */ + if (cb->ipx_source_net == cb->ipx_dest_net && cb->ipx_source_net) { + struct ipx_interface *i = + ipxitf_find_using_net(cb->ipx_source_net); + /* NB: NetWare servers lie about their hop count so we + * dropped the test based on it. This is the best way + * to determine this is a 0 hop count packet. */ + if (!i) { + intrfc->if_netnum = cb->ipx_source_net; + ipxitf_add_local_route(intrfc); + } else { + printk(KERN_WARNING "IPX: Network number collision " + "%lx\n %s %s and %s %s\n", + (unsigned long) ntohl(cb->ipx_source_net), + ipx_device_name(i), + ipx_frame_name(i->if_dlink_type), + ipx_device_name(intrfc), + ipx_frame_name(intrfc->if_dlink_type)); + ipxitf_put(i); + } + } +} + +/** + * ipxitf_pprop - Process packet propagation IPX packet type 0x14, used for + * NetBIOS broadcasts + * @intrfc: IPX interface receiving this packet + * @skb: Received packet + * + * Checks if packet is valid: if its more than %IPX_MAX_PPROP_HOPS hops or if it + * is smaller than a IPX header + the room for %IPX_MAX_PPROP_HOPS hops we drop + * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we + * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX + * RIP and SAP Router Specification", Part Number 107-000029-001. + * + * If it is valid, check if we have pprop broadcasting enabled by the user, + * if not, just return zero for local processing. + * + * If it is enabled check the packet and don't broadcast it if we have already + * seen this packet. + * + * Broadcast: send it to the interfaces that aren't on the packet visited nets + * array, just after the IPX header. + * + * Returns -EINVAL for invalid packets, so that the calling function drops + * the packet without local processing. 0 if packet is to be locally processed. + */ +static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + int i, rc = -EINVAL; + struct ipx_interface *ifcs; + char *c; + __be32 *l; + + /* Illegal packet - too many hops or too short */ + /* We decide to throw it away: no broadcasting, no local processing. + * NetBIOS unaware implementations route them as normal packets - + * tctrl <= 15, any data payload... */ + if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS || + ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) + + IPX_MAX_PPROP_HOPS * sizeof(u32)) + goto out; + /* are we broadcasting this damn thing? */ + rc = 0; + if (!sysctl_ipx_pprop_broadcasting) + goto out; + /* We do broadcast packet on the IPX_MAX_PPROP_HOPS hop, but we + * process it locally. All previous hops broadcasted it, and process it + * locally. */ + if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS) + goto out; + + c = ((u8 *) ipx) + sizeof(struct ipxhdr); + l = (__be32 *) c; + + /* Don't broadcast packet if already seen this net */ + for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) + if (*l++ == intrfc->if_netnum) + goto out; + + /* < IPX_MAX_PPROP_HOPS hops && input interface not in list. Save the + * position where we will insert recvd netnum into list, later on, + * in ipxitf_send */ + IPX_SKB_CB(skb)->last_hop.index = i; + IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum; + /* xmit on all other interfaces... */ + spin_lock_bh(&ipx_interfaces_lock); + list_for_each_entry(ifcs, &ipx_interfaces, node) { + /* Except unconfigured interfaces */ + if (!ifcs->if_netnum) + continue; + + /* That aren't in the list */ + if (ifcs == intrfc) + continue; + l = (__be32 *) c; + /* don't consider the last entry in the packet list, + * it is our netnum, and it is not there yet */ + for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) + if (ifcs->if_netnum == *l++) + break; + if (i == IPX_SKB_CB(skb)->ipx_tctrl) { + struct sk_buff *s = skb_copy(skb, GFP_ATOMIC); + + if (s) { + IPX_SKB_CB(s)->ipx_dest_net = ifcs->if_netnum; + ipxrtr_route_skb(s); + } + } + } + spin_unlock_bh(&ipx_interfaces_lock); +out: + return rc; +} + +static void ipxitf_insert(struct ipx_interface *intrfc) +{ + spin_lock_bh(&ipx_interfaces_lock); + list_add_tail(&intrfc->node, &ipx_interfaces); + spin_unlock_bh(&ipx_interfaces_lock); + + if (ipxcfg_auto_select_primary && !ipx_primary_net) + ipx_primary_net = intrfc; +} + +static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum, + __be16 dlink_type, + struct datalink_proto *dlink, + unsigned char internal, + int ipx_offset) +{ + struct ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC); + + if (intrfc) { + intrfc->if_dev = dev; + intrfc->if_netnum = netnum; + intrfc->if_dlink_type = dlink_type; + intrfc->if_dlink = dlink; + intrfc->if_internal = internal; + intrfc->if_ipx_offset = ipx_offset; + intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET; + INIT_HLIST_HEAD(&intrfc->if_sklist); + refcount_set(&intrfc->refcnt, 1); + spin_lock_init(&intrfc->if_sklist_lock); + } + + return intrfc; +} + +static int ipxitf_create_internal(struct ipx_interface_definition *idef) +{ + struct ipx_interface *intrfc; + int rc = -EEXIST; + + /* Only one primary network allowed */ + if (ipx_primary_net) + goto out; + + /* Must have a valid network number */ + rc = -EADDRNOTAVAIL; + if (!idef->ipx_network) + goto out; + intrfc = ipxitf_find_using_net(idef->ipx_network); + rc = -EADDRINUSE; + if (intrfc) { + ipxitf_put(intrfc); + goto out; + } + intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0); + rc = -EAGAIN; + if (!intrfc) + goto out; + memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN); + ipx_internal_net = ipx_primary_net = intrfc; + ipxitf_hold(intrfc); + ipxitf_insert(intrfc); + + rc = ipxitf_add_local_route(intrfc); + ipxitf_put(intrfc); +out: + return rc; +} + +static __be16 ipx_map_frame_type(unsigned char type) +{ + __be16 rc = 0; + + switch (type) { + case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX); break; + case IPX_FRAME_8022: rc = htons(ETH_P_802_2); break; + case IPX_FRAME_SNAP: rc = htons(ETH_P_SNAP); break; + case IPX_FRAME_8023: rc = htons(ETH_P_802_3); break; + } + + return rc; +} + +static int ipxitf_create(struct ipx_interface_definition *idef) +{ + struct net_device *dev; + __be16 dlink_type = 0; + struct datalink_proto *datalink = NULL; + struct ipx_interface *intrfc; + int rc; + + if (idef->ipx_special == IPX_INTERNAL) { + rc = ipxitf_create_internal(idef); + goto out; + } + + rc = -EEXIST; + if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net) + goto out; + + intrfc = ipxitf_find_using_net(idef->ipx_network); + rc = -EADDRINUSE; + if (idef->ipx_network && intrfc) { + ipxitf_put(intrfc); + goto out; + } + + if (intrfc) + ipxitf_put(intrfc); + + dev = dev_get_by_name(&init_net, idef->ipx_device); + rc = -ENODEV; + if (!dev) + goto out; + + switch (idef->ipx_dlink_type) { + case IPX_FRAME_8022: + dlink_type = htons(ETH_P_802_2); + datalink = p8022_datalink; + break; + case IPX_FRAME_ETHERII: + if (dev->type != ARPHRD_IEEE802) { + dlink_type = htons(ETH_P_IPX); + datalink = pEII_datalink; + break; + } + /* fall through */ + case IPX_FRAME_SNAP: + dlink_type = htons(ETH_P_SNAP); + datalink = pSNAP_datalink; + break; + case IPX_FRAME_8023: + dlink_type = htons(ETH_P_802_3); + datalink = p8023_datalink; + break; + case IPX_FRAME_NONE: + default: + rc = -EPROTONOSUPPORT; + goto out_dev; + } + + rc = -ENETDOWN; + if (!(dev->flags & IFF_UP)) + goto out_dev; + + /* Check addresses are suitable */ + rc = -EINVAL; + if (dev->addr_len > IPX_NODE_LEN) + goto out_dev; + + intrfc = ipxitf_find_using_phys(dev, dlink_type); + if (!intrfc) { + /* Ok now create */ + intrfc = ipxitf_alloc(dev, idef->ipx_network, dlink_type, + datalink, 0, dev->hard_header_len + + datalink->header_length); + rc = -EAGAIN; + if (!intrfc) + goto out_dev; + /* Setup primary if necessary */ + if (idef->ipx_special == IPX_PRIMARY) + ipx_primary_net = intrfc; + if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000", + IPX_NODE_LEN)) { + memset(intrfc->if_node, 0, IPX_NODE_LEN); + memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len, + dev->dev_addr, dev->addr_len); + } else + memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN); + ipxitf_hold(intrfc); + ipxitf_insert(intrfc); + } + + + /* If the network number is known, add a route */ + rc = 0; + if (!intrfc->if_netnum) + goto out_intrfc; + + rc = ipxitf_add_local_route(intrfc); +out_intrfc: + ipxitf_put(intrfc); + goto out; +out_dev: + dev_put(dev); +out: + return rc; +} + +static int ipxitf_delete(struct ipx_interface_definition *idef) +{ + struct net_device *dev = NULL; + __be16 dlink_type = 0; + struct ipx_interface *intrfc; + int rc = 0; + + spin_lock_bh(&ipx_interfaces_lock); + if (idef->ipx_special == IPX_INTERNAL) { + if (ipx_internal_net) { + __ipxitf_put(ipx_internal_net); + goto out; + } + rc = -ENOENT; + goto out; + } + + dlink_type = ipx_map_frame_type(idef->ipx_dlink_type); + rc = -EPROTONOSUPPORT; + if (!dlink_type) + goto out; + + dev = __dev_get_by_name(&init_net, idef->ipx_device); + rc = -ENODEV; + if (!dev) + goto out; + + intrfc = __ipxitf_find_using_phys(dev, dlink_type); + rc = -EINVAL; + if (!intrfc) + goto out; + __ipxitf_put(intrfc); + + rc = 0; +out: + spin_unlock_bh(&ipx_interfaces_lock); + return rc; +} + +static struct ipx_interface *ipxitf_auto_create(struct net_device *dev, + __be16 dlink_type) +{ + struct ipx_interface *intrfc = NULL; + struct datalink_proto *datalink; + + if (!dev) + goto out; + + /* Check addresses are suitable */ + if (dev->addr_len > IPX_NODE_LEN) + goto out; + + switch (ntohs(dlink_type)) { + case ETH_P_IPX: datalink = pEII_datalink; break; + case ETH_P_802_2: datalink = p8022_datalink; break; + case ETH_P_SNAP: datalink = pSNAP_datalink; break; + case ETH_P_802_3: datalink = p8023_datalink; break; + default: goto out; + } + + intrfc = ipxitf_alloc(dev, 0, dlink_type, datalink, 0, + dev->hard_header_len + datalink->header_length); + + if (intrfc) { + memset(intrfc->if_node, 0, IPX_NODE_LEN); + memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]), + dev->dev_addr, dev->addr_len); + spin_lock_init(&intrfc->if_sklist_lock); + refcount_set(&intrfc->refcnt, 1); + ipxitf_insert(intrfc); + dev_hold(dev); + } + +out: + return intrfc; +} + +static int ipxitf_ioctl(unsigned int cmd, void __user *arg) +{ + int rc = -EINVAL; + struct ifreq ifr; + int val; + + switch (cmd) { + case SIOCSIFADDR: { + struct sockaddr_ipx *sipx; + struct ipx_interface_definition f; + + rc = -EFAULT; + if (copy_from_user(&ifr, arg, sizeof(ifr))) + break; + sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; + rc = -EINVAL; + if (sipx->sipx_family != AF_IPX) + break; + f.ipx_network = sipx->sipx_network; + memcpy(f.ipx_device, ifr.ifr_name, + sizeof(f.ipx_device)); + memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN); + f.ipx_dlink_type = sipx->sipx_type; + f.ipx_special = sipx->sipx_special; + + if (sipx->sipx_action == IPX_DLTITF) + rc = ipxitf_delete(&f); + else + rc = ipxitf_create(&f); + break; + } + case SIOCGIFADDR: { + struct sockaddr_ipx *sipx; + struct ipx_interface *ipxif; + struct net_device *dev; + + rc = -EFAULT; + if (copy_from_user(&ifr, arg, sizeof(ifr))) + break; + sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; + dev = __dev_get_by_name(&init_net, ifr.ifr_name); + rc = -ENODEV; + if (!dev) + break; + ipxif = ipxitf_find_using_phys(dev, + ipx_map_frame_type(sipx->sipx_type)); + rc = -EADDRNOTAVAIL; + if (!ipxif) + break; + + sipx->sipx_family = AF_IPX; + sipx->sipx_network = ipxif->if_netnum; + memcpy(sipx->sipx_node, ipxif->if_node, + sizeof(sipx->sipx_node)); + rc = 0; + if (copy_to_user(arg, &ifr, sizeof(ifr))) + rc = -EFAULT; + ipxitf_put(ipxif); + break; + } + case SIOCAIPXITFCRT: + rc = -EFAULT; + if (get_user(val, (unsigned char __user *) arg)) + break; + rc = 0; + ipxcfg_auto_create_interfaces = val; + break; + case SIOCAIPXPRISLT: + rc = -EFAULT; + if (get_user(val, (unsigned char __user *) arg)) + break; + rc = 0; + ipxcfg_set_auto_select(val); + break; + } + + return rc; +} + +/* + * Checksum routine for IPX + */ + +/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */ +/* This functions should *not* mess with packet contents */ + +__be16 ipx_cksum(struct ipxhdr *packet, int length) +{ + /* + * NOTE: sum is a net byte order quantity, which optimizes the + * loop. This only works on big and little endian machines. (I + * don't know of a machine that isn't.) + */ + /* handle the first 3 words separately; checksum should be skipped + * and ipx_tctrl masked out */ + __u16 *p = (__u16 *)packet; + __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff)); + __u32 i = (length >> 1) - 3; /* Number of remaining complete words */ + + /* Loop through them */ + p += 3; + while (i--) + sum += *p++; + + /* Add on the last part word if it exists */ + if (packet->ipx_pktsize & htons(1)) + sum += (__force u16)htons(0xff00) & *p; + + /* Do final fixup */ + sum = (sum & 0xffff) + (sum >> 16); + + /* It's a pity there's no concept of carry in C */ + if (sum >= 0x10000) + sum++; + + /* + * Leave 0 alone; we don't want 0xffff here. Note that we can't get + * here with 0x10000, so this check is the same as ((__u16)sum) + */ + if (sum) + sum = ~sum; + + return (__force __be16)sum; +} + +const char *ipx_frame_name(__be16 frame) +{ + char* rc = "None"; + + switch (ntohs(frame)) { + case ETH_P_IPX: rc = "EtherII"; break; + case ETH_P_802_2: rc = "802.2"; break; + case ETH_P_SNAP: rc = "SNAP"; break; + case ETH_P_802_3: rc = "802.3"; break; + } + + return rc; +} + +const char *ipx_device_name(struct ipx_interface *intrfc) +{ + return intrfc->if_internal ? "Internal" : + intrfc->if_dev ? intrfc->if_dev->name : "Unknown"; +} + +/* Handling for system calls applied via the various interfaces to an IPX + * socket object. */ + +static int ipx_setsockopt(struct socket *sock, int level, int optname, + char __user *optval, unsigned int optlen) +{ + struct sock *sk = sock->sk; + int opt; + int rc = -EINVAL; + + lock_sock(sk); + if (optlen != sizeof(int)) + goto out; + + rc = -EFAULT; + if (get_user(opt, (unsigned int __user *)optval)) + goto out; + + rc = -ENOPROTOOPT; + if (!(level == SOL_IPX && optname == IPX_TYPE)) + goto out; + + ipx_sk(sk)->type = opt; + rc = 0; +out: + release_sock(sk); + return rc; +} + +static int ipx_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) +{ + struct sock *sk = sock->sk; + int val = 0; + int len; + int rc = -ENOPROTOOPT; + + lock_sock(sk); + if (!(level == SOL_IPX && optname == IPX_TYPE)) + goto out; + + val = ipx_sk(sk)->type; + + rc = -EFAULT; + if (get_user(len, optlen)) + goto out; + + len = min_t(unsigned int, len, sizeof(int)); + rc = -EINVAL; + if(len < 0) + goto out; + + rc = -EFAULT; + if (put_user(len, optlen) || copy_to_user(optval, &val, len)) + goto out; + + rc = 0; +out: + release_sock(sk); + return rc; +} + +static struct proto ipx_proto = { + .name = "IPX", + .owner = THIS_MODULE, + .obj_size = sizeof(struct ipx_sock), +}; + +static int ipx_create(struct net *net, struct socket *sock, int protocol, + int kern) +{ + int rc = -ESOCKTNOSUPPORT; + struct sock *sk; + + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + + /* + * SPX support is not anymore in the kernel sources. If you want to + * ressurrect it, completing it and making it understand shared skbs, + * be fully multithreaded, etc, grab the sources in an early 2.5 kernel + * tree. + */ + if (sock->type != SOCK_DGRAM) + goto out; + + rc = -ENOMEM; + sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, kern); + if (!sk) + goto out; + + sk_refcnt_debug_inc(sk); + sock_init_data(sock, sk); + sk->sk_no_check_tx = 1; /* Checksum off by default */ + sock->ops = &ipx_dgram_ops; + rc = 0; +out: + return rc; +} + +static int ipx_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (!sk) + goto out; + + lock_sock(sk); + sk->sk_shutdown = SHUTDOWN_MASK; + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_state_change(sk); + + sock_set_flag(sk, SOCK_DEAD); + sock->sk = NULL; + sk_refcnt_debug_release(sk); + ipx_destroy_socket(sk); + release_sock(sk); + sock_put(sk); +out: + return 0; +} + +/* caller must hold a reference to intrfc */ + +static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc) +{ + unsigned short socketNum = intrfc->if_sknum; + + spin_lock_bh(&intrfc->if_sklist_lock); + + if (socketNum < IPX_MIN_EPHEMERAL_SOCKET) + socketNum = IPX_MIN_EPHEMERAL_SOCKET; + + while (__ipxitf_find_socket(intrfc, htons(socketNum))) + if (socketNum > IPX_MAX_EPHEMERAL_SOCKET) + socketNum = IPX_MIN_EPHEMERAL_SOCKET; + else + socketNum++; + + spin_unlock_bh(&intrfc->if_sklist_lock); + intrfc->if_sknum = socketNum; + + return htons(socketNum); +} + +static int __ipx_bind(struct socket *sock, + struct sockaddr *uaddr, int addr_len) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + struct ipx_interface *intrfc; + struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr; + int rc = -EINVAL; + + if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx)) + goto out; + + intrfc = ipxitf_find_using_net(addr->sipx_network); + rc = -EADDRNOTAVAIL; + if (!intrfc) + goto out; + + if (!addr->sipx_port) { + addr->sipx_port = ipx_first_free_socketnum(intrfc); + rc = -EINVAL; + if (!addr->sipx_port) + goto out_put; + } + + /* protect IPX system stuff like routing/sap */ + rc = -EACCES; + if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && + !capable(CAP_NET_ADMIN)) + goto out_put; + + ipxs->port = addr->sipx_port; + +#ifdef CONFIG_IPX_INTERN + if (intrfc == ipx_internal_net) { + /* The source address is to be set explicitly if the + * socket is to be bound on the internal network. If a + * node number 0 was specified, the default is used. + */ + + rc = -EINVAL; + if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN)) + goto out_put; + if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN)) + memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN); + else + memcpy(ipxs->node, addr->sipx_node, IPX_NODE_LEN); + + rc = -EADDRINUSE; + if (ipxitf_find_internal_socket(intrfc, ipxs->node, + ipxs->port)) { + SOCK_DEBUG(sk, + "IPX: bind failed because port %X in use.\n", + ntohs(addr->sipx_port)); + goto out_put; + } + } else { + /* Source addresses are easy. It must be our + * network:node pair for an interface routed to IPX + * with the ipx routing ioctl() + */ + + memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN); + + rc = -EADDRINUSE; + if (ipxitf_find_socket(intrfc, addr->sipx_port)) { + SOCK_DEBUG(sk, + "IPX: bind failed because port %X in use.\n", + ntohs(addr->sipx_port)); + goto out_put; + } + } + +#else /* !def CONFIG_IPX_INTERN */ + + /* Source addresses are easy. It must be our network:node pair for + an interface routed to IPX with the ipx routing ioctl() */ + + rc = -EADDRINUSE; + if (ipxitf_find_socket(intrfc, addr->sipx_port)) { + SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", + ntohs((int)addr->sipx_port)); + goto out_put; + } + +#endif /* CONFIG_IPX_INTERN */ + + ipxitf_insert_socket(intrfc, sk); + sock_reset_flag(sk, SOCK_ZAPPED); + + rc = 0; +out_put: + ipxitf_put(intrfc); +out: + return rc; +} + +static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) +{ + struct sock *sk = sock->sk; + int rc; + + lock_sock(sk); + rc = __ipx_bind(sock, uaddr, addr_len); + release_sock(sk); + + return rc; +} + +static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + struct sockaddr_ipx *addr; + int rc = -EINVAL; + struct ipx_route *rt; + + sk->sk_state = TCP_CLOSE; + sock->state = SS_UNCONNECTED; + + lock_sock(sk); + if (addr_len != sizeof(*addr)) + goto out; + addr = (struct sockaddr_ipx *)uaddr; + + /* put the autobinding in */ + if (!ipxs->port) { + struct sockaddr_ipx uaddr; + + uaddr.sipx_port = 0; + uaddr.sipx_network = 0; + +#ifdef CONFIG_IPX_INTERN + rc = -ENETDOWN; + if (!ipxs->intrfc) + goto out; /* Someone zonked the iface */ + memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, + IPX_NODE_LEN); +#endif /* CONFIG_IPX_INTERN */ + + rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + sizeof(struct sockaddr_ipx)); + if (rc) + goto out; + } + + /* We can either connect to primary network or somewhere + * we can route to */ + rt = ipxrtr_lookup(addr->sipx_network); + rc = -ENETUNREACH; + if (!rt && !(!addr->sipx_network && ipx_primary_net)) + goto out; + + ipxs->dest_addr.net = addr->sipx_network; + ipxs->dest_addr.sock = addr->sipx_port; + memcpy(ipxs->dest_addr.node, addr->sipx_node, IPX_NODE_LEN); + ipxs->type = addr->sipx_type; + + if (sock->type == SOCK_DGRAM) { + sock->state = SS_CONNECTED; + sk->sk_state = TCP_ESTABLISHED; + } + + if (rt) + ipxrtr_put(rt); + rc = 0; +out: + release_sock(sk); + return rc; +} + + +static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + struct ipx_address *addr; + struct sockaddr_ipx sipx; + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + int rc; + + *uaddr_len = sizeof(struct sockaddr_ipx); + + lock_sock(sk); + if (peer) { + rc = -ENOTCONN; + if (sk->sk_state != TCP_ESTABLISHED) + goto out; + + addr = &ipxs->dest_addr; + sipx.sipx_network = addr->net; + sipx.sipx_port = addr->sock; + memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN); + } else { + if (ipxs->intrfc) { + sipx.sipx_network = ipxs->intrfc->if_netnum; +#ifdef CONFIG_IPX_INTERN + memcpy(sipx.sipx_node, ipxs->node, IPX_NODE_LEN); +#else + memcpy(sipx.sipx_node, ipxs->intrfc->if_node, + IPX_NODE_LEN); +#endif /* CONFIG_IPX_INTERN */ + + } else { + sipx.sipx_network = 0; + memset(sipx.sipx_node, '\0', IPX_NODE_LEN); + } + + sipx.sipx_port = ipxs->port; + } + + sipx.sipx_family = AF_IPX; + sipx.sipx_type = ipxs->type; + sipx.sipx_zero = 0; + memcpy(uaddr, &sipx, sizeof(sipx)); + + rc = 0; +out: + release_sock(sk); + return rc; +} + +static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) +{ + /* NULL here for pt means the packet was looped back */ + struct ipx_interface *intrfc; + struct ipxhdr *ipx; + u16 ipx_pktsize; + int rc = 0; + + if (!net_eq(dev_net(dev), &init_net)) + goto drop; + + /* Not ours */ + if (skb->pkt_type == PACKET_OTHERHOST) + goto drop; + + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + goto out; + + if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) + goto drop; + + ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); + + /* Too small or invalid header? */ + if (ipx_pktsize < sizeof(struct ipxhdr) || + !pskb_may_pull(skb, ipx_pktsize)) + goto drop; + + ipx = ipx_hdr(skb); + if (ipx->ipx_checksum != IPX_NO_CHECKSUM && + ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) + goto drop; + + IPX_SKB_CB(skb)->ipx_tctrl = ipx->ipx_tctrl; + IPX_SKB_CB(skb)->ipx_dest_net = ipx->ipx_dest.net; + IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net; + + /* Determine what local ipx endpoint this is */ + intrfc = ipxitf_find_using_phys(dev, pt->type); + if (!intrfc) { + if (ipxcfg_auto_create_interfaces && + IPX_SKB_CB(skb)->ipx_dest_net) { + intrfc = ipxitf_auto_create(dev, pt->type); + if (intrfc) + ipxitf_hold(intrfc); + } + + if (!intrfc) /* Not one of ours */ + /* or invalid packet for auto creation */ + goto drop; + } + + rc = ipxitf_rcv(intrfc, skb); + ipxitf_put(intrfc); + goto out; +drop: + kfree_skb(skb); +out: + return rc; +} + +static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + DECLARE_SOCKADDR(struct sockaddr_ipx *, usipx, msg->msg_name); + struct sockaddr_ipx local_sipx; + int rc = -EINVAL; + int flags = msg->msg_flags; + + lock_sock(sk); + /* Socket gets bound below anyway */ +/* if (sk->sk_zapped) + return -EIO; */ /* Socket not bound */ + if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) + goto out; + + /* Max possible packet size limited by 16 bit pktsize in header */ + if (len >= 65535 - sizeof(struct ipxhdr)) + goto out; + + if (usipx) { + if (!ipxs->port) { + struct sockaddr_ipx uaddr; + + uaddr.sipx_port = 0; + uaddr.sipx_network = 0; +#ifdef CONFIG_IPX_INTERN + rc = -ENETDOWN; + if (!ipxs->intrfc) + goto out; /* Someone zonked the iface */ + memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, + IPX_NODE_LEN); +#endif + rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + sizeof(struct sockaddr_ipx)); + if (rc) + goto out; + } + + rc = -EINVAL; + if (msg->msg_namelen < sizeof(*usipx) || + usipx->sipx_family != AF_IPX) + goto out; + } else { + rc = -ENOTCONN; + if (sk->sk_state != TCP_ESTABLISHED) + goto out; + + usipx = &local_sipx; + usipx->sipx_family = AF_IPX; + usipx->sipx_type = ipxs->type; + usipx->sipx_port = ipxs->dest_addr.sock; + usipx->sipx_network = ipxs->dest_addr.net; + memcpy(usipx->sipx_node, ipxs->dest_addr.node, IPX_NODE_LEN); + } + + rc = ipxrtr_route_packet(sk, usipx, msg, len, flags & MSG_DONTWAIT); + if (rc >= 0) + rc = len; +out: + release_sock(sk); + return rc; +} + + +static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, + int flags) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + DECLARE_SOCKADDR(struct sockaddr_ipx *, sipx, msg->msg_name); + struct ipxhdr *ipx = NULL; + struct sk_buff *skb; + int copied, rc; + bool locked = true; + + lock_sock(sk); + /* put the autobinding in */ + if (!ipxs->port) { + struct sockaddr_ipx uaddr; + + uaddr.sipx_port = 0; + uaddr.sipx_network = 0; + +#ifdef CONFIG_IPX_INTERN + rc = -ENETDOWN; + if (!ipxs->intrfc) + goto out; /* Someone zonked the iface */ + memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); +#endif /* CONFIG_IPX_INTERN */ + + rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + sizeof(struct sockaddr_ipx)); + if (rc) + goto out; + } + + rc = -ENOTCONN; + if (sock_flag(sk, SOCK_ZAPPED)) + goto out; + + release_sock(sk); + locked = false; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &rc); + if (!skb) { + if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN)) + rc = 0; + goto out; + } + + ipx = ipx_hdr(skb); + copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr); + if (copied > size) { + copied = size; + msg->msg_flags |= MSG_TRUNC; + } + + rc = skb_copy_datagram_msg(skb, sizeof(struct ipxhdr), msg, copied); + if (rc) + goto out_free; + if (skb->tstamp) + sk->sk_stamp = skb->tstamp; + + if (sipx) { + sipx->sipx_family = AF_IPX; + sipx->sipx_port = ipx->ipx_source.sock; + memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN); + sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; + sipx->sipx_type = ipx->ipx_type; + sipx->sipx_zero = 0; + msg->msg_namelen = sizeof(*sipx); + } + rc = copied; + +out_free: + skb_free_datagram(sk, skb); +out: + if (locked) + release_sock(sk); + return rc; +} + + +static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + long amount = 0; + struct sock *sk = sock->sk; + void __user *argp = (void __user *)arg; + + lock_sock(sk); + switch (cmd) { + case TIOCOUTQ: + amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); + if (amount < 0) + amount = 0; + rc = put_user(amount, (int __user *)argp); + break; + case TIOCINQ: { + struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); + /* These two are safe on a single CPU system as only + * user tasks fiddle here */ + if (skb) + amount = skb->len - sizeof(struct ipxhdr); + rc = put_user(amount, (int __user *)argp); + break; + } + case SIOCADDRT: + case SIOCDELRT: + rc = -EPERM; + if (capable(CAP_NET_ADMIN)) + rc = ipxrtr_ioctl(cmd, argp); + break; + case SIOCSIFADDR: + case SIOCAIPXITFCRT: + case SIOCAIPXPRISLT: + rc = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; + /* fall through */ + case SIOCGIFADDR: + rc = ipxitf_ioctl(cmd, argp); + break; + case SIOCIPXCFGDATA: + rc = ipxcfg_get_config_data(argp); + break; + case SIOCIPXNCPCONN: + /* + * This socket wants to take care of the NCP connection + * handed to us in arg. + */ + rc = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; + rc = get_user(ipx_sk(sk)->ipx_ncp_conn, + (const unsigned short __user *)argp); + break; + case SIOCGSTAMP: + rc = sock_get_timestamp(sk, argp); + break; + case SIOCGIFDSTADDR: + case SIOCSIFDSTADDR: + case SIOCGIFBRDADDR: + case SIOCSIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCSIFNETMASK: + rc = -EINVAL; + break; + default: + rc = -ENOIOCTLCMD; + break; + } + release_sock(sk); + + return rc; +} + + +#ifdef CONFIG_COMPAT +static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + /* + * These 4 commands use same structure on 32bit and 64bit. Rest of IPX + * commands is handled by generic ioctl code. As these commands are + * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic + * code. + */ + switch (cmd) { + case SIOCAIPXITFCRT: + case SIOCAIPXPRISLT: + case SIOCIPXCFGDATA: + case SIOCIPXNCPCONN: + return ipx_ioctl(sock, cmd, arg); + default: + return -ENOIOCTLCMD; + } +} +#endif + +static int ipx_shutdown(struct socket *sock, int mode) +{ + struct sock *sk = sock->sk; + + if (mode < SHUT_RD || mode > SHUT_RDWR) + return -EINVAL; + /* This maps: + * SHUT_RD (0) -> RCV_SHUTDOWN (1) + * SHUT_WR (1) -> SEND_SHUTDOWN (2) + * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) + */ + ++mode; + + lock_sock(sk); + sk->sk_shutdown |= mode; + release_sock(sk); + sk->sk_state_change(sk); + + return 0; +} + +/* + * Socket family declarations + */ + +static const struct net_proto_family ipx_family_ops = { + .family = PF_IPX, + .create = ipx_create, + .owner = THIS_MODULE, +}; + +static const struct proto_ops ipx_dgram_ops = { + .family = PF_IPX, + .owner = THIS_MODULE, + .release = ipx_release, + .bind = ipx_bind, + .connect = ipx_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = ipx_getname, + .poll = datagram_poll, + .ioctl = ipx_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ipx_compat_ioctl, +#endif + .listen = sock_no_listen, + .shutdown = ipx_shutdown, + .setsockopt = ipx_setsockopt, + .getsockopt = ipx_getsockopt, + .sendmsg = ipx_sendmsg, + .recvmsg = ipx_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + +static struct packet_type ipx_8023_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_802_3), + .func = ipx_rcv, +}; + +static struct packet_type ipx_dix_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_IPX), + .func = ipx_rcv, +}; + +static struct notifier_block ipx_dev_notifier = { + .notifier_call = ipxitf_device_event, +}; + +static const unsigned char ipx_8022_type = 0xE0; +static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; +static const char ipx_EII_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with Ethernet II\n"; +static const char ipx_8023_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with 802.3\n"; +static const char ipx_llc_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with 802.2\n"; +static const char ipx_snap_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with SNAP\n"; + +static int __init ipx_init(void) +{ + int rc = proto_register(&ipx_proto, 1); + + if (rc != 0) + goto out; + + sock_register(&ipx_family_ops); + + pEII_datalink = make_EII_client(); + if (pEII_datalink) + dev_add_pack(&ipx_dix_packet_type); + else + printk(ipx_EII_err_msg); + + p8023_datalink = make_8023_client(); + if (p8023_datalink) + dev_add_pack(&ipx_8023_packet_type); + else + printk(ipx_8023_err_msg); + + p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv); + if (!p8022_datalink) + printk(ipx_llc_err_msg); + + pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv); + if (!pSNAP_datalink) + printk(ipx_snap_err_msg); + + register_netdevice_notifier(&ipx_dev_notifier); + ipx_register_sysctl(); + ipx_proc_init(); +out: + return rc; +} + +static void __exit ipx_proto_finito(void) +{ + ipx_proc_exit(); + ipx_unregister_sysctl(); + + unregister_netdevice_notifier(&ipx_dev_notifier); + + ipxitf_cleanup(); + + if (pSNAP_datalink) { + unregister_snap_client(pSNAP_datalink); + pSNAP_datalink = NULL; + } + + if (p8022_datalink) { + unregister_8022_client(p8022_datalink); + p8022_datalink = NULL; + } + + dev_remove_pack(&ipx_8023_packet_type); + if (p8023_datalink) { + destroy_8023_client(p8023_datalink); + p8023_datalink = NULL; + } + + dev_remove_pack(&ipx_dix_packet_type); + if (pEII_datalink) { + destroy_EII_client(pEII_datalink); + pEII_datalink = NULL; + } + + proto_unregister(&ipx_proto); + sock_unregister(ipx_family_ops.family); +} + +module_init(ipx_init); +module_exit(ipx_proto_finito); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETPROTO(PF_IPX); diff --git a/drivers/staging/ipx/ipx_proc.c b/drivers/staging/ipx/ipx_proc.c new file mode 100644 index 000000000000..38a3d51d9ead --- /dev/null +++ b/drivers/staging/ipx/ipx_proc.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IPX proc routines + * + * Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002 + */ + +#include <linux/init.h> +#ifdef CONFIG_PROC_FS +#include <linux/proc_fs.h> +#include <linux/spinlock.h> +#include <linux/seq_file.h> +#include <linux/export.h> +#include <net/net_namespace.h> +#include <net/tcp_states.h> +#include <net/ipx.h> + +static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) +{ + spin_lock_bh(&ipx_interfaces_lock); + return seq_list_start_head(&ipx_interfaces, *pos); +} + +static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) +{ + return seq_list_next(v, &ipx_interfaces, pos); +} + +static void ipx_seq_interface_stop(struct seq_file *seq, void *v) +{ + spin_unlock_bh(&ipx_interfaces_lock); +} + +static int ipx_seq_interface_show(struct seq_file *seq, void *v) +{ + struct ipx_interface *i; + + if (v == &ipx_interfaces) { + seq_puts(seq, "Network Node_Address Primary Device " + "Frame_Type"); +#ifdef IPX_REFCNT_DEBUG + seq_puts(seq, " refcnt"); +#endif + seq_puts(seq, "\n"); + goto out; + } + + i = list_entry(v, struct ipx_interface, node); + seq_printf(seq, "%08X ", ntohl(i->if_netnum)); + seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", + i->if_node[0], i->if_node[1], i->if_node[2], + i->if_node[3], i->if_node[4], i->if_node[5]); + seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No"); + seq_printf(seq, "%-11s", ipx_device_name(i)); + seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type)); +#ifdef IPX_REFCNT_DEBUG + seq_printf(seq, "%6d", refcount_read(&i->refcnt)); +#endif + seq_puts(seq, "\n"); +out: + return 0; +} + +static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) +{ + read_lock_bh(&ipx_routes_lock); + return seq_list_start_head(&ipx_routes, *pos); +} + +static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) +{ + return seq_list_next(v, &ipx_routes, pos); +} + +static void ipx_seq_route_stop(struct seq_file *seq, void *v) +{ + read_unlock_bh(&ipx_routes_lock); +} + +static int ipx_seq_route_show(struct seq_file *seq, void *v) +{ + struct ipx_route *rt; + + if (v == &ipx_routes) { + seq_puts(seq, "Network Router_Net Router_Node\n"); + goto out; + } + + rt = list_entry(v, struct ipx_route, node); + + seq_printf(seq, "%08X ", ntohl(rt->ir_net)); + if (rt->ir_routed) + seq_printf(seq, "%08X %02X%02X%02X%02X%02X%02X\n", + ntohl(rt->ir_intrfc->if_netnum), + rt->ir_router_node[0], rt->ir_router_node[1], + rt->ir_router_node[2], rt->ir_router_node[3], + rt->ir_router_node[4], rt->ir_router_node[5]); + else + seq_puts(seq, "Directly Connected\n"); +out: + return 0; +} + +static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) +{ + struct sock *s = NULL; + struct ipx_interface *i; + + list_for_each_entry(i, &ipx_interfaces, node) { + spin_lock_bh(&i->if_sklist_lock); + sk_for_each(s, &i->if_sklist) { + if (!pos) + break; + --pos; + } + spin_unlock_bh(&i->if_sklist_lock); + if (!pos) { + if (s) + goto found; + break; + } + } + s = NULL; +found: + return s; +} + +static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos) +{ + loff_t l = *pos; + + spin_lock_bh(&ipx_interfaces_lock); + return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN; +} + +static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sock* sk, *next; + struct ipx_interface *i; + struct ipx_sock *ipxs; + + ++*pos; + if (v == SEQ_START_TOKEN) { + sk = NULL; + i = ipx_interfaces_head(); + if (!i) + goto out; + sk = sk_head(&i->if_sklist); + if (sk) + spin_lock_bh(&i->if_sklist_lock); + goto out; + } + sk = v; + next = sk_next(sk); + if (next) { + sk = next; + goto out; + } + ipxs = ipx_sk(sk); + i = ipxs->intrfc; + spin_unlock_bh(&i->if_sklist_lock); + sk = NULL; + for (;;) { + if (i->node.next == &ipx_interfaces) + break; + i = list_entry(i->node.next, struct ipx_interface, node); + spin_lock_bh(&i->if_sklist_lock); + if (!hlist_empty(&i->if_sklist)) { + sk = sk_head(&i->if_sklist); + break; + } + spin_unlock_bh(&i->if_sklist_lock); + } +out: + return sk; +} + +static int ipx_seq_socket_show(struct seq_file *seq, void *v) +{ + struct sock *s; + struct ipx_sock *ipxs; + + if (v == SEQ_START_TOKEN) { +#ifdef CONFIG_IPX_INTERN + seq_puts(seq, "Local_Address " + "Remote_Address Tx_Queue " + "Rx_Queue State Uid\n"); +#else + seq_puts(seq, "Local_Address Remote_Address " + "Tx_Queue Rx_Queue State Uid\n"); +#endif + goto out; + } + + s = v; + ipxs = ipx_sk(s); +#ifdef CONFIG_IPX_INTERN + seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X ", + ntohl(ipxs->intrfc->if_netnum), + ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3], + ipxs->node[4], ipxs->node[5], ntohs(ipxs->port)); +#else + seq_printf(seq, "%08X:%04X ", ntohl(ipxs->intrfc->if_netnum), + ntohs(ipxs->port)); +#endif /* CONFIG_IPX_INTERN */ + if (s->sk_state != TCP_ESTABLISHED) + seq_printf(seq, "%-28s", "Not_Connected"); + else { + seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X ", + ntohl(ipxs->dest_addr.net), + ipxs->dest_addr.node[0], ipxs->dest_addr.node[1], + ipxs->dest_addr.node[2], ipxs->dest_addr.node[3], + ipxs->dest_addr.node[4], ipxs->dest_addr.node[5], + ntohs(ipxs->dest_addr.sock)); + } + + seq_printf(seq, "%08X %08X %02X %03u\n", + sk_wmem_alloc_get(s), + sk_rmem_alloc_get(s), + s->sk_state, + from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); +out: + return 0; +} + +static const struct seq_operations ipx_seq_interface_ops = { + .start = ipx_seq_interface_start, + .next = ipx_seq_interface_next, + .stop = ipx_seq_interface_stop, + .show = ipx_seq_interface_show, +}; + +static const struct seq_operations ipx_seq_route_ops = { + .start = ipx_seq_route_start, + .next = ipx_seq_route_next, + .stop = ipx_seq_route_stop, + .show = ipx_seq_route_show, +}; + +static const struct seq_operations ipx_seq_socket_ops = { + .start = ipx_seq_socket_start, + .next = ipx_seq_socket_next, + .stop = ipx_seq_interface_stop, + .show = ipx_seq_socket_show, +}; + +static int ipx_seq_route_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ipx_seq_route_ops); +} + +static int ipx_seq_interface_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ipx_seq_interface_ops); +} + +static int ipx_seq_socket_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ipx_seq_socket_ops); +} + +static const struct file_operations ipx_seq_interface_fops = { + .owner = THIS_MODULE, + .open = ipx_seq_interface_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations ipx_seq_route_fops = { + .owner = THIS_MODULE, + .open = ipx_seq_route_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations ipx_seq_socket_fops = { + .owner = THIS_MODULE, + .open = ipx_seq_socket_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static struct proc_dir_entry *ipx_proc_dir; + +int __init ipx_proc_init(void) +{ + struct proc_dir_entry *p; + int rc = -ENOMEM; + + ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net); + + if (!ipx_proc_dir) + goto out; + p = proc_create("interface", S_IRUGO, + ipx_proc_dir, &ipx_seq_interface_fops); + if (!p) + goto out_interface; + + p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops); + if (!p) + goto out_route; + + p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops); + if (!p) + goto out_socket; + + rc = 0; +out: + return rc; +out_socket: + remove_proc_entry("route", ipx_proc_dir); +out_route: + remove_proc_entry("interface", ipx_proc_dir); +out_interface: + remove_proc_entry("ipx", init_net.proc_net); + goto out; +} + +void __exit ipx_proc_exit(void) +{ + remove_proc_entry("interface", ipx_proc_dir); + remove_proc_entry("route", ipx_proc_dir); + remove_proc_entry("socket", ipx_proc_dir); + remove_proc_entry("ipx", init_net.proc_net); +} + +#else /* CONFIG_PROC_FS */ + +int __init ipx_proc_init(void) +{ + return 0; +} + +void __exit ipx_proc_exit(void) +{ +} + +#endif /* CONFIG_PROC_FS */ diff --git a/drivers/staging/ipx/ipx_route.c b/drivers/staging/ipx/ipx_route.c new file mode 100644 index 000000000000..3cf93aa9f284 --- /dev/null +++ b/drivers/staging/ipx/ipx_route.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implements the IPX routing routines. + * Code moved from af_ipx.c. + * + * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2003 + * + * See net/ipx/ChangeLog. + */ + +#include <linux/list.h> +#include <linux/route.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include <net/ipx.h> +#include <net/sock.h> + +LIST_HEAD(ipx_routes); +DEFINE_RWLOCK(ipx_routes_lock); + +extern struct ipx_interface *ipx_internal_net; + +extern struct ipx_interface *ipxitf_find_using_net(__be32 net); +extern int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy); +extern int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy); + +struct ipx_route *ipxrtr_lookup(__be32 net) +{ + struct ipx_route *r; + + read_lock_bh(&ipx_routes_lock); + list_for_each_entry(r, &ipx_routes, node) + if (r->ir_net == net) { + ipxrtr_hold(r); + goto unlock; + } + r = NULL; +unlock: + read_unlock_bh(&ipx_routes_lock); + return r; +} + +/* + * Caller must hold a reference to intrfc + */ +int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, + unsigned char *node) +{ + struct ipx_route *rt; + int rc; + + /* Get a route structure; either existing or create */ + rt = ipxrtr_lookup(network); + if (!rt) { + rt = kmalloc(sizeof(*rt), GFP_ATOMIC); + rc = -EAGAIN; + if (!rt) + goto out; + + refcount_set(&rt->refcnt, 1); + ipxrtr_hold(rt); + write_lock_bh(&ipx_routes_lock); + list_add(&rt->node, &ipx_routes); + write_unlock_bh(&ipx_routes_lock); + } else { + rc = -EEXIST; + if (intrfc == ipx_internal_net) + goto out_put; + } + + rt->ir_net = network; + rt->ir_intrfc = intrfc; + if (!node) { + memset(rt->ir_router_node, '\0', IPX_NODE_LEN); + rt->ir_routed = 0; + } else { + memcpy(rt->ir_router_node, node, IPX_NODE_LEN); + rt->ir_routed = 1; + } + + rc = 0; +out_put: + ipxrtr_put(rt); +out: + return rc; +} + +void ipxrtr_del_routes(struct ipx_interface *intrfc) +{ + struct ipx_route *r, *tmp; + + write_lock_bh(&ipx_routes_lock); + list_for_each_entry_safe(r, tmp, &ipx_routes, node) + if (r->ir_intrfc == intrfc) { + list_del(&r->node); + ipxrtr_put(r); + } + write_unlock_bh(&ipx_routes_lock); +} + +static int ipxrtr_create(struct ipx_route_definition *rd) +{ + struct ipx_interface *intrfc; + int rc = -ENETUNREACH; + + /* Find the appropriate interface */ + intrfc = ipxitf_find_using_net(rd->ipx_router_network); + if (!intrfc) + goto out; + rc = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node); + ipxitf_put(intrfc); +out: + return rc; +} + +static int ipxrtr_delete(__be32 net) +{ + struct ipx_route *r, *tmp; + int rc; + + write_lock_bh(&ipx_routes_lock); + list_for_each_entry_safe(r, tmp, &ipx_routes, node) + if (r->ir_net == net) { + /* Directly connected; can't lose route */ + rc = -EPERM; + if (!r->ir_routed) + goto out; + list_del(&r->node); + ipxrtr_put(r); + rc = 0; + goto out; + } + rc = -ENOENT; +out: + write_unlock_bh(&ipx_routes_lock); + return rc; +} + +/* + * The skb has to be unshared, we'll end up calling ipxitf_send, that'll + * modify the packet + */ +int ipxrtr_route_skb(struct sk_buff *skb) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + struct ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net); + + if (!r) { /* no known route */ + kfree_skb(skb); + return 0; + } + + ipxitf_hold(r->ir_intrfc); + ipxitf_send(r->ir_intrfc, skb, r->ir_routed ? + r->ir_router_node : ipx->ipx_dest.node); + ipxitf_put(r->ir_intrfc); + ipxrtr_put(r); + + return 0; +} + +/* + * Route an outgoing frame from a socket. + */ +int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, + struct msghdr *msg, size_t len, int noblock) +{ + struct sk_buff *skb; + struct ipx_sock *ipxs = ipx_sk(sk); + struct ipx_interface *intrfc; + struct ipxhdr *ipx; + size_t size; + int ipx_offset; + struct ipx_route *rt = NULL; + int rc; + + /* Find the appropriate interface on which to send packet */ + if (!usipx->sipx_network && ipx_primary_net) { + usipx->sipx_network = ipx_primary_net->if_netnum; + intrfc = ipx_primary_net; + } else { + rt = ipxrtr_lookup(usipx->sipx_network); + rc = -ENETUNREACH; + if (!rt) + goto out; + intrfc = rt->ir_intrfc; + } + + ipxitf_hold(intrfc); + ipx_offset = intrfc->if_ipx_offset; + size = sizeof(struct ipxhdr) + len + ipx_offset; + + skb = sock_alloc_send_skb(sk, size, noblock, &rc); + if (!skb) + goto out_put; + + skb_reserve(skb, ipx_offset); + skb->sk = sk; + + /* Fill in IPX header */ + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + skb_put(skb, sizeof(struct ipxhdr)); + ipx = ipx_hdr(skb); + ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr)); + IPX_SKB_CB(skb)->ipx_tctrl = 0; + ipx->ipx_type = usipx->sipx_type; + + IPX_SKB_CB(skb)->last_hop.index = -1; +#ifdef CONFIG_IPX_INTERN + IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum; + memcpy(ipx->ipx_source.node, ipxs->node, IPX_NODE_LEN); +#else + rc = ntohs(ipxs->port); + if (rc == 0x453 || rc == 0x452) { + /* RIP/SAP special handling for mars_nwe */ + IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; + memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN); + } else { + IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum; + memcpy(ipx->ipx_source.node, ipxs->intrfc->if_node, + IPX_NODE_LEN); + } +#endif /* CONFIG_IPX_INTERN */ + ipx->ipx_source.sock = ipxs->port; + IPX_SKB_CB(skb)->ipx_dest_net = usipx->sipx_network; + memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN); + ipx->ipx_dest.sock = usipx->sipx_port; + + rc = memcpy_from_msg(skb_put(skb, len), msg, len); + if (rc) { + kfree_skb(skb); + goto out_put; + } + + /* Apply checksum. Not allowed on 802.3 links. */ + if (sk->sk_no_check_tx || + intrfc->if_dlink_type == htons(IPX_FRAME_8023)) + ipx->ipx_checksum = htons(0xFFFF); + else + ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr)); + + rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ? + rt->ir_router_node : ipx->ipx_dest.node); +out_put: + ipxitf_put(intrfc); + if (rt) + ipxrtr_put(rt); +out: + return rc; +} + +/* + * We use a normal struct rtentry for route handling + */ +int ipxrtr_ioctl(unsigned int cmd, void __user *arg) +{ + struct rtentry rt; /* Use these to behave like 'other' stacks */ + struct sockaddr_ipx *sg, *st; + int rc = -EFAULT; + + if (copy_from_user(&rt, arg, sizeof(rt))) + goto out; + + sg = (struct sockaddr_ipx *)&rt.rt_gateway; + st = (struct sockaddr_ipx *)&rt.rt_dst; + + rc = -EINVAL; + if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */ + sg->sipx_family != AF_IPX || + st->sipx_family != AF_IPX) + goto out; + + switch (cmd) { + case SIOCDELRT: + rc = ipxrtr_delete(st->sipx_network); + break; + case SIOCADDRT: { + struct ipx_route_definition f; + f.ipx_network = st->sipx_network; + f.ipx_router_network = sg->sipx_network; + memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN); + rc = ipxrtr_create(&f); + break; + } + } + +out: + return rc; +} diff --git a/drivers/staging/ipx/pe2.c b/drivers/staging/ipx/pe2.c new file mode 100644 index 000000000000..ba7d4214bbff --- /dev/null +++ b/drivers/staging/ipx/pe2.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/in.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/slab.h> + +#include <net/datalink.h> + +static int pEII_request(struct datalink_proto *dl, + struct sk_buff *skb, unsigned char *dest_node) +{ + struct net_device *dev = skb->dev; + + skb->protocol = htons(ETH_P_IPX); + dev_hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len); + return dev_queue_xmit(skb); +} + +struct datalink_proto *make_EII_client(void) +{ + struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC); + + if (proto) { + proto->header_length = 0; + proto->request = pEII_request; + } + + return proto; +} + +void destroy_EII_client(struct datalink_proto *dl) +{ + kfree(dl); +} diff --git a/drivers/staging/ipx/sysctl_net_ipx.c b/drivers/staging/ipx/sysctl_net_ipx.c new file mode 100644 index 000000000000..c3eef457db88 --- /dev/null +++ b/drivers/staging/ipx/sysctl_net_ipx.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -*- linux-c -*- + * sysctl_net_ipx.c: sysctl interface to net IPX subsystem. + * + * Begun April 1, 1996, Mike Shaver. + * Added /proc/sys/net/ipx directory entry (empty =) ). [MS] + * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001 + */ + +#include <linux/mm.h> +#include <linux/sysctl.h> +#include <net/net_namespace.h> +#include <net/ipx.h> + +#ifndef CONFIG_SYSCTL +#error This file should not be compiled without CONFIG_SYSCTL defined +#endif + +static struct ctl_table ipx_table[] = { + { + .procname = "ipx_pprop_broadcasting", + .data = &sysctl_ipx_pprop_broadcasting, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { }, +}; + +static struct ctl_table_header *ipx_table_header; + +void ipx_register_sysctl(void) +{ + ipx_table_header = register_net_sysctl(&init_net, "net/ipx", ipx_table); +} + +void ipx_unregister_sysctl(void) +{ + unregister_net_sysctl_table(ipx_table_header); +} diff --git a/drivers/staging/irda/net/irlmp.c b/drivers/staging/irda/net/irlmp.c index 34355061ab0b..7af618fb66c0 100644 --- a/drivers/staging/irda/net/irlmp.c +++ b/drivers/staging/irda/net/irlmp.c @@ -1668,7 +1668,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel) IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto errlsap;); - if ((self->slsap_sel == slsap_sel)) { + if (self->slsap_sel == slsap_sel) { pr_debug("Source LSAP selector=%02x in use\n", self->slsap_sel); goto errlsap; @@ -1693,7 +1693,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel) self = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps); while (self != NULL) { IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;); - if ((self->slsap_sel == slsap_sel)) { + if (self->slsap_sel == slsap_sel) { pr_debug("Source LSAP selector=%02x in use (unconnected)\n", self->slsap_sel); goto erruncon; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 7cb61e2e7d3b..7cbc6a06afec 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -886,17 +886,15 @@ static void search_granted_lock(struct list_head *queue, struct ldlm_lock *req, struct sl_insert_point *prev) { - struct list_head *tmp; struct ldlm_lock *lock, *mode_end, *policy_end; - list_for_each(tmp, queue) { - lock = list_entry(tmp, struct ldlm_lock, l_res_link); + list_for_each_entry(lock, queue, l_res_link) { mode_end = list_prev_entry(lock, l_sl_mode); if (lock->l_req_mode != req->l_req_mode) { /* jump to last lock of mode group */ - tmp = &mode_end->l_res_link; + lock = mode_end; continue; } @@ -933,9 +931,7 @@ static void search_granted_lock(struct list_head *queue, break; /* go to next policy group within mode group */ - tmp = policy_end->l_res_link.next; - lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + lock = list_next_entry(policy_end, l_res_link); } /* loop over policy groups within the mode group */ /* insert point is last lock of the mode group, @@ -1687,7 +1683,7 @@ ldlm_work_bl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - lock = list_entry(arg->list->next, struct ldlm_lock, l_bl_ast); + lock = list_first_entry(arg->list, struct ldlm_lock, l_bl_ast); /* nobody should touch l_bl_ast */ lock_res_and_lock(lock); @@ -1723,7 +1719,7 @@ ldlm_work_cp_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - lock = list_entry(arg->list->next, struct ldlm_lock, l_cp_ast); + lock = list_first_entry(arg->list, struct ldlm_lock, l_cp_ast); /* It's possible to receive a completion AST before we've set * the l_completion_ast pointer: either because the AST arrived @@ -1769,7 +1765,7 @@ ldlm_work_revoke_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - lock = list_entry(arg->list->next, struct ldlm_lock, l_rk_ast); + lock = list_first_entry(arg->list, struct ldlm_lock, l_rk_ast); list_del_init(&lock->l_rk_ast); /* the desc just pretend to exclusive */ @@ -1796,7 +1792,7 @@ static int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - gl_work = list_entry(arg->list->next, struct ldlm_glimpse_work, + gl_work = list_first_entry(arg->list, struct ldlm_glimpse_work, gl_list); list_del_init(&gl_work->gl_list); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 2d5a2c932ddc..ada50b69c5f6 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -1093,8 +1093,10 @@ static int ldlm_cleanup(void) kset_unregister(ldlm_ns_kset); if (ldlm_svc_kset) kset_unregister(ldlm_svc_kset); - if (ldlm_kobj) + if (ldlm_kobj) { + sysfs_remove_group(ldlm_kobj, &ldlm_attr_group); kobject_put(ldlm_kobj); + } ldlm_debugfs_cleanup(); diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 3bdf48e4edb4..cfa1d7f92b0f 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -49,15 +49,13 @@ static void lov_init_set(struct lov_request_set *set) static void lov_finish_set(struct lov_request_set *set) { - struct list_head *pos, *n; + struct lov_request *req; LASSERT(set); - list_for_each_safe(pos, n, &set->set_list) { - struct lov_request *req = list_entry(pos, - struct lov_request, - rq_link); + while ((req = list_first_entry_or_null(&set->set_list, + struct lov_request, + rq_link)) != NULL) { list_del_init(&req->rq_link); - kfree(req->rq_oi.oi_osfs); kfree(req); } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index d415f8396038..3b683b774fef 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -79,13 +79,12 @@ EXPORT_SYMBOL(cl_lock_slice_add); void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock) { + struct cl_lock_slice *slice; cl_lock_trace(D_DLMTRACE, env, "destroy lock", lock); - while (!list_empty(&lock->cll_layers)) { - struct cl_lock_slice *slice; - - slice = list_entry(lock->cll_layers.next, - struct cl_lock_slice, cls_linkage); + while ((slice = list_first_entry_or_null(&lock->cll_layers, + struct cl_lock_slice, + cls_linkage)) != NULL) { list_del_init(lock->cll_layers.next); slice->cls_ops->clo_fini(env, slice); } diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 2985bca4dc4c..3e24b76f6301 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -377,7 +377,8 @@ static int obd_init_checks(void) char buf[64]; int len, ret = 0; - CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld", "%#llx"); + CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld", + "%#llx"); CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF); diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index fc59f29a4290..57951237def2 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -501,6 +501,7 @@ int class_procfs_init(void) rc = debugfs_lustre_root ? PTR_ERR(debugfs_lustre_root) : -ENOMEM; debugfs_lustre_root = NULL; + sysfs_remove_group(lustre_kobj, &lustre_attr_group); kobject_put(lustre_kobj); goto out; } @@ -509,6 +510,7 @@ int class_procfs_init(void) &obd_device_list_fops); if (IS_ERR_OR_NULL(file)) { rc = file ? PTR_ERR(file) : -ENOMEM; + sysfs_remove_group(lustre_kobj, &lustre_attr_group); kobject_put(lustre_kobj); goto out; } @@ -522,6 +524,7 @@ int class_procfs_clean(void) debugfs_lustre_root = NULL; + sysfs_remove_group(lustre_kobj, &lustre_attr_group); kobject_put(lustre_kobj); return 0; diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index bb1d6dafca83..26994b429cf2 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -207,13 +207,9 @@ static irqreturn_t csi_idmac_eof_interrupt(int irq, void *dev_id) goto unlock; } - if (priv->fim) { - struct timespec cur_ts; - - ktime_get_ts(&cur_ts); + if (priv->fim) /* call frame interval monitor */ - imx_media_fim_eof_monitor(priv->fim, &cur_ts); - } + imx_media_fim_eof_monitor(priv->fim, ktime_get()); csi_vb2_buf_done(priv); diff --git a/drivers/staging/media/imx/imx-media-fim.c b/drivers/staging/media/imx/imx-media-fim.c index 47275ef803f3..6df189135db8 100644 --- a/drivers/staging/media/imx/imx-media-fim.c +++ b/drivers/staging/media/imx/imx-media-fim.c @@ -66,7 +66,7 @@ struct imx_media_fim { int icap_flags; int counter; - struct timespec last_ts; + ktime_t last_ts; unsigned long sum; /* usec */ unsigned long nominal; /* usec */ @@ -147,22 +147,26 @@ static void send_fim_event(struct imx_media_fim *fim, unsigned long error) * (presumably random) interrupt latency. */ static void frame_interval_monitor(struct imx_media_fim *fim, - struct timespec *ts) + ktime_t timestamp) { - unsigned long interval, error, error_avg; + long long interval, error; + unsigned long error_avg; bool send_event = false; - struct timespec diff; if (!fim->enabled || ++fim->counter <= 0) goto out_update_ts; - diff = timespec_sub(*ts, fim->last_ts); - interval = diff.tv_sec * 1000 * 1000 + diff.tv_nsec / 1000; - error = abs(interval - fim->nominal); + /* max error is less than l00µs, so use 32-bit division or fail */ + interval = ktime_to_ns(ktime_sub(timestamp, fim->last_ts)); + error = abs(interval - NSEC_PER_USEC * (u64)fim->nominal); + if (error > U32_MAX) + error = U32_MAX; + else + error = abs((u32)error / NSEC_PER_USEC); if (fim->tolerance_max && error >= fim->tolerance_max) { dev_dbg(fim->sd->dev, - "FIM: %lu ignored, out of tolerance bounds\n", + "FIM: %llu ignored, out of tolerance bounds\n", error); fim->counter--; goto out_update_ts; @@ -184,7 +188,7 @@ static void frame_interval_monitor(struct imx_media_fim *fim, } out_update_ts: - fim->last_ts = *ts; + fim->last_ts = timestamp; if (send_event) send_fim_event(fim, error_avg); } @@ -195,14 +199,14 @@ out_update_ts: * to interrupt latency. */ static void fim_input_capture_handler(int channel, void *dev_id, - struct timespec *ts) + ktime_t timestamp) { struct imx_media_fim *fim = dev_id; unsigned long flags; spin_lock_irqsave(&fim->lock, flags); - frame_interval_monitor(fim, ts); + frame_interval_monitor(fim, timestamp); if (!completion_done(&fim->icap_first_event)) complete(&fim->icap_first_event); @@ -405,14 +409,14 @@ err_free: * the frame_interval_monitor() is called by the input capture event * callback handler in that case. */ -void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts) +void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp) { unsigned long flags; spin_lock_irqsave(&fim->lock, flags); if (!icap_enabled(fim)) - frame_interval_monitor(fim, ts); + frame_interval_monitor(fim, timestamp); spin_unlock_irqrestore(&fim->lock, flags); } diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index d409170632bd..ac3ab115394f 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -280,7 +280,7 @@ int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd, /* imx-media-fim.c */ struct imx_media_fim; -void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts); +void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp); int imx_media_fim_set_stream(struct imx_media_fim *fim, const struct v4l2_fract *frame_interval, bool on); diff --git a/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt new file mode 100644 index 000000000000..d8fa841e3742 --- /dev/null +++ b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt @@ -0,0 +1,313 @@ +What: /sys/bus/most/devices/.../description +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Provides information about the interface type and the physical + location of the device. Hardware attached via USB, for instance, + might return <usb_device 1-1.1:1.0> +Users: + +What: /sys/bus/most/devices/.../interface +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the type of peripheral interface the device uses. +Users: + +What: /sys/bus/most/devices/.../dci +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + If the network interface controller is attached via USB, a dci + directory is created that allows applications to read and + write the controller's DCI registers. +Users: + +What: /sys/bus/most/devices/.../dci/arb_address +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to set an arbitrary DCI register address an + application wants to read from or write to. +Users: + +What: /sys/bus/most/devices/.../dci/arb_value +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to read and write the DCI register whose address + is stored in arb_address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_eui48_hi +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_eui48_lo +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_eui48_mi +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_filter +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP filter address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash0 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash1 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash2 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash3 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/ni_state +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the current network interface state. +Users: + +What: /sys/bus/most/devices/.../dci/node_address +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the current node address. +Users: + +What: /sys/bus/most/devices/.../dci/node_position +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the current node position. +Users: + +What: /sys/bus/most/devices/.../dci/packet_bandwidth +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the configured packet bandwidth. +Users: + +What: /sys/bus/most/devices/.../dci/sync_ep +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Triggers the controller's synchronization process for a certain + endpoint. +Users: + +What: /sys/bus/most/devices/.../<channel>/ +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + For every channel of the device a directory is created, whose + name is dictated by the HDM. This enables an application to + collect information about the channel's capabilities and + configure it. +Users: + +What: /sys/bus/most/devices/.../<channel>/available_datatypes +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the data types the current channel can transport. +Users: + +What: /sys/bus/most/devices/.../<channel>/available_directions +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the directions the current channel is capable of. +Users: + +What: /sys/bus/most/devices/.../<channel>/number_of_packet_buffers +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the number of packet buffers the current channel can + handle. +Users: + +What: /sys/bus/most/devices/.../<channel>/number_of_stream_buffers +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the number of streaming buffers the current channel can + handle. +Users: + +What: /sys/bus/most/devices/.../<channel>/size_of_packet_buffer +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the size of a packet buffer the current channel can + handle. +Users: + +What: /sys/bus/most/devices/.../<channel>/size_of_stream_buffer +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the size of a streaming buffer the current channel can + handle. +Users: + +What: /sys/bus/most/devices/.../<channel>/set_number_of_buffers +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the number of buffers of the current channel. +Users: + +What: /sys/bus/most/devices/.../<channel>/set_buffer_size +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the size of a buffer of the current channel. +Users: + +What: /sys/bus/most/devices/.../<channel>/set_direction +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the direction of the current channel. + The following strings will be accepted: + 'dir_tx', + 'dir_rx' +Users: + +What: /sys/bus/most/devices/.../<channel>/set_datatype +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the data type of the current channel. + The following strings will be accepted: + 'control', + 'async', + 'sync', + 'isoc_avp' +Users: + +What: /sys/bus/most/devices/.../<channel>/set_subbuffer_size +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the subbuffer size of the current channel. +Users: + +What: /sys/bus/most/devices/.../<channel>/set_packets_per_xact +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the number of packets per transaction of + the current channel. This is only needed network interface + controller is attached via USB. +Users: + +What: /sys/bus/most/devices/.../<channel>/channel_starving +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates whether current channel ran out of buffers. +Users: + +What: /sys/bus/most/drivers/mostcore/add_link +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to link a channel to a component of the + mostcore. A link created by writing to this file is + referred to as pipe. +Users: + +What: /sys/bus/most/drivers/mostcore/remove_link +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to unlink a channel from a component. +Users: + +What: /sys/bus/most/drivers/mostcore/components +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to retrieve a list of registered components. +Users: + +What: /sys/bus/most/drivers/mostcore/links +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to retrieve a list of established links. +Users: diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt index a4dc0c348fbc..bb9b4e870199 100644 --- a/drivers/staging/most/Documentation/driver_usage.txt +++ b/drivers/staging/most/Documentation/driver_usage.txt @@ -23,20 +23,29 @@ audio/video streaming. Therefore, the driver perfectly fits to the mission of Automotive Grade Linux to create open source software solutions for automotive applications. -The driver consists basically of three layers. The hardware layer, the -core layer and the application layer. The core layer consists of the core -module only. This module handles the communication flow through all three -layers, the configuration of the driver, the configuration interface -representation in sysfs, and the buffer management. -For each of the other two layers a selection of modules is provided. These -modules can arbitrarily be combined to meet the needs of the desired -system architecture. A module of the hardware layer is referred to as an -HDM (hardware dependent module). Each module of this layer handles exactly -one of the peripheral interfaces of a network interface controller (e.g. -USB, MediaLB, I2C). A module of the application layer is referred to as an -AIM (application interfacing module). The modules of this layer give access -to MOST via one the following ways: character devices, ALSA, Networking or -V4L2. +The MOST driver uses module stacking to divide the associated modules into +three layers. From bottom up these layers are: the adapter layer, the core +layer and the application layer. The core layer implements the MOST +subsystem and consists basically of the module core.c and its API. It +registers the MOST bus with the kernel's device model, handles the data +routing through all three layers, the configuration of the driver, the +representation of the configuration interface in sysfs and the buffer +management. + +For each of the other two layers a set of modules is provided. Those can be +arbitrarily combined with the core to meet the connectivity of the desired +system architecture. + +A module of the adapter layer is basically a device driver for a different +subsystem. It is registered with the core to connect the MOST subsystem to +the attached network interface controller hardware. Hence, a given module +of this layer is designed to handle exactly one of the peripheral +interfaces (e.g. USB, MediaLB, I2C) the hardware provides. + +A module of the application layer is referred to as a core comoponent, +which kind of extends the core by providing connectivity to the user space. +Applications, then, can access a MOST network via character devices, an +ALSA soundcard, a Network adapter or a V4L2 capture device. To physically access MOST, an Intelligent Network Interface Controller (INIC) is needed. For more information on available controllers visit: @@ -44,15 +53,14 @@ www.microchip.com - Section 1.1 Hardware Layer + Section 1.1 Adapter Layer -The hardware layer contains so called hardware dependent modules (HDM). For each -peripheral interface the hardware supports the driver has a suitable module -that handles the interface. - -The HDMs encapsulate the peripheral interface specific knowledge of the driver -and provides an easy way of extending the number of supported interfaces. -Currently the following HDMs are available: +The adapter layer contains a pool of device drivers. For each peripheral +interface the hardware supports there is one suitable module that handles +the interface. Adapter drivers encapsulate the peripheral interface +specific knowledge of the MOST driver stack and provide an easy way of +extending the number of supported interfaces. Currently the following +interfaces are available: 1) MediaLB (DIM2) Host wants to communicate with hardware via MediaLB. @@ -63,26 +71,34 @@ Currently the following HDMs are available: 3) USB Host wants to communicate with the hardware via USB. +Once an adapter driver recognizes a MOST device being attached, it +registers it with the core, which, in turn, assigns the necessary members +of the embedded struct device (e.g. the bus this device belongs to and +attribute groups) and registers it with the kernel's device model. - Section 1.2 Core Layer - -The core layer contains the mostcore module only, which processes the driver -configuration via sysfs, buffer management and data forwarding. + Section 1.2 Core Layer +This layer implements the MOST subsystem. It contains the core module and +the header file most.h that exposes the API of the core. When inserted in +the kernel, it registers the MOST bus_type with the kernel's device model +and registers itself as a device driver for this bus. Besides these meta +tasks the core populates the configuration directory for a registered MOST +device (represented by struct most_interface) in sysfs and processes the +configuration of the device's interface. The core layer also handles the +buffer management and the data/message routing. - Section 1.2 Application Layer -The application layer contains so called application interfacing modules (AIM). -Depending on how the driver should interface to the application, one or more -suitable modules can be selected. + Section 1.3 Application Layer -The AIMs encapsulate the application interface specific knowledge of the driver -and provides access to user space or other kernel subsystems. -Currently the following AIMs are available +This layer contains a pool of device drivers that are components of the +core designed to make up the userspace experience of the MOST driver stack. +Depending on how an application is meant to interface the driver, one or +more modules of this pool can be registered with the core. Currently the +following components are available 1) Character Device - Applications can access the driver by means of character devices. + Userspace can access the driver by means of character devices. 2) Networking Standard networking applications (e.g. iperf) can by used to access @@ -97,84 +113,86 @@ Currently the following AIMs are available used to access the driver via the ALSA subsystem. + Section 2 Usage of the MOST Driver - Section 2 Configuration + Section 2.1 Configuration -See ABI/sysfs-class-most.txt +See ABI/sysfs-bus-most.txt + Section 2.2 Routing Channels - Section 3 USB Padding +To connect a configured channel to a certain core component and make it +accessible for user space applications, the driver attribute 'add_link' is +used. The configuration string passed to it has the following format: -When transceiving synchronous or isochronous data, the number of packets per USB -transaction and the sub-buffer size need to be configured. These values -are needed for the driver to process buffer padding, as expected by hardware, -which is for performance optimization purposes of the USB transmission. + "device_name:channel_name:component_name:link_name[.param]" -When transmitting synchronous data the allocated channel width needs to be -written to 'set_subbuffer_size'. Additionally, the number of MOST frames that -should travel to the host within one USB transaction need to be written to -'packets_per_xact'. +It is the concatenation of up to four substrings separated by a colon. The +substrings contain the names of the MOST interface, the channel, the +component driver and a custom name with which the link is going to be +referenced with. Since some components need additional information, the +link name can be extended with a component-specific parameter (separated by +a dot). In case the character device component is loaded, the handle would +also appear as a device node in the /dev directory. -Internally the synchronous threshold is calculated as follows: +Cdev component example: + $ echo "mdev0:ep_81:cdev:my_rx_channel" >$(DRV_DIR)/add_link - frame_size = set_subbuffer_size * packets_per_xact -In case 'packets_per_xact' is set to 0xFF the maximum number of packets, -allocated within one MOST frame, is calculated that fit into _one_ 512 byte -USB full packet. +Sound component example: - frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync +The sound component needs an additional parameter to determine the audio +resolution that is going to be used. The following formats are available: -This frame_size is the number of synchronous data within an USB transaction, -which renders MTU_USB - frame_size bytes for padding. + - "1x8" (Mono) + - "2x16" (16-bit stereo) + - "2x24" (24-bit stereo) + - "2x32" (32-bit stereo) + - "6x16" (16-bit surround 5.1) -When transmitting isochronous AVP data the desired packet size needs to be -written to 'set_subbuffer_size' and hardware will always expect two isochronous -packets within one USB transaction. This renders + $ echo "mdev0:ep_81:sound:most51_playback.6x16" >$(DRV_DIR)/add_link - MTU_USB - (2 * set_subbuffer_size) -bytes for padding. - -Note that at least 2 times set_subbuffer_size bytes for isochronous data or -set_subbuffer_size times packts_per_xact bytes for synchronous data need to be -put in the transmission buffer and passed to the driver. -Since HDMs are allowed to change a chosen configuration to best fit its -constraints, it is recommended to always double check the configuration and read -back the previously written files. + Section 2.3 USB Padding +When transceiving synchronous or isochronous data, the number of packets +per USB transaction and the sub-buffer size need to be configured. These +values are needed for the driver to process buffer padding, as expected by +hardware, which is for performance optimization purposes of the USB +transmission. +When transmitting synchronous data the allocated channel width needs to be +written to 'set_subbuffer_size'. Additionally, the number of MOST frames +that should travel to the host within one USB transaction need to be +written to 'packets_per_xact'. - Section 4 Routing Channels +The driver, then, calculates the synchronous threshold as follows: -To connect a channel that has been configured as outlined above to an AIM and -make it accessible to user space applications, the attribute file 'add_link' is -used. To actually bind a channel to the AIM a string needs to be written to the -file that complies with the following syntax: + frame_size = set_subbuffer_size * packets_per_xact - "most_device:channel_name:link_name[.param]" +In case 'packets_per_xact' is set to 0xFF the maximum number of packets, +allocated within one MOST frame, is calculated that fit into _one_ 512 byte +USB full packet. -The example above links the channel "channel_name" of the device "most_device" -to the AIM. In case the AIM interfaces the VFS this would also create a device -node "link_name" in the /dev directory. The parameter "param" is an AIM dependent -string, which can be omitted in case the used AIM does not make any use of it. + frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync -Cdev AIM example: - $ echo "mdev0:ep_81:my_rx_channel" >add_link - $ echo "mdev0:ep_81" >add_link +This frame_size is the number of synchronous data within an USB +transaction, which renders MTU_USB - frame_size bytes for padding. +When transmitting isochronous AVP data the desired packet size needs to be +written to 'set_subbuffer_size' and hardware will always expect two +isochronous packets within one USB transaction. This renders -Sound/ALSA AIM example: + MTU_USB - (2 * set_subbuffer_size) -The sound/ALSA AIM needs an additional parameter to determine the audio resolution -that is going to be used. The following strings can be used: +bytes for padding. - - "1x8" (Mono) - - "2x16" (16-bit stereo) - - "2x24" (24-bit stereo) - - "2x32" (32-bit stereo) +Note that at least (2 * set_subbuffer_size) bytes for isochronous data or +(set_subbuffer_size * packts_per_xact) bytes for synchronous data need to +be put in the transmission buffer and passed to the driver. - $ echo "mdev0:ep_81:audio_rx.2x16" >add_link - $ echo "mdev0:ep_81" >add_link +Since adapter drivers are allowed to change a chosen configuration to best +fit its constraints, it is recommended to always double check the +configuration and read back the previously written files. diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 0b9b9b539f70..20047abbe560 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -1,10 +1,15 @@ menuconfig MOST - tristate "MOST driver" + tristate "MOST support" depends on HAS_DMA - select MOSTCORE default n ---help--- - This option allows you to enable support for MOST Network transceivers. + Say Y here if you want to enable MOST support. + This driver needs at least one additional component to enable the + desired access from userspace (e.g. character devices) and one that + matches the network controller's hardware interface (e.g. USB). + + To compile this driver as a module, choose M here: the + module will be called most_core. If in doubt, say N here. @@ -12,20 +17,18 @@ menuconfig MOST if MOST -source "drivers/staging/most/mostcore/Kconfig" - -source "drivers/staging/most/aim-cdev/Kconfig" +source "drivers/staging/most/cdev/Kconfig" -source "drivers/staging/most/aim-network/Kconfig" +source "drivers/staging/most/net/Kconfig" -source "drivers/staging/most/aim-sound/Kconfig" +source "drivers/staging/most/sound/Kconfig" -source "drivers/staging/most/aim-v4l2/Kconfig" +source "drivers/staging/most/video/Kconfig" -source "drivers/staging/most/hdm-dim2/Kconfig" +source "drivers/staging/most/dim2/Kconfig" -source "drivers/staging/most/hdm-i2c/Kconfig" +source "drivers/staging/most/i2c/Kconfig" -source "drivers/staging/most/hdm-usb/Kconfig" +source "drivers/staging/most/usb/Kconfig" endif diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index f5bbb9deaab5..f8bcf488ecf2 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -1,9 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_MOSTCORE) += mostcore/ -obj-$(CONFIG_AIM_CDEV) += aim-cdev/ -obj-$(CONFIG_AIM_NETWORK) += aim-network/ -obj-$(CONFIG_AIM_SOUND) += aim-sound/ -obj-$(CONFIG_AIM_V4L2) += aim-v4l2/ -obj-$(CONFIG_HDM_DIM2) += hdm-dim2/ -obj-$(CONFIG_HDM_I2C) += hdm-i2c/ -obj-$(CONFIG_HDM_USB) += hdm-usb/ +obj-$(CONFIG_MOST) += most_core.o +most_core-y := core.o +ccflags-y += -Idrivers/staging/ + +obj-$(CONFIG_MOST_CDEV) += cdev/ +obj-$(CONFIG_MOST_NET) += net/ +obj-$(CONFIG_MOST_SOUND) += sound/ +obj-$(CONFIG_MOST_VIDEO) += video/ +obj-$(CONFIG_MOST_DIM2) += dim2/ +obj-$(CONFIG_MOST_I2C) += i2c/ +obj-$(CONFIG_MOST_USB) += usb/ diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile deleted file mode 100644 index 0bcc6c637b75..000000000000 --- a/drivers/staging/most/aim-cdev/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AIM_CDEV) += aim_cdev.o - -aim_cdev-objs := cdev.o -ccflags-y += -Idrivers/staging/most/mostcore/
\ No newline at end of file diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile deleted file mode 100644 index 840c1dd94873..000000000000 --- a/drivers/staging/most/aim-network/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AIM_NETWORK) += aim_network.o - -aim_network-objs := networking.o -ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile deleted file mode 100644 index beba9586fd28..000000000000 --- a/drivers/staging/most/aim-sound/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AIM_SOUND) += aim_sound.o - -aim_sound-objs := sound.o -ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile deleted file mode 100644 index 69a7524b466c..000000000000 --- a/drivers/staging/most/aim-v4l2/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o - -aim_v4l2-objs := video.o - -ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/cdev/Kconfig index 3c59f1bac127..2b04e26bcbea 100644 --- a/drivers/staging/most/aim-cdev/Kconfig +++ b/drivers/staging/most/cdev/Kconfig @@ -2,11 +2,11 @@ # MOST Cdev configuration # -config AIM_CDEV - tristate "Cdev AIM" +config MOST_CDEV + tristate "Cdev" ---help--- Say Y here if you want to commumicate via character devices. To compile this driver as a module, choose M here: the - module will be called aim_cdev.
\ No newline at end of file + module will be called most_cdev. diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile new file mode 100644 index 000000000000..afb9870eb50f --- /dev/null +++ b/drivers/staging/most/cdev/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_CDEV) += most_cdev.o + +most_cdev-objs := cdev.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 1e5cbc893496..dd9456fd2cd6 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * cdev.c - Application interfacing module for character devices + * cdev.c - Character device component for Mostcore * * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -22,15 +16,17 @@ #include <linux/kfifo.h> #include <linux/uaccess.h> #include <linux/idr.h> -#include "mostcore.h" +#include "most/core.h" -static dev_t aim_devno; -static struct class *aim_class; -static struct ida minor_id; -static unsigned int major; -static struct most_aim cdev_aim; +static struct cdev_component { + dev_t devno; + struct ida minor_id; + unsigned int major; + struct class *class; + struct core_component cc; +} comp; -struct aim_channel { +struct comp_channel { wait_queue_head_t wq; spinlock_t unlink; /* synchronization lock to unlink channels */ struct cdev cdev; @@ -46,28 +42,28 @@ struct aim_channel { struct list_head list; }; -#define to_channel(d) container_of(d, struct aim_channel, cdev) +#define to_channel(d) container_of(d, struct comp_channel, cdev) static struct list_head channel_list; static spinlock_t ch_list_lock; -static inline bool ch_has_mbo(struct aim_channel *c) +static inline bool ch_has_mbo(struct comp_channel *c) { - return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; + return channel_has_mbo(c->iface, c->channel_id, &comp.cc) > 0; } -static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) +static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo) { if (!kfifo_peek(&c->fifo, mbo)) { - *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + *mbo = most_get_mbo(c->iface, c->channel_id, &comp.cc); if (*mbo) kfifo_in(&c->fifo, mbo, 1); } return *mbo; } -static struct aim_channel *get_channel(struct most_interface *iface, int id) +static struct comp_channel *get_channel(struct most_interface *iface, int id) { - struct aim_channel *c, *tmp; + struct comp_channel *c, *tmp; unsigned long flags; int found_channel = 0; @@ -84,44 +80,44 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id) return c; } -static void stop_channel(struct aim_channel *c) +static void stop_channel(struct comp_channel *c) { struct mbo *mbo; while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) most_put_mbo(mbo); - most_stop_channel(c->iface, c->channel_id, &cdev_aim); + most_stop_channel(c->iface, c->channel_id, &comp.cc); } -static void destroy_cdev(struct aim_channel *c) +static void destroy_cdev(struct comp_channel *c) { unsigned long flags; - device_destroy(aim_class, c->devno); + device_destroy(comp.class, c->devno); cdev_del(&c->cdev); spin_lock_irqsave(&ch_list_lock, flags); list_del(&c->list); spin_unlock_irqrestore(&ch_list_lock, flags); } -static void destroy_channel(struct aim_channel *c) +static void destroy_channel(struct comp_channel *c) { - ida_simple_remove(&minor_id, MINOR(c->devno)); + ida_simple_remove(&comp.minor_id, MINOR(c->devno)); kfifo_free(&c->fifo); kfree(c); } /** - * aim_open - implements the syscall to open the device + * comp_open - implements the syscall to open the device * @inode: inode pointer * @filp: file pointer * * This stores the channel pointer in the private data field of * the file structure and activates the channel within the core. */ -static int aim_open(struct inode *inode, struct file *filp) +static int comp_open(struct inode *inode, struct file *filp) { - struct aim_channel *c; + struct comp_channel *c; int ret; c = to_channel(inode->i_cdev); @@ -149,7 +145,7 @@ static int aim_open(struct inode *inode, struct file *filp) } c->mbo_offs = 0; - ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); + ret = most_start_channel(c->iface, c->channel_id, &comp.cc); if (!ret) c->access_ref = 1; mutex_unlock(&c->io_mutex); @@ -157,15 +153,15 @@ static int aim_open(struct inode *inode, struct file *filp) } /** - * aim_close - implements the syscall to close the device + * comp_close - implements the syscall to close the device * @inode: inode pointer * @filp: file pointer * * This stops the channel within the core. */ -static int aim_close(struct inode *inode, struct file *filp) +static int comp_close(struct inode *inode, struct file *filp) { - struct aim_channel *c = to_channel(inode->i_cdev); + struct comp_channel *c = to_channel(inode->i_cdev); mutex_lock(&c->io_mutex); spin_lock(&c->unlink); @@ -182,19 +178,19 @@ static int aim_close(struct inode *inode, struct file *filp) } /** - * aim_write - implements the syscall to write to the device + * comp_write - implements the syscall to write to the device * @filp: file pointer * @buf: pointer to user buffer * @count: number of bytes to write * @offset: offset from where to start writing */ -static ssize_t aim_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) +static ssize_t comp_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset) { int ret; size_t to_copy, left; struct mbo *mbo = NULL; - struct aim_channel *c = filp->private_data; + struct comp_channel *c = filp->private_data; mutex_lock(&c->io_mutex); while (c->dev && !ch_get_mbo(c, &mbo)) { @@ -236,18 +232,18 @@ unlock: } /** - * aim_read - implements the syscall to read from the device + * comp_read - implements the syscall to read from the device * @filp: file pointer * @buf: pointer to user buffer * @count: number of bytes to read * @offset: offset from where to start reading */ static ssize_t -aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) +comp_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { size_t to_copy, not_copied, copied; struct mbo *mbo; - struct aim_channel *c = filp->private_data; + struct comp_channel *c = filp->private_data; mutex_lock(&c->io_mutex); while (c->dev && !kfifo_peek(&c->fifo, &mbo)) { @@ -287,9 +283,9 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) return copied; } -static unsigned int aim_poll(struct file *filp, poll_table *wait) +static unsigned int comp_poll(struct file *filp, poll_table *wait) { - struct aim_channel *c = filp->private_data; + struct comp_channel *c = filp->private_data; unsigned int mask = 0; poll_wait(filp, &c->wq, wait); @@ -309,24 +305,24 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait) */ static const struct file_operations channel_fops = { .owner = THIS_MODULE, - .read = aim_read, - .write = aim_write, - .open = aim_open, - .release = aim_close, - .poll = aim_poll, + .read = comp_read, + .write = comp_write, + .open = comp_open, + .release = comp_close, + .poll = comp_poll, }; /** - * aim_disconnect_channel - disconnect a channel + * comp_disconnect_channel - disconnect a channel * @iface: pointer to interface instance * @channel_id: channel index * * This frees allocated memory and removes the cdev that represents this * channel in user space. */ -static int aim_disconnect_channel(struct most_interface *iface, int channel_id) +static int comp_disconnect_channel(struct most_interface *iface, int channel_id) { - struct aim_channel *c; + struct comp_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); @@ -354,15 +350,15 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) } /** - * aim_rx_completion - completion handler for rx channels + * comp_rx_completion - completion handler for rx channels * @mbo: pointer to buffer object that has completed * * This searches for the channel linked to this MBO and stores it in the local * fifo buffer. */ -static int aim_rx_completion(struct mbo *mbo) +static int comp_rx_completion(struct mbo *mbo) { - struct aim_channel *c; + struct comp_channel *c; if (!mbo) return -EINVAL; @@ -387,15 +383,15 @@ static int aim_rx_completion(struct mbo *mbo) } /** - * aim_tx_completion - completion handler for tx channels + * comp_tx_completion - completion handler for tx channels * @iface: pointer to interface instance * @channel_id: channel index/ID * * This wakes sleeping processes in the wait-queue. */ -static int aim_tx_completion(struct most_interface *iface, int channel_id) +static int comp_tx_completion(struct most_interface *iface, int channel_id) { - struct aim_channel *c; + struct comp_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); @@ -414,35 +410,33 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) } /** - * aim_probe - probe function of the driver module + * comp_probe - probe function of the driver module * @iface: pointer to interface instance * @channel_id: channel index/ID * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) * @name: name of the device to be created * * This allocates achannel object and creates the device node in /dev * * Returns 0 on success or error code otherwise. */ -static int aim_probe(struct most_interface *iface, int channel_id, - struct most_channel_config *cfg, - struct kobject *parent, char *name) +static int comp_probe(struct most_interface *iface, int channel_id, + struct most_channel_config *cfg, char *name) { - struct aim_channel *c; + struct comp_channel *c; unsigned long cl_flags; int retval; int current_minor; - if ((!iface) || (!cfg) || (!parent) || (!name)) { - pr_info("Probing AIM with bad arguments"); + if ((!iface) || (!cfg) || (!name)) { + pr_info("Probing component with bad arguments"); return -EINVAL; } c = get_channel(iface, channel_id); if (c) return -EEXIST; - current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); + current_minor = ida_simple_get(&comp.minor_id, 0, 0, GFP_KERNEL); if (current_minor < 0) return current_minor; @@ -452,7 +446,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, goto error_alloc_channel; } - c->devno = MKDEV(major, current_minor); + c->devno = MKDEV(comp.major, current_minor); cdev_init(&c->cdev, &channel_fops); c->cdev.owner = THIS_MODULE; cdev_add(&c->cdev, c->devno, 1); @@ -472,11 +466,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, spin_lock_irqsave(&ch_list_lock, cl_flags); list_add_tail(&c->list, &channel_list); spin_unlock_irqrestore(&ch_list_lock, cl_flags); - c->dev = device_create(aim_class, - NULL, - c->devno, - NULL, - "%s", name); + c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name); if (IS_ERR(c->dev)) { retval = PTR_ERR(c->dev); @@ -493,16 +483,18 @@ error_alloc_kfifo: cdev_del(&c->cdev); kfree(c); error_alloc_channel: - ida_simple_remove(&minor_id, current_minor); + ida_simple_remove(&comp.minor_id, current_minor); return retval; } -static struct most_aim cdev_aim = { - .name = "cdev", - .probe_channel = aim_probe, - .disconnect_channel = aim_disconnect_channel, - .rx_completion = aim_rx_completion, - .tx_completion = aim_tx_completion, +static struct cdev_component comp = { + .cc = { + .name = "cdev", + .probe_channel = comp_probe, + .disconnect_channel = comp_disconnect_channel, + .rx_completion = comp_rx_completion, + .tx_completion = comp_tx_completion, + }, }; static int __init mod_init(void) @@ -511,54 +503,52 @@ static int __init mod_init(void) pr_info("init()\n"); + comp.class = class_create(THIS_MODULE, "most_cdev"); + if (IS_ERR(comp.class)) { + pr_info("No udev support.\n"); + return PTR_ERR(comp.class); + } + INIT_LIST_HEAD(&channel_list); spin_lock_init(&ch_list_lock); - ida_init(&minor_id); + ida_init(&comp.minor_id); - err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); + err = alloc_chrdev_region(&comp.devno, 0, 50, "cdev"); if (err < 0) goto dest_ida; - major = MAJOR(aim_devno); - - aim_class = class_create(THIS_MODULE, "most_cdev_aim"); - if (IS_ERR(aim_class)) { - pr_err("no udev support\n"); - err = PTR_ERR(aim_class); - goto free_cdev; - } - err = most_register_aim(&cdev_aim); + comp.major = MAJOR(comp.devno); + err = most_register_component(&comp.cc); if (err) - goto dest_class; + goto free_cdev; return 0; -dest_class: - class_destroy(aim_class); free_cdev: - unregister_chrdev_region(aim_devno, 1); + unregister_chrdev_region(comp.devno, 1); dest_ida: - ida_destroy(&minor_id); + ida_destroy(&comp.minor_id); + class_destroy(comp.class); return err; } static void __exit mod_exit(void) { - struct aim_channel *c, *tmp; + struct comp_channel *c, *tmp; pr_info("exit module\n"); - most_deregister_aim(&cdev_aim); + most_deregister_component(&comp.cc); list_for_each_entry_safe(c, tmp, &channel_list, list) { destroy_cdev(c); destroy_channel(c); } - class_destroy(aim_class); - unregister_chrdev_region(aim_devno, 1); - ida_destroy(&minor_id); + unregister_chrdev_region(comp.devno, 1); + ida_destroy(&comp.minor_id); + class_destroy(comp.class); } module_init(mod_init); module_exit(mod_exit); MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("character device AIM for mostcore"); +MODULE_DESCRIPTION("character device component for mostcore"); diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c new file mode 100644 index 000000000000..c1fba5ba7541 --- /dev/null +++ b/drivers/staging/most/core.c @@ -0,0 +1,1603 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * core.c - Implementation of core module of MOST Linux driver stack + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/poll.h> +#include <linux/wait.h> +#include <linux/kobject.h> +#include <linux/mutex.h> +#include <linux/completion.h> +#include <linux/sysfs.h> +#include <linux/kthread.h> +#include <linux/dma-mapping.h> +#include <linux/idr.h> +#include <most/core.h> + +#define MAX_CHANNELS 64 +#define STRING_SIZE 80 + +static struct ida mdev_id; +static int dummy_num_buffers; + +static struct mostcore { + struct device dev; + struct device_driver drv; + struct bus_type bus; + struct list_head comp_list; +} mc; + +#define to_driver(d) container_of(d, struct mostcore, drv); + +struct pipe { + struct core_component *comp; + int refs; + int num_buffers; +}; + +struct most_channel { + struct device dev; + struct completion cleanup; + atomic_t mbo_ref; + atomic_t mbo_nq_level; + u16 channel_id; + char name[STRING_SIZE]; + bool is_poisoned; + struct mutex start_mutex; + struct mutex nq_mutex; /* nq thread synchronization */ + int is_starving; + struct most_interface *iface; + struct most_channel_config cfg; + bool keep_mbo; + bool enqueue_halt; + struct list_head fifo; + spinlock_t fifo_lock; + struct list_head halt_fifo; + struct list_head list; + struct pipe pipe0; + struct pipe pipe1; + struct list_head trash_fifo; + struct task_struct *hdm_enqueue_task; + wait_queue_head_t hdm_fifo_wq; + +}; + +#define to_channel(d) container_of(d, struct most_channel, dev) + +struct interface_private { + int dev_id; + char name[STRING_SIZE]; + struct most_channel *channel[MAX_CHANNELS]; + struct list_head channel_list; +}; + +static const struct { + int most_ch_data_type; + const char *name; +} ch_data_type[] = { + { MOST_CH_CONTROL, "control\n" }, + { MOST_CH_ASYNC, "async\n" }, + { MOST_CH_SYNC, "sync\n" }, + { MOST_CH_ISOC, "isoc\n"}, + { MOST_CH_ISOC, "isoc_avp\n"}, +}; + +/** + * list_pop_mbo - retrieves the first MBO of the list and removes it + * @ptr: the list head to grab the MBO from. + */ +#define list_pop_mbo(ptr) \ +({ \ + struct mbo *_mbo = list_first_entry(ptr, struct mbo, list); \ + list_del(&_mbo->list); \ + _mbo; \ +}) + +/** + * most_free_mbo_coherent - free an MBO and its coherent buffer + * @mbo: most buffer + */ +static void most_free_mbo_coherent(struct mbo *mbo) +{ + struct most_channel *c = mbo->context; + u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; + + dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address, + mbo->bus_address); + kfree(mbo); + if (atomic_sub_and_test(1, &c->mbo_ref)) + complete(&c->cleanup); +} + +/** + * flush_channel_fifos - clear the channel fifos + * @c: pointer to channel object + */ +static void flush_channel_fifos(struct most_channel *c) +{ + unsigned long flags, hf_flags; + struct mbo *mbo, *tmp; + + if (list_empty(&c->fifo) && list_empty(&c->halt_fifo)) + return; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_for_each_entry_safe(mbo, tmp, &c->fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, flags); + } + spin_unlock_irqrestore(&c->fifo_lock, flags); + + spin_lock_irqsave(&c->fifo_lock, hf_flags); + list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, hf_flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, hf_flags); + } + spin_unlock_irqrestore(&c->fifo_lock, hf_flags); + + if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) + pr_info("WARN: fifo | trash fifo not empty\n"); +} + +/** + * flush_trash_fifo - clear the trash fifo + * @c: pointer to channel object + */ +static int flush_trash_fifo(struct most_channel *c) +{ + struct mbo *mbo, *tmp; + unsigned long flags; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, flags); + } + spin_unlock_irqrestore(&c->fifo_lock, flags); + return 0; +} + +static ssize_t available_directions_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + unsigned int i = c->channel_id; + + strcpy(buf, ""); + if (c->iface->channel_vector[i].direction & MOST_CH_RX) + strcat(buf, "rx "); + if (c->iface->channel_vector[i].direction & MOST_CH_TX) + strcat(buf, "tx "); + strcat(buf, "\n"); + return strlen(buf); +} + +static ssize_t available_datatypes_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + unsigned int i = c->channel_id; + + strcpy(buf, ""); + if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL) + strcat(buf, "control "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC) + strcat(buf, "async "); + if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) + strcat(buf, "sync "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC) + strcat(buf, "isoc "); + strcat(buf, "\n"); + return strlen(buf); +} + +static ssize_t number_of_packet_buffers_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].num_buffers_packet); +} + +static ssize_t number_of_stream_buffers_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].num_buffers_streaming); +} + +static ssize_t size_of_packet_buffer_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].buffer_size_packet); +} + +static ssize_t size_of_stream_buffer_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].buffer_size_streaming); +} + +static ssize_t channel_starving_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); +} + +static ssize_t set_number_of_buffers_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); +} + +static ssize_t set_number_of_buffers_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct most_channel *c = to_channel(dev); + int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); + + if (ret) + return ret; + return count; +} + +static ssize_t set_buffer_size_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); +} + +static ssize_t set_buffer_size_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct most_channel *c = to_channel(dev); + int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); + + if (ret) + return ret; + return count; +} + +static ssize_t set_direction_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + + if (c->cfg.direction & MOST_CH_TX) + return snprintf(buf, PAGE_SIZE, "tx\n"); + else if (c->cfg.direction & MOST_CH_RX) + return snprintf(buf, PAGE_SIZE, "rx\n"); + return snprintf(buf, PAGE_SIZE, "unconfigured\n"); +} + +static ssize_t set_direction_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct most_channel *c = to_channel(dev); + + if (!strcmp(buf, "dir_rx\n")) { + c->cfg.direction = MOST_CH_RX; + } else if (!strcmp(buf, "rx\n")) { + c->cfg.direction = MOST_CH_RX; + } else if (!strcmp(buf, "dir_tx\n")) { + c->cfg.direction = MOST_CH_TX; + } else if (!strcmp(buf, "tx\n")) { + c->cfg.direction = MOST_CH_TX; + } else { + pr_info("WARN: invalid attribute settings\n"); + return -EINVAL; + } + return count; +} + +static ssize_t set_datatype_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + struct most_channel *c = to_channel(dev); + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) + return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); + } + return snprintf(buf, PAGE_SIZE, "unconfigured\n"); +} + +static ssize_t set_datatype_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + int i; + struct most_channel *c = to_channel(dev); + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (!strcmp(buf, ch_data_type[i].name)) { + c->cfg.data_type = ch_data_type[i].most_ch_data_type; + break; + } + } + + if (i == ARRAY_SIZE(ch_data_type)) { + pr_info("WARN: invalid attribute settings\n"); + return -EINVAL; + } + return count; +} + +static ssize_t set_subbuffer_size_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); +} + +static ssize_t set_subbuffer_size_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct most_channel *c = to_channel(dev); + int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); + + if (ret) + return ret; + return count; +} + +static ssize_t set_packets_per_xact_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_channel *c = to_channel(dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); +} + +static ssize_t set_packets_per_xact_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct most_channel *c = to_channel(dev); + int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); + + if (ret) + return ret; + return count; +} + +#define DEV_ATTR(_name) (&dev_attr_##_name.attr) + +static DEVICE_ATTR_RO(available_directions); +static DEVICE_ATTR_RO(available_datatypes); +static DEVICE_ATTR_RO(number_of_packet_buffers); +static DEVICE_ATTR_RO(number_of_stream_buffers); +static DEVICE_ATTR_RO(size_of_stream_buffer); +static DEVICE_ATTR_RO(size_of_packet_buffer); +static DEVICE_ATTR_RO(channel_starving); +static DEVICE_ATTR_RW(set_buffer_size); +static DEVICE_ATTR_RW(set_number_of_buffers); +static DEVICE_ATTR_RW(set_direction); +static DEVICE_ATTR_RW(set_datatype); +static DEVICE_ATTR_RW(set_subbuffer_size); +static DEVICE_ATTR_RW(set_packets_per_xact); + +static struct attribute *channel_attrs[] = { + DEV_ATTR(available_directions), + DEV_ATTR(available_datatypes), + DEV_ATTR(number_of_packet_buffers), + DEV_ATTR(number_of_stream_buffers), + DEV_ATTR(size_of_stream_buffer), + DEV_ATTR(size_of_packet_buffer), + DEV_ATTR(channel_starving), + DEV_ATTR(set_buffer_size), + DEV_ATTR(set_number_of_buffers), + DEV_ATTR(set_direction), + DEV_ATTR(set_datatype), + DEV_ATTR(set_subbuffer_size), + DEV_ATTR(set_packets_per_xact), + NULL, +}; + +static struct attribute_group channel_attr_group = { + .attrs = channel_attrs, +}; + +static const struct attribute_group *channel_attr_groups[] = { + &channel_attr_group, + NULL, +}; + +static ssize_t description_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_interface *iface = to_most_interface(dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", iface->description); +} + +static ssize_t interface_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct most_interface *iface = to_most_interface(dev); + + switch (iface->interface) { + case ITYPE_LOOPBACK: + return snprintf(buf, PAGE_SIZE, "loopback\n"); + case ITYPE_I2C: + return snprintf(buf, PAGE_SIZE, "i2c\n"); + case ITYPE_I2S: + return snprintf(buf, PAGE_SIZE, "i2s\n"); + case ITYPE_TSI: + return snprintf(buf, PAGE_SIZE, "tsi\n"); + case ITYPE_HBI: + return snprintf(buf, PAGE_SIZE, "hbi\n"); + case ITYPE_MEDIALB_DIM: + return snprintf(buf, PAGE_SIZE, "mlb_dim\n"); + case ITYPE_MEDIALB_DIM2: + return snprintf(buf, PAGE_SIZE, "mlb_dim2\n"); + case ITYPE_USB: + return snprintf(buf, PAGE_SIZE, "usb\n"); + case ITYPE_PCIE: + return snprintf(buf, PAGE_SIZE, "pcie\n"); + } + return snprintf(buf, PAGE_SIZE, "unknown\n"); +} + +static DEVICE_ATTR_RO(description); +static DEVICE_ATTR_RO(interface); + +static struct attribute *interface_attrs[] = { + DEV_ATTR(description), + DEV_ATTR(interface), + NULL, +}; + +static struct attribute_group interface_attr_group = { + .attrs = interface_attrs, +}; + +static const struct attribute_group *interface_attr_groups[] = { + &interface_attr_group, + NULL, +}; + +static struct core_component *match_component(char *name) +{ + struct core_component *comp; + + list_for_each_entry(comp, &mc.comp_list, list) { + if (!strcmp(comp->name, name)) + return comp; + } + return NULL; +} + +struct show_links_data { + int offs; + char *buf; +}; + +int print_links(struct device *dev, void *data) +{ + struct show_links_data *d = data; + int offs = d->offs; + char *buf = d->buf; + struct most_channel *c; + struct most_interface *iface = to_most_interface(dev); + + list_for_each_entry(c, &iface->p->channel_list, list) { + if (c->pipe0.comp) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe0.comp->name, + dev_name(&iface->dev), + dev_name(&c->dev)); + } + if (c->pipe1.comp) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe1.comp->name, + dev_name(&iface->dev), + dev_name(&c->dev)); + } + } + d->offs = offs; + return 0; +} + +static ssize_t links_show(struct device_driver *drv, char *buf) +{ + struct show_links_data d = { .buf = buf }; + + bus_for_each_dev(&mc.bus, NULL, &d, print_links); + return d.offs; +} + +static ssize_t components_show(struct device_driver *drv, char *buf) +{ + struct core_component *comp; + int offs = 0; + + list_for_each_entry(comp, &mc.comp_list, list) { + offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n", + comp->name); + } + return offs; +} +/** + * split_string - parses buf and extracts ':' separated substrings. + * + * @buf: complete string from attribute 'add_channel' + * @a: storage for 1st substring (=interface name) + * @b: storage for 2nd substring (=channel name) + * @c: storage for 3rd substring (=component name) + * @d: storage optional 4th substring (=user defined name) + * + * Examples: + * + * Input: "mdev0:ch6:cdev:my_channel\n" or + * "mdev0:ch6:cdev:my_channel" + * + * Output: *a -> "mdev0", *b -> "ch6", *c -> "cdev" *d -> "my_channel" + * + * Input: "mdev1:ep81:cdev\n" + * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d -> "" + * + * Input: "mdev1:ep81" + * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d == NULL + */ +static int split_string(char *buf, char **a, char **b, char **c, char **d) +{ + *a = strsep(&buf, ":"); + if (!*a) + return -EIO; + + *b = strsep(&buf, ":\n"); + if (!*b) + return -EIO; + + *c = strsep(&buf, ":\n"); + if (!*c) + return -EIO; + + if (d) + *d = strsep(&buf, ":\n"); + + return 0; +} + +static int match_bus_dev(struct device *dev, void *data) +{ + char *mdev_name = data; + + return !strcmp(dev_name(dev), mdev_name); +} + +/** + * get_channel - get pointer to channel + * @mdev: name of the device interface + * @mdev_ch: name of channel + */ +static struct most_channel *get_channel(char *mdev, char *mdev_ch) +{ + struct device *dev = NULL; + struct most_interface *iface; + struct most_channel *c, *tmp; + + dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev); + if (!dev) + return NULL; + iface = to_most_interface(dev); + list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { + if (!strcmp(dev_name(&c->dev), mdev_ch)) + return c; + } + return NULL; +} + +static +inline int link_channel_to_component(struct most_channel *c, + struct core_component *comp, + char *comp_param) +{ + int ret; + struct core_component **comp_ptr; + + if (!c->pipe0.comp) + comp_ptr = &c->pipe0.comp; + else if (!c->pipe1.comp) + comp_ptr = &c->pipe1.comp; + else + return -ENOSPC; + + *comp_ptr = comp; + ret = comp->probe_channel(c->iface, c->channel_id, &c->cfg, comp_param); + if (ret) { + *comp_ptr = NULL; + return ret; + } + return 0; +} + +/** + * add_link_store - store function for add_link attribute + * @drv: device driver + * @buf: buffer + * @len: buffer length + * + * This parses the string given by buf and splits it into + * four substrings. Note: last substring is optional. In case a cdev + * component is loaded the optional 4th substring will make up the name of + * device node in the /dev directory. If omitted, the device node will + * inherit the channel's name within sysfs. + * + * Searches for (device, channel) pair and probes the component + * + * Example: + * (1) echo "mdev0:ch6:cdev:my_rxchannel" >add_link + * (2) echo "mdev1:ep81:cdev" >add_link + * + * (1) would create the device node /dev/my_rxchannel + * (2) would create the device node /dev/mdev1-ep81 + */ +static ssize_t add_link_store(struct device_driver *drv, + const char *buf, + size_t len) +{ + struct most_channel *c; + struct core_component *comp; + char buffer[STRING_SIZE]; + char *mdev; + char *mdev_ch; + char *comp_name; + char *comp_param; + char devnod_buf[STRING_SIZE]; + int ret; + size_t max_len = min_t(size_t, len + 1, STRING_SIZE); + + strlcpy(buffer, buf, max_len); + ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param); + if (ret) + return ret; + comp = match_component(comp_name); + if (!comp) + return -ENODEV; + if (!comp_param || *comp_param == 0) { + snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, + mdev_ch); + comp_param = devnod_buf; + } + + c = get_channel(mdev, mdev_ch); + if (!c) + return -ENODEV; + + ret = link_channel_to_component(c, comp, comp_param); + if (ret) + return ret; + return len; +} + +/** + * remove_link_store - store function for remove_link attribute + * @drv: device driver + * @buf: buffer + * @len: buffer length + * + * Example: + * echo "mdev0:ep81" >remove_link + */ +static ssize_t remove_link_store(struct device_driver *drv, + const char *buf, + size_t len) +{ + struct most_channel *c; + struct core_component *comp; + char buffer[STRING_SIZE]; + char *mdev; + char *mdev_ch; + char *comp_name; + int ret; + size_t max_len = min_t(size_t, len + 1, STRING_SIZE); + + strlcpy(buffer, buf, max_len); + ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, NULL); + if (ret) + return ret; + comp = match_component(comp_name); + if (!comp) + return -ENODEV; + c = get_channel(mdev, mdev_ch); + if (!c) + return -ENODEV; + + if (comp->disconnect_channel(c->iface, c->channel_id)) + return -EIO; + if (c->pipe0.comp == comp) + c->pipe0.comp = NULL; + if (c->pipe1.comp == comp) + c->pipe1.comp = NULL; + return len; +} + +#define DRV_ATTR(_name) (&driver_attr_##_name.attr) + +static DRIVER_ATTR_RO(links); +static DRIVER_ATTR_RO(components); +static DRIVER_ATTR_WO(add_link); +static DRIVER_ATTR_WO(remove_link); + +static struct attribute *mc_attrs[] = { + DRV_ATTR(links), + DRV_ATTR(components), + DRV_ATTR(add_link), + DRV_ATTR(remove_link), + NULL, +}; + +static struct attribute_group mc_attr_group = { + .attrs = mc_attrs, +}; + +static const struct attribute_group *mc_attr_groups[] = { + &mc_attr_group, + NULL, +}; + +int most_match(struct device *dev, struct device_driver *drv) +{ + if (!strcmp(dev_name(dev), "most")) + return 0; + else + return 1; +} + +static inline void trash_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_channel *c = mbo->context; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add(&mbo->list, &c->trash_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); +} + +static bool hdm_mbo_ready(struct most_channel *c) +{ + bool empty; + + if (c->enqueue_halt) + return false; + + spin_lock_irq(&c->fifo_lock); + empty = list_empty(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); + + return !empty; +} + +static void nq_hdm_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_channel *c = mbo->context; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add_tail(&mbo->list, &c->halt_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + wake_up_interruptible(&c->hdm_fifo_wq); +} + +static int hdm_enqueue_thread(void *data) +{ + struct most_channel *c = data; + struct mbo *mbo; + int ret; + typeof(c->iface->enqueue) enqueue = c->iface->enqueue; + + while (likely(!kthread_should_stop())) { + wait_event_interruptible(c->hdm_fifo_wq, + hdm_mbo_ready(c) || + kthread_should_stop()); + + mutex_lock(&c->nq_mutex); + spin_lock_irq(&c->fifo_lock); + if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) { + spin_unlock_irq(&c->fifo_lock); + mutex_unlock(&c->nq_mutex); + continue; + } + + mbo = list_pop_mbo(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); + + if (c->cfg.direction == MOST_CH_RX) + mbo->buffer_length = c->cfg.buffer_size; + + ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo); + mutex_unlock(&c->nq_mutex); + + if (unlikely(ret)) { + pr_err("hdm enqueue failed\n"); + nq_hdm_mbo(mbo); + c->hdm_enqueue_task = NULL; + return 0; + } + } + + return 0; +} + +static int run_enqueue_thread(struct most_channel *c, int channel_id) +{ + struct task_struct *task = + kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d", + channel_id); + + if (IS_ERR(task)) + return PTR_ERR(task); + + c->hdm_enqueue_task = task; + return 0; +} + +/** + * arm_mbo - recycle MBO for further usage + * @mbo: most buffer + * + * This puts an MBO back to the list to have it ready for up coming + * tx transactions. + * + * In case the MBO belongs to a channel that recently has been + * poisoned, the MBO is scheduled to be trashed. + * Calls the completion handler of an attached component. + */ +static void arm_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_channel *c; + + BUG_ON((!mbo) || (!mbo->context)); + c = mbo->context; + + if (c->is_poisoned) { + trash_mbo(mbo); + return; + } + + spin_lock_irqsave(&c->fifo_lock, flags); + ++*mbo->num_buffers_ptr; + list_add_tail(&mbo->list, &c->fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + + if (c->pipe0.refs && c->pipe0.comp->tx_completion) + c->pipe0.comp->tx_completion(c->iface, c->channel_id); + + if (c->pipe1.refs && c->pipe1.comp->tx_completion) + c->pipe1.comp->tx_completion(c->iface, c->channel_id); +} + +/** + * arm_mbo_chain - helper function that arms an MBO chain for the HDM + * @c: pointer to interface channel + * @dir: direction of the channel + * @compl: pointer to completion function + * + * This allocates buffer objects including the containing DMA coherent + * buffer and puts them in the fifo. + * Buffers of Rx channels are put in the kthread fifo, hence immediately + * submitted to the HDM. + * + * Returns the number of allocated and enqueued MBOs. + */ +static int arm_mbo_chain(struct most_channel *c, int dir, + void (*compl)(struct mbo *)) +{ + unsigned int i; + int retval; + struct mbo *mbo; + u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; + + atomic_set(&c->mbo_nq_level, 0); + + for (i = 0; i < c->cfg.num_buffers; i++) { + mbo = kzalloc(sizeof(*mbo), GFP_KERNEL); + if (!mbo) { + retval = i; + goto _exit; + } + mbo->context = c; + mbo->ifp = c->iface; + mbo->hdm_channel_id = c->channel_id; + mbo->virt_address = dma_alloc_coherent(NULL, + coherent_buf_size, + &mbo->bus_address, + GFP_KERNEL); + if (!mbo->virt_address) { + pr_info("WARN: No DMA coherent buffer.\n"); + retval = i; + goto _error1; + } + mbo->complete = compl; + mbo->num_buffers_ptr = &dummy_num_buffers; + if (dir == MOST_CH_RX) { + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); + } else { + arm_mbo(mbo); + } + } + return i; + +_error1: + kfree(mbo); +_exit: + return retval; +} + +/** + * most_submit_mbo - submits an MBO to fifo + * @mbo: most buffer + */ +void most_submit_mbo(struct mbo *mbo) +{ + if (WARN_ONCE(!mbo || !mbo->context, + "bad mbo or missing channel reference\n")) + return; + + nq_hdm_mbo(mbo); +} +EXPORT_SYMBOL_GPL(most_submit_mbo); + +/** + * most_write_completion - write completion handler + * @mbo: most buffer + * + * This recycles the MBO for further usage. In case the channel has been + * poisoned, the MBO is scheduled to be trashed. + */ +static void most_write_completion(struct mbo *mbo) +{ + struct most_channel *c; + + BUG_ON((!mbo) || (!mbo->context)); + + c = mbo->context; + if (mbo->status == MBO_E_INVAL) + pr_info("WARN: Tx MBO status: invalid\n"); + if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) + trash_mbo(mbo); + else + arm_mbo(mbo); +} + +int channel_has_mbo(struct most_interface *iface, int id, + struct core_component *comp) +{ + struct most_channel *c = iface->p->channel[id]; + unsigned long flags; + int empty; + + if (unlikely(!c)) + return -EINVAL; + + if (c->pipe0.refs && c->pipe1.refs && + ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) || + (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0))) + return 0; + + spin_lock_irqsave(&c->fifo_lock, flags); + empty = list_empty(&c->fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + return !empty; +} +EXPORT_SYMBOL_GPL(channel_has_mbo); + +/** + * most_get_mbo - get pointer to an MBO of pool + * @iface: pointer to interface instance + * @id: channel ID + * @comp: driver component + * + * This attempts to get a free buffer out of the channel fifo. + * Returns a pointer to MBO on success or NULL otherwise. + */ +struct mbo *most_get_mbo(struct most_interface *iface, int id, + struct core_component *comp) +{ + struct mbo *mbo; + struct most_channel *c; + unsigned long flags; + int *num_buffers_ptr; + + c = iface->p->channel[id]; + if (unlikely(!c)) + return NULL; + + if (c->pipe0.refs && c->pipe1.refs && + ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) || + (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0))) + return NULL; + + if (comp == c->pipe0.comp) + num_buffers_ptr = &c->pipe0.num_buffers; + else if (comp == c->pipe1.comp) + num_buffers_ptr = &c->pipe1.num_buffers; + else + num_buffers_ptr = &dummy_num_buffers; + + spin_lock_irqsave(&c->fifo_lock, flags); + if (list_empty(&c->fifo)) { + spin_unlock_irqrestore(&c->fifo_lock, flags); + return NULL; + } + mbo = list_pop_mbo(&c->fifo); + --*num_buffers_ptr; + spin_unlock_irqrestore(&c->fifo_lock, flags); + + mbo->num_buffers_ptr = num_buffers_ptr; + mbo->buffer_length = c->cfg.buffer_size; + return mbo; +} +EXPORT_SYMBOL_GPL(most_get_mbo); + +/** + * most_put_mbo - return buffer to pool + * @mbo: most buffer + */ +void most_put_mbo(struct mbo *mbo) +{ + struct most_channel *c = mbo->context; + + if (c->cfg.direction == MOST_CH_TX) { + arm_mbo(mbo); + return; + } + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); +} +EXPORT_SYMBOL_GPL(most_put_mbo); + +/** + * most_read_completion - read completion handler + * @mbo: most buffer + * + * This function is called by the HDM when data has been received from the + * hardware and copied to the buffer of the MBO. + * + * In case the channel has been poisoned it puts the buffer in the trash queue. + * Otherwise, it passes the buffer to an component for further processing. + */ +static void most_read_completion(struct mbo *mbo) +{ + struct most_channel *c = mbo->context; + + if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) { + trash_mbo(mbo); + return; + } + + if (mbo->status == MBO_E_INVAL) { + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); + return; + } + + if (atomic_sub_and_test(1, &c->mbo_nq_level)) + c->is_starving = 1; + + if (c->pipe0.refs && c->pipe0.comp->rx_completion && + c->pipe0.comp->rx_completion(mbo) == 0) + return; + + if (c->pipe1.refs && c->pipe1.comp->rx_completion && + c->pipe1.comp->rx_completion(mbo) == 0) + return; + + most_put_mbo(mbo); +} + +/** + * most_start_channel - prepares a channel for communication + * @iface: pointer to interface instance + * @id: channel ID + * @comp: driver component + * + * This prepares the channel for usage. Cross-checks whether the + * channel's been properly configured. + * + * Returns 0 on success or error code otherwise. + */ +int most_start_channel(struct most_interface *iface, int id, + struct core_component *comp) +{ + int num_buffer; + int ret; + struct most_channel *c = iface->p->channel[id]; + + if (unlikely(!c)) + return -EINVAL; + + mutex_lock(&c->start_mutex); + if (c->pipe0.refs + c->pipe1.refs > 0) + goto out; /* already started by another component */ + + if (!try_module_get(iface->mod)) { + pr_info("failed to acquire HDM lock\n"); + mutex_unlock(&c->start_mutex); + return -ENOLCK; + } + + c->cfg.extra_len = 0; + if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { + pr_info("channel configuration failed. Go check settings...\n"); + ret = -EINVAL; + goto error; + } + + init_waitqueue_head(&c->hdm_fifo_wq); + + if (c->cfg.direction == MOST_CH_RX) + num_buffer = arm_mbo_chain(c, c->cfg.direction, + most_read_completion); + else + num_buffer = arm_mbo_chain(c, c->cfg.direction, + most_write_completion); + if (unlikely(!num_buffer)) { + pr_info("failed to allocate memory\n"); + ret = -ENOMEM; + goto error; + } + + ret = run_enqueue_thread(c, id); + if (ret) + goto error; + + c->is_starving = 0; + c->pipe0.num_buffers = c->cfg.num_buffers / 2; + c->pipe1.num_buffers = c->cfg.num_buffers - c->pipe0.num_buffers; + atomic_set(&c->mbo_ref, num_buffer); + +out: + if (comp == c->pipe0.comp) + c->pipe0.refs++; + if (comp == c->pipe1.comp) + c->pipe1.refs++; + mutex_unlock(&c->start_mutex); + return 0; + +error: + module_put(iface->mod); + mutex_unlock(&c->start_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(most_start_channel); + +/** + * most_stop_channel - stops a running channel + * @iface: pointer to interface instance + * @id: channel ID + * @comp: driver component + */ +int most_stop_channel(struct most_interface *iface, int id, + struct core_component *comp) +{ + struct most_channel *c; + + if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { + pr_err("Bad interface or index out of range\n"); + return -EINVAL; + } + c = iface->p->channel[id]; + if (unlikely(!c)) + return -EINVAL; + + mutex_lock(&c->start_mutex); + if (c->pipe0.refs + c->pipe1.refs >= 2) + goto out; + + if (c->hdm_enqueue_task) + kthread_stop(c->hdm_enqueue_task); + c->hdm_enqueue_task = NULL; + + if (iface->mod) + module_put(iface->mod); + + c->is_poisoned = true; + if (c->iface->poison_channel(c->iface, c->channel_id)) { + pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id, + c->iface->description); + mutex_unlock(&c->start_mutex); + return -EAGAIN; + } + flush_trash_fifo(c); + flush_channel_fifos(c); + +#ifdef CMPL_INTERRUPTIBLE + if (wait_for_completion_interruptible(&c->cleanup)) { + pr_info("Interrupted while clean up ch %d\n", c->channel_id); + mutex_unlock(&c->start_mutex); + return -EINTR; + } +#else + wait_for_completion(&c->cleanup); +#endif + c->is_poisoned = false; + +out: + if (comp == c->pipe0.comp) + c->pipe0.refs--; + if (comp == c->pipe1.comp) + c->pipe1.refs--; + mutex_unlock(&c->start_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(most_stop_channel); + +/** + * most_register_component - registers a driver component with the core + * @comp: driver component + */ +int most_register_component(struct core_component *comp) +{ + if (!comp) { + pr_err("Bad component\n"); + return -EINVAL; + } + list_add_tail(&comp->list, &mc.comp_list); + pr_info("registered new core component %s\n", comp->name); + return 0; +} +EXPORT_SYMBOL_GPL(most_register_component); + +static int disconnect_channels(struct device *dev, void *data) +{ + struct most_interface *iface; + struct most_channel *c, *tmp; + struct core_component *comp = data; + + iface = to_most_interface(dev); + list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { + if (c->pipe0.comp == comp || c->pipe1.comp == comp) + comp->disconnect_channel(c->iface, c->channel_id); + if (c->pipe0.comp == comp) + c->pipe0.comp = NULL; + if (c->pipe1.comp == comp) + c->pipe1.comp = NULL; + } + return 0; +} + +/** + * most_deregister_component - deregisters a driver component with the core + * @comp: driver component + */ +int most_deregister_component(struct core_component *comp) +{ + if (!comp) { + pr_err("Bad component\n"); + return -EINVAL; + } + + bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels); + list_del(&comp->list); + pr_info("deregistering component %s\n", comp->name); + return 0; +} +EXPORT_SYMBOL_GPL(most_deregister_component); + +static void release_interface(struct device *dev) +{ + pr_info("releasing interface dev %s...\n", dev_name(dev)); +} + +static void release_channel(struct device *dev) +{ + pr_info("releasing channel dev %s...\n", dev_name(dev)); +} + +/** + * most_register_interface - registers an interface with core + * @iface: device interface + * + * Allocates and initializes a new interface instance and all of its channels. + * Returns a pointer to kobject or an error pointer. + */ +int most_register_interface(struct most_interface *iface) +{ + unsigned int i; + int id; + struct most_channel *c; + + if (!iface || !iface->enqueue || !iface->configure || + !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { + pr_err("Bad interface or channel overflow\n"); + return -EINVAL; + } + + id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); + if (id < 0) { + pr_info("Failed to alloc mdev ID\n"); + return id; + } + + iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL); + if (!iface->p) { + pr_info("Failed to allocate interface instance\n"); + ida_simple_remove(&mdev_id, id); + return -ENOMEM; + } + + INIT_LIST_HEAD(&iface->p->channel_list); + iface->p->dev_id = id; + snprintf(iface->p->name, STRING_SIZE, "mdev%d", id); + iface->dev.init_name = iface->p->name; + iface->dev.bus = &mc.bus; + iface->dev.parent = &mc.dev; + iface->dev.groups = interface_attr_groups; + iface->dev.release = release_interface; + if (device_register(&iface->dev)) { + pr_err("registering iface->dev failed\n"); + kfree(iface->p); + ida_simple_remove(&mdev_id, id); + return -ENOMEM; + } + + for (i = 0; i < iface->num_channels; i++) { + const char *name_suffix = iface->channel_vector[i].name_suffix; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + goto free_instance; + if (!name_suffix) + snprintf(c->name, STRING_SIZE, "ch%d", i); + else + snprintf(c->name, STRING_SIZE, "%s", name_suffix); + c->dev.init_name = c->name; + c->dev.parent = &iface->dev; + c->dev.groups = channel_attr_groups; + c->dev.release = release_channel; + if (device_register(&c->dev)) { + pr_err("registering c->dev failed\n"); + goto free_instance_nodev; + } + iface->p->channel[i] = c; + c->is_starving = 0; + c->iface = iface; + c->channel_id = i; + c->keep_mbo = false; + c->enqueue_halt = false; + c->is_poisoned = false; + c->cfg.direction = 0; + c->cfg.data_type = 0; + c->cfg.num_buffers = 0; + c->cfg.buffer_size = 0; + c->cfg.subbuffer_size = 0; + c->cfg.packets_per_xact = 0; + spin_lock_init(&c->fifo_lock); + INIT_LIST_HEAD(&c->fifo); + INIT_LIST_HEAD(&c->trash_fifo); + INIT_LIST_HEAD(&c->halt_fifo); + init_completion(&c->cleanup); + atomic_set(&c->mbo_ref, 0); + mutex_init(&c->start_mutex); + mutex_init(&c->nq_mutex); + list_add_tail(&c->list, &iface->p->channel_list); + } + pr_info("registered new device mdev%d (%s)\n", + id, iface->description); + return 0; + +free_instance_nodev: + kfree(c); + +free_instance: + while (i > 0) { + c = iface->p->channel[--i]; + device_unregister(&c->dev); + kfree(c); + } + kfree(iface->p); + device_unregister(&iface->dev); + ida_simple_remove(&mdev_id, id); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(most_register_interface); + +/** + * most_deregister_interface - deregisters an interface with core + * @iface: device interface + * + * Before removing an interface instance from the list, all running + * channels are stopped and poisoned. + */ +void most_deregister_interface(struct most_interface *iface) +{ + int i; + struct most_channel *c; + + pr_info("deregistering device %s (%s)\n", dev_name(&iface->dev), iface->description); + for (i = 0; i < iface->num_channels; i++) { + c = iface->p->channel[i]; + if (c->pipe0.comp) + c->pipe0.comp->disconnect_channel(c->iface, + c->channel_id); + if (c->pipe1.comp) + c->pipe1.comp->disconnect_channel(c->iface, + c->channel_id); + c->pipe0.comp = NULL; + c->pipe1.comp = NULL; + list_del(&c->list); + device_unregister(&c->dev); + kfree(c); + } + + ida_simple_remove(&mdev_id, iface->p->dev_id); + kfree(iface->p); + device_unregister(&iface->dev); +} +EXPORT_SYMBOL_GPL(most_deregister_interface); + +/** + * most_stop_enqueue - prevents core from enqueueing MBOs + * @iface: pointer to interface + * @id: channel id + * + * This is called by an HDM that _cannot_ attend to its duties and + * is imminent to get run over by the core. The core is not going to + * enqueue any further packets unless the flagging HDM calls + * most_resume enqueue(). + */ +void most_stop_enqueue(struct most_interface *iface, int id) +{ + struct most_channel *c = iface->p->channel[id]; + + if (!c) + return; + + mutex_lock(&c->nq_mutex); + c->enqueue_halt = true; + mutex_unlock(&c->nq_mutex); +} +EXPORT_SYMBOL_GPL(most_stop_enqueue); + +/** + * most_resume_enqueue - allow core to enqueue MBOs again + * @iface: pointer to interface + * @id: channel id + * + * This clears the enqueue halt flag and enqueues all MBOs currently + * sitting in the wait fifo. + */ +void most_resume_enqueue(struct most_interface *iface, int id) +{ + struct most_channel *c = iface->p->channel[id]; + + if (!c) + return; + + mutex_lock(&c->nq_mutex); + c->enqueue_halt = false; + mutex_unlock(&c->nq_mutex); + + wake_up_interruptible(&c->hdm_fifo_wq); +} +EXPORT_SYMBOL_GPL(most_resume_enqueue); + +static void release_most_sub(struct device *dev) +{ + pr_info("releasing most_subsystem\n"); +} + +static int __init most_init(void) +{ + int err; + + pr_info("init()\n"); + INIT_LIST_HEAD(&mc.comp_list); + ida_init(&mdev_id); + + mc.bus.name = "most", + mc.bus.match = most_match, + mc.drv.name = "most_core", + mc.drv.bus = &mc.bus, + mc.drv.groups = mc_attr_groups; + + err = bus_register(&mc.bus); + if (err) { + pr_info("Cannot register most bus\n"); + return err; + } + err = driver_register(&mc.drv); + if (err) { + pr_info("Cannot register core driver\n"); + goto exit_bus; + } + mc.dev.init_name = "most_bus"; + mc.dev.release = release_most_sub; + if (device_register(&mc.dev)) { + err = -ENOMEM; + goto exit_driver; + } + + return 0; + +exit_driver: + driver_unregister(&mc.drv); +exit_bus: + bus_unregister(&mc.bus); + return err; +} + +static void __exit most_exit(void) +{ + pr_info("exit core module\n"); + device_unregister(&mc.dev); + driver_unregister(&mc.drv); + bus_unregister(&mc.bus); + ida_destroy(&mdev_id); +} + +module_init(most_init); +module_exit(most_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); +MODULE_DESCRIPTION("Core module of stacked MOST Linux driver"); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/core.h index 915e5159d1eb..74a29163b68a 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/core.h @@ -1,31 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * mostcore.h - Interface between MostCore, - * Hardware Dependent Module (HDM) and Application Interface Module (AIM). + * most.h - API for component and adapter drivers * * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. - */ - -/* - * Authors: - * Andrey Shvetsov <andrey.shvetsov@k2l.de> - * Christian Gromm <christian.gromm@microchip.com> - * Sebastian Graf */ #ifndef __MOST_CORE_H__ #define __MOST_CORE_H__ #include <linux/types.h> +#include <linux/device.h> -struct kobject; struct module; +struct interface_private; /** * Interface type @@ -79,22 +66,22 @@ enum mbo_status_flags { * The value is bitwise OR-combination of the values from the * enumeration most_channel_data_type. Zero is allowed value and means * "channel may not be used". - * @num_buffer_packet: Maximum number of buffers supported by this channel + * @num_buffers_packet: Maximum number of buffers supported by this channel * for packet data types (Async,Control,QoS) * @buffer_size_packet: Maximum buffer size supported by this channel * for packet data types (Async,Control,QoS) - * @num_buffer_streaming: Maximum number of buffers supported by this channel + * @num_buffers_streaming: Maximum number of buffers supported by this channel * for streaming data types (Sync,AV Packetized) * @buffer_size_streaming: Maximum buffer size supported by this channel * for streaming data types (Sync,AV Packetized) * @name_suffix: Optional suffix providean by an HDM that is attached to the * regular channel name. * - * Describes the capabilities of a MostCore channel like supported Data Types + * Describes the capabilities of a MOST channel like supported Data Types * and directions. This information is provided by an HDM for the MostCore. * * The Core creates read only sysfs attribute files in - * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the + * /sys/devices/most/mdev#/<channel>/ with the * following attributes: * -available_directions * -available_datatypes @@ -129,7 +116,7 @@ struct most_channel_capability { * @packets_per_xact: number of MOST frames that are packet inside one USB * packet. This is USB specific * - * Describes the configuration for a MostCore channel. This information is + * Describes the configuration for a MOST channel. This information is * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a * parameter of the "configure" function call. */ @@ -153,6 +140,7 @@ struct most_channel_config { * * @list: list head for use by the mbo's current owner * @ifp: (in) associated interface instance + * @num_buffers_ptr: amount of pool buffers * @hdm_channel_id: (in) HDM channel instance * @virt_address: (in) kernel virtual address of the buffer * @bus_address: (in) bus address of the buffer @@ -161,15 +149,15 @@ struct most_channel_config { * @status: (out) transfer status * @complete: (in) completion routine * - * The MostCore allocates and initializes the MBO. + * The core allocates and initializes the MBO. * - * The HDM receives MBO for transfer from MostCore with the call to enqueue(). + * The HDM receives MBO for transfer from the core with the call to enqueue(). * The HDM copies the data to- or from the buffer depending on configured * channel direction, set "processed_length" and "status" and completes * the transfer procedure by calling the completion routine. * - * At the end the MostCore deallocates the MBO or recycles it for further - * transfers for the same or different HDM. + * Finally, the MBO is being deallocated or recycled for further + * transfers of the same or a different HDM. * * Directions of usage: * The core driver should never access any MBO fields (even if marked @@ -202,10 +190,12 @@ struct mbo { /** * Interface instance description. * - * Describes one instance of an interface like Medusa PCIe or Vantage USB. + * Describes an interface of a MOST device the core driver is bound to. * This structure is allocated and initialized in the HDM. MostCore may not * modify this structure. * + * @dev: the actual device + * @mod: module * @interface Interface type. \sa most_interface_type. * @description PRELIMINARY. * Unique description of the device instance from point of view of the @@ -238,10 +228,11 @@ struct mbo { * @priv Private field used by mostcore to store context information. */ struct most_interface { + struct device dev; struct module *mod; enum most_interface_type interface; const char *description; - int num_channels; + unsigned int num_channels; struct most_channel_capability *channel_vector; int (*configure)(struct most_interface *iface, int channel_idx, struct most_channel_config *channel_config); @@ -253,27 +244,29 @@ struct most_interface { unsigned char link_stat, unsigned char *mac_addr)); void *priv; + struct interface_private *p; }; +#define to_most_interface(d) container_of(d, struct most_interface, dev) + /** - * struct most_aim - identifies MOST device driver to mostcore - * @name: Driver name + * struct core_component - identifies a loadable component for the mostcore + * @list: list_head + * @name: component name * @probe_channel: function for core to notify driver about channel connection * @disconnect_channel: callback function to disconnect a certain channel * @rx_completion: completion handler for received packets * @tx_completion: completion handler for transmitted packets - * @context: context pointer to be used by mostcore */ -struct most_aim { +struct core_component { + struct list_head list; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, - struct most_channel_config *cfg, - struct kobject *parent, char *name); + struct most_channel_config *cfg, char *name); int (*disconnect_channel)(struct most_interface *iface, int channel_idx); int (*rx_completion)(struct mbo *mbo); int (*tx_completion)(struct most_interface *iface, int channel_idx); - void *context; }; /** @@ -285,7 +278,7 @@ struct most_aim { * Note: HDM has to ensure that any reference held on the kobj is * released before deregistering the interface. */ -struct kobject *most_register_interface(struct most_interface *iface); +int most_register_interface(struct most_interface *iface); /** * Deregisters instance of the interface. @@ -310,16 +303,16 @@ void most_stop_enqueue(struct most_interface *iface, int channel_idx); * in wait fifo. */ void most_resume_enqueue(struct most_interface *iface, int channel_idx); -int most_register_aim(struct most_aim *aim); -int most_deregister_aim(struct most_aim *aim); +int most_register_component(struct core_component *comp); +int most_deregister_component(struct core_component *comp); struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, - struct most_aim *); + struct core_component *comp); void most_put_mbo(struct mbo *mbo); int channel_has_mbo(struct most_interface *iface, int channel_idx, - struct most_aim *aim); + struct core_component *comp); int most_start_channel(struct most_interface *iface, int channel_idx, - struct most_aim *); + struct core_component *comp); int most_stop_channel(struct most_interface *iface, int channel_idx, - struct most_aim *); + struct core_component *comp); #endif /* MOST_CORE_H_ */ diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/dim2/Kconfig index 663bfebff674..e39c4e525cac 100644 --- a/drivers/staging/most/hdm-dim2/Kconfig +++ b/drivers/staging/most/dim2/Kconfig @@ -2,8 +2,8 @@ # MediaLB configuration # -config HDM_DIM2 - tristate "DIM2 HDM" +config MOST_DIM2 + tristate "DIM2" depends on HAS_IOMEM ---help--- @@ -13,4 +13,4 @@ config HDM_DIM2 maintainer of this driver. To compile this driver as a module, choose M here: the - module will be called hdm_dim2. + module will be called most_dim2. diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile new file mode 100644 index 000000000000..66676f5907ee --- /dev/null +++ b/drivers/staging/most/dim2/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_DIM2) += most_dim2.o + +most_dim2-objs := dim2.o hal.o sysfs.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/dim2/dim2.c index df7021c522b3..2bd40abbc8c6 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/dim2/dim2.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module + * dim2.c - MediaLB DIM2 Hardware Dependent Module * * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -25,11 +19,11 @@ #include <linux/sched.h> #include <linux/kthread.h> -#include <mostcore.h> -#include "dim2_hal.h" -#include "dim2_hdm.h" -#include "dim2_errors.h" -#include "dim2_sysfs.h" +#include "most/core.h" +#include "hal.h" +#include "dim2.h" +#include "errors.h" +#include "sysfs.h" #define DMA_CHANNELS (32 - 1) /* channel 0 is a system channel */ @@ -93,6 +87,7 @@ struct hdm_channel { * @atx_idx: index of async tx channel */ struct dim2_hdm { + struct device dev; struct hdm_channel hch[DMA_CHANNELS]; struct most_channel_capability capabilities[DMA_CHANNELS]; struct most_interface most_iface; @@ -744,7 +739,6 @@ static int dim2_probe(struct platform_device *pdev) struct dim2_hdm *dev; struct resource *res; int ret, i; - struct kobject *kobj; int irq; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -832,17 +826,20 @@ static int dim2_probe(struct platform_device *pdev) dev->most_iface.enqueue = enqueue; dev->most_iface.poison_channel = poison_channel; dev->most_iface.request_netinfo = request_netinfo; + dev->dev.init_name = "dim2_state"; + dev->dev.parent = &dev->most_iface.dev; - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { - ret = PTR_ERR(kobj); + ret = most_register_interface(&dev->most_iface); + if (ret) { dev_err(&pdev->dev, "failed to register MOST interface\n"); goto err_stop_thread; } - ret = dim2_sysfs_probe(&dev->bus, kobj); - if (ret) + ret = dim2_sysfs_probe(&dev->dev); + if (ret) { + dev_err(&pdev->dev, "failed to create sysfs attribute\n"); goto err_unreg_iface; + } ret = startup_dim(pdev); if (ret) { @@ -853,7 +850,7 @@ static int dim2_probe(struct platform_device *pdev) return 0; err_destroy_bus: - dim2_sysfs_destroy(&dev->bus); + dim2_sysfs_destroy(&dev->dev); err_unreg_iface: most_deregister_interface(&dev->most_iface); err_stop_thread: @@ -881,7 +878,7 @@ static int dim2_remove(struct platform_device *pdev) if (pdata && pdata->destroy) pdata->destroy(pdata); - dim2_sysfs_destroy(&dev->bus); + dim2_sysfs_destroy(&dev->dev); most_deregister_interface(&dev->most_iface); kthread_stop(dev->netinfo_task); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/dim2/dim2.h index 4050e7c764ed..6a9fc51a2eb4 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.h +++ b/drivers/staging/most/dim2/dim2.h @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * dim2_hdm.h - MediaLB DIM2 HDM Header + * dim2.h - MediaLB DIM2 HDM Header * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #ifndef DIM2_HDM_H diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/dim2/errors.h index 66343ba426c1..3487510fbd2f 100644 --- a/drivers/staging/most/hdm-dim2/dim2_errors.h +++ b/drivers/staging/most/dim2/errors.h @@ -1,15 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * dim2_errors.h - Definitions of errors for DIM2 HAL API + * errors.h - Definitions of errors for DIM2 HAL API * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #ifndef _MOST_DIM_ERRORS_H diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/dim2/hal.c index 91484643d289..17c04e1c5e62 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -1,22 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * dim2_hal.c - DIM2 HAL implementation + * hal.c - DIM2 HAL implementation * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ /* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ -#include "dim2_hal.h" -#include "dim2_errors.h" -#include "dim2_reg.h" +#include "hal.h" +#include "errors.h" +#include "reg.h" #include <linux/stddef.h> #include <linux/kernel.h> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/dim2/hal.h index 6df6ea5f7da4..e04a5350f134 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -1,22 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * dim2_hal.h - DIM2 HAL interface + * hal.h - DIM2 HAL interface * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #ifndef _DIM2_HAL_H #define _DIM2_HAL_H #include <linux/types.h> -#include "dim2_reg.h" +#include "reg.h" /* * The values below are specified in the hardware specification. diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/dim2/reg.h index f7d9fbcd29f2..69cbf78239f1 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/dim2/reg.h @@ -1,15 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * dim2_reg.h - Definitions for registers of DIM2 + * reg.h - Definitions for registers of DIM2 * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #ifndef DIM2_OS62420_H diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c new file mode 100644 index 000000000000..c85b2cdcdca3 --- /dev/null +++ b/drivers/staging/most/dim2/sysfs.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sysfs.c - MediaLB sysfs information + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include "sysfs.h" +#include <linux/device.h> + +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + bool state = dim2_sysfs_get_state_cb(); + + return sprintf(buf, "%s\n", state ? "locked" : ""); +} + +static DEVICE_ATTR_RO(state); + +static struct attribute *dev_attrs[] = { + &dev_attr_state.attr, + NULL, +}; + +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, +}; + +static const struct attribute_group *dev_attr_groups[] = { + &dev_attr_group, + NULL, +}; + +int dim2_sysfs_probe(struct device *dev) +{ + dev->groups = dev_attr_groups; + return device_register(dev); +} + +void dim2_sysfs_destroy(struct device *dev) +{ + device_unregister(dev); +} diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h new file mode 100644 index 000000000000..33756a3bffe2 --- /dev/null +++ b/drivers/staging/most/dim2/sysfs.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sysfs.h - MediaLB sysfs information + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ + +#ifndef DIM2_SYSFS_H +#define DIM2_SYSFS_H + +#include <linux/kobject.h> + +struct medialb_bus { + struct kobject kobj_group; +}; + +struct device; + +int dim2_sysfs_probe(struct device *dev); +void dim2_sysfs_destroy(struct device *dev); + +/* + * callback, + * must deliver MediaLB state as true if locked or false if unlocked + */ +bool dim2_sysfs_get_state_cb(void); + +#endif /* DIM2_SYSFS_H */ diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile deleted file mode 100644 index 6bbee879a8ea..000000000000 --- a/drivers/staging/most/hdm-dim2/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o - -hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o -ccflags-y += -Idrivers/staging/most/mostcore/ -ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c deleted file mode 100644 index d8b22f91d2c3..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * dim2_sysfs.c - MediaLB sysfs information - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. - */ - -/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include "dim2_sysfs.h" - -struct bus_attr { - struct attribute attr; - ssize_t (*show)(struct medialb_bus *bus, char *buf); - ssize_t (*store)(struct medialb_bus *bus, const char *buf, - size_t count); -}; - -static ssize_t state_show(struct medialb_bus *bus, char *buf) -{ - bool state = dim2_sysfs_get_state_cb(); - - return sprintf(buf, "%s\n", state ? "locked" : ""); -} - -static struct bus_attr state_attr = __ATTR_RO(state); - -static struct attribute *bus_default_attrs[] = { - &state_attr.attr, - NULL, -}; - -static const struct attribute_group bus_attr_group = { - .attrs = bus_default_attrs, -}; - -static void bus_kobj_release(struct kobject *kobj) -{ -} - -static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->show) - return -EIO; - - return xattr->show(bus, buf); -} - -static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->store) - return -EIO; - - return xattr->store(bus, buf, count); -} - -static struct sysfs_ops const bus_kobj_sysfs_ops = { - .show = bus_kobj_attr_show, - .store = bus_kobj_attr_store, -}; - -static struct kobj_type bus_ktype = { - .release = bus_kobj_release, - .sysfs_ops = &bus_kobj_sysfs_ops, -}; - -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) -{ - int err; - - kobject_init(&bus->kobj_group, &bus_ktype); - err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); - if (err) { - pr_err("kobject_add() failed: %d\n", err); - goto err_kobject_add; - } - - err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); - if (err) { - pr_err("sysfs_create_group() failed: %d\n", err); - goto err_create_group; - } - - return 0; - -err_create_group: - kobject_put(&bus->kobj_group); - -err_kobject_add: - return err; -} - -void dim2_sysfs_destroy(struct medialb_bus *bus) -{ - kobject_put(&bus->kobj_group); -} diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h deleted file mode 100644 index b71dd027ebc7..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * dim2_sysfs.h - MediaLB sysfs information - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. - */ - -/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ - -#ifndef DIM2_SYSFS_H -#define DIM2_SYSFS_H - -#include <linux/kobject.h> - -struct medialb_bus { - struct kobject kobj_group; -}; - -struct dim2_hdm; - -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); -void dim2_sysfs_destroy(struct medialb_bus *bus); - -/* - * callback, - * must deliver MediaLB state as true if locked or false if unlocked - */ -bool dim2_sysfs_get_state_cb(void); - -#endif /* DIM2_SYSFS_H */ diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile deleted file mode 100644 index 03a4a59b1f9f..000000000000 --- a/drivers/staging/most/hdm-i2c/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_HDM_I2C) += hdm_i2c.o - -ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile deleted file mode 100644 index 6bbacb41e94b..000000000000 --- a/drivers/staging/most/hdm-usb/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_HDM_USB) += hdm_usb.o - -ccflags-y += -Idrivers/staging/most/mostcore/ -ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/i2c/Kconfig index 6fd7983668ad..79d0ff27f56d 100644 --- a/drivers/staging/most/hdm-i2c/Kconfig +++ b/drivers/staging/most/i2c/Kconfig @@ -2,11 +2,11 @@ # MOST I2C configuration # -config HDM_I2C - tristate "I2C HDM" +config MOST_I2C + tristate "I2C" depends on I2C ---help--- Say Y here if you want to connect via I2C to network tranceiver. To compile this driver as a module, choose M here: the - module will be called hdm_i2c. + module will be called most_i2c. diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile new file mode 100644 index 000000000000..a7d094c1e1c2 --- /dev/null +++ b/drivers/staging/most/i2c/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_I2C) += most_i2c.o + +most_i2c-objs := i2c.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/i2c/i2c.c index 2b4de404e46a..141239fc9f51 100644 --- a/drivers/staging/most/hdm-i2c/hdm_i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * hdm_i2c.c - Hardware Dependent Module for I2C Interface + * i2c.c - Hardware Dependent Module for I2C Interface * * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -21,7 +15,7 @@ #include <linux/interrupt.h> #include <linux/err.h> -#include <mostcore.h> +#include "most/core.h" enum { CH_RX, CH_TX, NUM_CHANNELS }; @@ -309,7 +303,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct hdm_i2c *dev; int ret, i; - struct kobject *kobj; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -347,11 +340,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) dev->client = client; i2c_set_clientdata(client, dev); - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { + ret = most_register_interface(&dev->most_iface); + if (ret) { pr_err("Failed to register i2c as a MOST interface\n"); kfree(dev); - return PTR_ERR(kobj); + return ret; } dev->polling_mode = polling_req || client->irq <= 0; diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig deleted file mode 100644 index 47172546d728..000000000000 --- a/drivers/staging/most/mostcore/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# MOSTCore configuration -# - -config MOSTCORE - tristate "MOST Core" - depends on HAS_DMA - - ---help--- - Say Y here if you want to enable MOST support. - This device driver needs at least an additional AIM and HDM to work. - - To compile this driver as a module, choose M here: the - module will be called mostcore. diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile deleted file mode 100644 index a078f01cf7c2..000000000000 --- a/drivers/staging/most/mostcore/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_MOSTCORE) += mostcore.o - -mostcore-objs := core.o diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c deleted file mode 100644 index 069269db394c..000000000000 --- a/drivers/staging/most/mostcore/core.c +++ /dev/null @@ -1,1949 +0,0 @@ -/* - * core.c - Implementation of core module of MOST Linux driver stack - * - * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/list.h> -#include <linux/poll.h> -#include <linux/wait.h> -#include <linux/kobject.h> -#include <linux/mutex.h> -#include <linux/completion.h> -#include <linux/sysfs.h> -#include <linux/kthread.h> -#include <linux/dma-mapping.h> -#include <linux/idr.h> -#include "mostcore.h" - -#define MAX_CHANNELS 64 -#define STRING_SIZE 80 - -static struct class *most_class; -static struct device *core_dev; -static struct ida mdev_id; -static int dummy_num_buffers; - -struct most_c_aim_obj { - struct most_aim *ptr; - int refs; - int num_buffers; -}; - -struct most_c_obj { - struct kobject kobj; - struct completion cleanup; - atomic_t mbo_ref; - atomic_t mbo_nq_level; - u16 channel_id; - bool is_poisoned; - struct mutex start_mutex; - struct mutex nq_mutex; /* nq thread synchronization */ - int is_starving; - struct most_interface *iface; - struct most_inst_obj *inst; - struct most_channel_config cfg; - bool keep_mbo; - bool enqueue_halt; - struct list_head fifo; - spinlock_t fifo_lock; - struct list_head halt_fifo; - struct list_head list; - struct most_c_aim_obj aim0; - struct most_c_aim_obj aim1; - struct list_head trash_fifo; - struct task_struct *hdm_enqueue_task; - wait_queue_head_t hdm_fifo_wq; -}; - -#define to_c_obj(d) container_of(d, struct most_c_obj, kobj) - -struct most_inst_obj { - int dev_id; - struct most_interface *iface; - struct list_head channel_list; - struct most_c_obj *channel[MAX_CHANNELS]; - struct kobject kobj; - struct list_head list; -}; - -static const struct { - int most_ch_data_type; - const char *name; -} ch_data_type[] = { - { MOST_CH_CONTROL, "control\n" }, - { MOST_CH_ASYNC, "async\n" }, - { MOST_CH_SYNC, "sync\n" }, - { MOST_CH_ISOC, "isoc\n"}, - { MOST_CH_ISOC, "isoc_avp\n"}, -}; - -#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) - -/** - * list_pop_mbo - retrieves the first MBO of the list and removes it - * @ptr: the list head to grab the MBO from. - */ -#define list_pop_mbo(ptr) \ -({ \ - struct mbo *_mbo = list_first_entry(ptr, struct mbo, list); \ - list_del(&_mbo->list); \ - _mbo; \ -}) - -/* ___ ___ - * ___C H A N N E L___ - */ - -/** - * struct most_c_attr - to access the attributes of a channel object - * @attr: attributes of a channel - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_c_attr { - struct attribute attr; - ssize_t (*show)(struct most_c_obj *d, - struct most_c_attr *attr, - char *buf); - ssize_t (*store)(struct most_c_obj *d, - struct most_c_attr *attr, - const char *buf, - size_t count); -}; - -#define to_channel_attr(a) container_of(a, struct most_c_attr, attr) - -/** - * channel_attr_show - show function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - */ -static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->show) - return -EIO; - - return channel_attr->show(c_obj, channel_attr, buf); -} - -/** - * channel_attr_store - store function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - * @len: length of buffer - */ -static ssize_t channel_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->store) - return -EIO; - return channel_attr->store(c_obj, channel_attr, buf, len); -} - -static const struct sysfs_ops most_channel_sysfs_ops = { - .show = channel_attr_show, - .store = channel_attr_store, -}; - -/** - * most_free_mbo_coherent - free an MBO and its coherent buffer - * @mbo: buffer to be released - * - */ -static void most_free_mbo_coherent(struct mbo *mbo) -{ - struct most_c_obj *c = mbo->context; - u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; - - dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address, - mbo->bus_address); - kfree(mbo); - if (atomic_sub_and_test(1, &c->mbo_ref)) - complete(&c->cleanup); -} - -/** - * flush_channel_fifos - clear the channel fifos - * @c: pointer to channel object - */ -static void flush_channel_fifos(struct most_c_obj *c) -{ - unsigned long flags, hf_flags; - struct mbo *mbo, *tmp; - - if (list_empty(&c->fifo) && list_empty(&c->halt_fifo)) - return; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_for_each_entry_safe(mbo, tmp, &c->fifo, list) { - list_del(&mbo->list); - spin_unlock_irqrestore(&c->fifo_lock, flags); - most_free_mbo_coherent(mbo); - spin_lock_irqsave(&c->fifo_lock, flags); - } - spin_unlock_irqrestore(&c->fifo_lock, flags); - - spin_lock_irqsave(&c->fifo_lock, hf_flags); - list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) { - list_del(&mbo->list); - spin_unlock_irqrestore(&c->fifo_lock, hf_flags); - most_free_mbo_coherent(mbo); - spin_lock_irqsave(&c->fifo_lock, hf_flags); - } - spin_unlock_irqrestore(&c->fifo_lock, hf_flags); - - if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) - pr_info("WARN: fifo | trash fifo not empty\n"); -} - -/** - * flush_trash_fifo - clear the trash fifo - * @c: pointer to channel object - */ -static int flush_trash_fifo(struct most_c_obj *c) -{ - struct mbo *mbo, *tmp; - unsigned long flags; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) { - list_del(&mbo->list); - spin_unlock_irqrestore(&c->fifo_lock, flags); - most_free_mbo_coherent(mbo); - spin_lock_irqsave(&c->fifo_lock, flags); - } - spin_unlock_irqrestore(&c->fifo_lock, flags); - return 0; -} - -/** - * most_channel_release - release function of channel object - * @kobj: pointer to channel's kobject - */ -static void most_channel_release(struct kobject *kobj) -{ - struct most_c_obj *c = to_c_obj(kobj); - - kfree(c); -} - -static ssize_t available_directions_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - strcpy(buf, ""); - if (c->iface->channel_vector[i].direction & MOST_CH_RX) - strcat(buf, "rx "); - if (c->iface->channel_vector[i].direction & MOST_CH_TX) - strcat(buf, "tx "); - strcat(buf, "\n"); - return strlen(buf); -} - -static ssize_t available_datatypes_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - strcpy(buf, ""); - if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL) - strcat(buf, "control "); - if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC) - strcat(buf, "async "); - if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) - strcat(buf, "sync "); - if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC) - strcat(buf, "isoc "); - strcat(buf, "\n"); - return strlen(buf); -} - -static ssize_t number_of_packet_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].num_buffers_packet); -} - -static ssize_t number_of_stream_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].num_buffers_streaming); -} - -static ssize_t size_of_packet_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].buffer_size_packet); -} - -static ssize_t size_of_stream_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].buffer_size_streaming); -} - -static ssize_t channel_starving_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); -} - -static ssize_t set_number_of_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); -} - -static ssize_t set_number_of_buffers_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); - - if (ret) - return ret; - return count; -} - -static ssize_t set_buffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); -} - -static ssize_t set_buffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); - - if (ret) - return ret; - return count; -} - -static ssize_t set_direction_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - if (c->cfg.direction & MOST_CH_TX) - return snprintf(buf, PAGE_SIZE, "tx\n"); - else if (c->cfg.direction & MOST_CH_RX) - return snprintf(buf, PAGE_SIZE, "rx\n"); - return snprintf(buf, PAGE_SIZE, "unconfigured\n"); -} - -static ssize_t set_direction_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - if (!strcmp(buf, "dir_rx\n")) { - c->cfg.direction = MOST_CH_RX; - } else if (!strcmp(buf, "rx\n")) { - c->cfg.direction = MOST_CH_RX; - } else if (!strcmp(buf, "dir_tx\n")) { - c->cfg.direction = MOST_CH_TX; - } else if (!strcmp(buf, "tx\n")) { - c->cfg.direction = MOST_CH_TX; - } else { - pr_info("WARN: invalid attribute settings\n"); - return -EINVAL; - } - return count; -} - -static ssize_t set_datatype_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { - if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) - return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); - } - return snprintf(buf, PAGE_SIZE, "unconfigured\n"); -} - -static ssize_t set_datatype_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { - if (!strcmp(buf, ch_data_type[i].name)) { - c->cfg.data_type = ch_data_type[i].most_ch_data_type; - break; - } - } - - if (i == ARRAY_SIZE(ch_data_type)) { - pr_info("WARN: invalid attribute settings\n"); - return -EINVAL; - } - return count; -} - -static ssize_t set_subbuffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); -} - -static ssize_t set_subbuffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); - - if (ret) - return ret; - return count; -} - -static ssize_t set_packets_per_xact_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); -} - -static ssize_t set_packets_per_xact_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); - - if (ret) - return ret; - return count; -} - -static struct most_c_attr most_c_attrs[] = { - __ATTR_RO(available_directions), - __ATTR_RO(available_datatypes), - __ATTR_RO(number_of_packet_buffers), - __ATTR_RO(number_of_stream_buffers), - __ATTR_RO(size_of_stream_buffer), - __ATTR_RO(size_of_packet_buffer), - __ATTR_RO(channel_starving), - __ATTR_RW(set_buffer_size), - __ATTR_RW(set_number_of_buffers), - __ATTR_RW(set_direction), - __ATTR_RW(set_datatype), - __ATTR_RW(set_subbuffer_size), - __ATTR_RW(set_packets_per_xact), -}; - -/** - * most_channel_def_attrs - array of default attributes of channel object - */ -static struct attribute *most_channel_def_attrs[] = { - &most_c_attrs[0].attr, - &most_c_attrs[1].attr, - &most_c_attrs[2].attr, - &most_c_attrs[3].attr, - &most_c_attrs[4].attr, - &most_c_attrs[5].attr, - &most_c_attrs[6].attr, - &most_c_attrs[7].attr, - &most_c_attrs[8].attr, - &most_c_attrs[9].attr, - &most_c_attrs[10].attr, - &most_c_attrs[11].attr, - &most_c_attrs[12].attr, - NULL, -}; - -static struct kobj_type most_channel_ktype = { - .sysfs_ops = &most_channel_sysfs_ops, - .release = most_channel_release, - .default_attrs = most_channel_def_attrs, -}; - -static struct kset *most_channel_kset; - -/** - * create_most_c_obj - allocates a channel object - * @name: name of the channel object - * @parent: parent kobject - * - * This create a channel object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct most_c_obj * -create_most_c_obj(const char *name, struct kobject *parent) -{ - struct most_c_obj *c; - int retval; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - return NULL; - c->kobj.kset = most_channel_kset; - retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent, - "%s", name); - if (retval) { - kobject_put(&c->kobj); - return NULL; - } - kobject_uevent(&c->kobj, KOBJ_ADD); - return c; -} - -/* ___ ___ - * ___I N S T A N C E___ - */ - -static struct list_head instance_list; - -/** - * struct most_inst_attribute - to access the attributes of instance object - * @attr: attributes of an instance - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_inst_attribute { - struct attribute attr; - ssize_t (*show)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - char *buf); - ssize_t (*store)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_instance_attr(a) \ - container_of(a, struct most_inst_attribute, attr) - -/** - * instance_attr_show - show function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t instance_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->show) - return -EIO; - - return instance_attr->show(instance_obj, instance_attr, buf); -} - -/** - * instance_attr_store - store function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t instance_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->store) - return -EIO; - - return instance_attr->store(instance_obj, instance_attr, buf, len); -} - -static const struct sysfs_ops most_inst_sysfs_ops = { - .show = instance_attr_show, - .store = instance_attr_store, -}; - -/** - * most_inst_release - release function for instance object - * @kobj: pointer to instance's kobject - * - * This frees the allocated memory for the instance object - */ -static void most_inst_release(struct kobject *kobj) -{ - struct most_inst_obj *inst = to_inst_obj(kobj); - - kfree(inst); -} - -static ssize_t description_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", - instance_obj->iface->description); -} - -static ssize_t interface_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, - char *buf) -{ - switch (instance_obj->iface->interface) { - case ITYPE_LOOPBACK: - return snprintf(buf, PAGE_SIZE, "loopback\n"); - case ITYPE_I2C: - return snprintf(buf, PAGE_SIZE, "i2c\n"); - case ITYPE_I2S: - return snprintf(buf, PAGE_SIZE, "i2s\n"); - case ITYPE_TSI: - return snprintf(buf, PAGE_SIZE, "tsi\n"); - case ITYPE_HBI: - return snprintf(buf, PAGE_SIZE, "hbi\n"); - case ITYPE_MEDIALB_DIM: - return snprintf(buf, PAGE_SIZE, "mlb_dim\n"); - case ITYPE_MEDIALB_DIM2: - return snprintf(buf, PAGE_SIZE, "mlb_dim2\n"); - case ITYPE_USB: - return snprintf(buf, PAGE_SIZE, "usb\n"); - case ITYPE_PCIE: - return snprintf(buf, PAGE_SIZE, "pcie\n"); - } - return snprintf(buf, PAGE_SIZE, "unknown\n"); -} - -static struct most_inst_attribute most_inst_attr_description = - __ATTR_RO(description); - -static struct most_inst_attribute most_inst_attr_interface = - __ATTR_RO(interface); - -static struct attribute *most_inst_def_attrs[] = { - &most_inst_attr_description.attr, - &most_inst_attr_interface.attr, - NULL, -}; - -static struct kobj_type most_inst_ktype = { - .sysfs_ops = &most_inst_sysfs_ops, - .release = most_inst_release, - .default_attrs = most_inst_def_attrs, -}; - -static struct kset *most_inst_kset; - -/** - * create_most_inst_obj - creates an instance object - * @name: name of the object to be created - * - * This allocates memory for an instance structure, assigns the proper kset - * and registers it with sysfs. - * - * Returns a pointer to the instance object or NULL when something went wrong. - */ -static struct most_inst_obj *create_most_inst_obj(const char *name) -{ - struct most_inst_obj *inst; - int retval; - - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) - return NULL; - inst->kobj.kset = most_inst_kset; - retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL, - "%s", name); - if (retval) { - kobject_put(&inst->kobj); - return NULL; - } - kobject_uevent(&inst->kobj, KOBJ_ADD); - return inst; -} - -/** - * destroy_most_inst_obj - MOST instance release function - * @inst: pointer to the instance object - * - * This decrements the reference counter of the instance object. - * If the reference count turns zero, its release function is called - */ -static void destroy_most_inst_obj(struct most_inst_obj *inst) -{ - struct most_c_obj *c, *tmp; - - list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - flush_trash_fifo(c); - flush_channel_fifos(c); - kobject_put(&c->kobj); - } - kobject_put(&inst->kobj); -} - -/* ___ ___ - * ___A I M___ - */ -struct most_aim_obj { - struct kobject kobj; - struct list_head list; - struct most_aim *driver; -}; - -#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) - -static struct list_head aim_list; - -/** - * struct most_aim_attribute - to access the attributes of AIM object - * @attr: attributes of an AIM - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_aim_attribute { - struct attribute attr; - ssize_t (*show)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - char *buf); - ssize_t (*store)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr) - -/** - * aim_attr_show - show function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t aim_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->show) - return -EIO; - - return aim_attr->show(aim_obj, aim_attr, buf); -} - -/** - * aim_attr_store - store function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t aim_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->store) - return -EIO; - return aim_attr->store(aim_obj, aim_attr, buf, len); -} - -static const struct sysfs_ops most_aim_sysfs_ops = { - .show = aim_attr_show, - .store = aim_attr_store, -}; - -/** - * most_aim_release - AIM release function - * @kobj: pointer to AIM's kobject - */ -static void most_aim_release(struct kobject *kobj) -{ - struct most_aim_obj *aim_obj = to_aim_obj(kobj); - - kfree(aim_obj); -} - -static ssize_t links_show(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - char *buf) -{ - struct most_c_obj *c; - struct most_inst_obj *i; - int offs = 0; - - list_for_each_entry(i, &instance_list, list) { - list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr == aim_obj->driver || - c->aim1.ptr == aim_obj->driver) { - offs += snprintf(buf + offs, PAGE_SIZE - offs, - "%s:%s\n", - kobject_name(&i->kobj), - kobject_name(&c->kobj)); - } - } - } - - return offs; -} - -/** - * split_string - parses and changes string in the buffer buf and - * splits it into two mandatory and one optional substrings. - * - * @buf: complete string from attribute 'add_channel' - * @a: address of pointer to 1st substring (=instance name) - * @b: address of pointer to 2nd substring (=channel name) - * @c: optional address of pointer to 3rd substring (=user defined name) - * - * Examples: - * - * Input: "mdev0:ch6:my_channel\n" or - * "mdev0:ch6:my_channel" - * - * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel" - * - * Input: "mdev1:ep81\n" - * Output: *a -> "mdev1", *b -> "ep81", *c -> "" - * - * Input: "mdev1:ep81" - * Output: *a -> "mdev1", *b -> "ep81", *c == NULL - */ -static int split_string(char *buf, char **a, char **b, char **c) -{ - *a = strsep(&buf, ":"); - if (!*a) - return -EIO; - - *b = strsep(&buf, ":\n"); - if (!*b) - return -EIO; - - if (c) - *c = strsep(&buf, ":\n"); - - return 0; -} - -/** - * get_channel_by_name - get pointer to channel object - * @mdev: name of the device instance - * @mdev_ch: name of the respective channel - * - * This retrieves the pointer to a channel object. - */ -static struct -most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) -{ - struct most_c_obj *c, *tmp; - struct most_inst_obj *i, *i_tmp; - int found = 0; - - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - if (!strcmp(kobject_name(&i->kobj), mdev)) { - found++; - break; - } - } - if (unlikely(!found)) - return ERR_PTR(-EIO); - - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (!strcmp(kobject_name(&c->kobj), mdev_ch)) { - found++; - break; - } - } - if (unlikely(found < 2)) - return ERR_PTR(-EIO); - return c; -} - -/** - * add_link_store - store() function for add_link attribute - * @aim_obj: pointer to AIM object - * @attr: its attributes - * @buf: buffer - * @len: buffer length - * - * This parses the string given by buf and splits it into - * three substrings. Note: third substring is optional. In case a cdev - * AIM is loaded the optional 3rd substring will make up the name of - * device node in the /dev directory. If omitted, the device node will - * inherit the channel's name within sysfs. - * - * Searches for a pair of device and channel and probes the AIM - * - * Example: - * (1) echo "mdev0:ch6:my_rxchannel" >add_link - * (2) echo "mdev1:ep81" >add_link - * - * (1) would create the device node /dev/my_rxchannel - * (2) would create the device node /dev/mdev1-ep81 - */ -static ssize_t add_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_obj *c; - struct most_aim **aim_ptr; - char buffer[STRING_SIZE]; - char *mdev; - char *mdev_ch; - char *mdev_devnod; - char devnod_buf[STRING_SIZE]; - int ret; - size_t max_len = min_t(size_t, len + 1, STRING_SIZE); - - strlcpy(buffer, buf, max_len); - - ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod); - if (ret) - return ret; - - if (!mdev_devnod || *mdev_devnod == 0) { - snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, - mdev_ch); - mdev_devnod = devnod_buf; - } - - c = get_channel_by_name(mdev, mdev_ch); - if (IS_ERR(c)) - return -ENODEV; - - if (!c->aim0.ptr) - aim_ptr = &c->aim0.ptr; - else if (!c->aim1.ptr) - aim_ptr = &c->aim1.ptr; - else - return -ENOSPC; - - *aim_ptr = aim_obj->driver; - ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, - &c->cfg, &c->kobj, mdev_devnod); - if (ret) { - *aim_ptr = NULL; - return ret; - } - - return len; -} - -/** - * remove_link_store - store function for remove_link attribute - * @aim_obj: pointer to AIM object - * @attr: its attributes - * @buf: buffer - * @len: buffer length - * - * Example: - * echo "mdev0:ep81" >remove_link - */ -static ssize_t remove_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_obj *c; - char buffer[STRING_SIZE]; - char *mdev; - char *mdev_ch; - int ret; - size_t max_len = min_t(size_t, len + 1, STRING_SIZE); - - strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, NULL); - if (ret) - return ret; - - c = get_channel_by_name(mdev, mdev_ch); - if (IS_ERR(c)) - return -ENODEV; - - if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) - return -EIO; - if (c->aim0.ptr == aim_obj->driver) - c->aim0.ptr = NULL; - if (c->aim1.ptr == aim_obj->driver) - c->aim1.ptr = NULL; - return len; -} - -static struct most_aim_attribute most_aim_attrs[] = { - __ATTR_RO(links), - __ATTR_WO(add_link), - __ATTR_WO(remove_link), -}; - -static struct attribute *most_aim_def_attrs[] = { - &most_aim_attrs[0].attr, - &most_aim_attrs[1].attr, - &most_aim_attrs[2].attr, - NULL, -}; - -static struct kobj_type most_aim_ktype = { - .sysfs_ops = &most_aim_sysfs_ops, - .release = most_aim_release, - .default_attrs = most_aim_def_attrs, -}; - -static struct kset *most_aim_kset; - -/** - * create_most_aim_obj - creates an AIM object - * @name: name of the AIM - * - * This creates an AIM object assigns the proper kset and registers - * it with sysfs. - * Returns a pointer to the object or NULL if something went wrong. - */ -static struct most_aim_obj *create_most_aim_obj(const char *name) -{ - struct most_aim_obj *most_aim; - int retval; - - most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL); - if (!most_aim) - return NULL; - most_aim->kobj.kset = most_aim_kset; - retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype, - NULL, "%s", name); - if (retval) { - kobject_put(&most_aim->kobj); - return NULL; - } - kobject_uevent(&most_aim->kobj, KOBJ_ADD); - return most_aim; -} - -/** - * destroy_most_aim_obj - AIM release function - * @p: pointer to AIM object - * - * This decrements the reference counter of the AIM object. If the - * reference count turns zero, its release function will be called. - */ -static void destroy_most_aim_obj(struct most_aim_obj *p) -{ - kobject_put(&p->kobj); -} - -/* ___ ___ - * ___C O R E___ - */ - -/** - * Instantiation of the MOST bus - */ -static struct bus_type most_bus = { - .name = "most", -}; - -/** - * Instantiation of the core driver - */ -static struct device_driver mostcore = { - .name = "mostcore", - .bus = &most_bus, -}; - -static inline void trash_mbo(struct mbo *mbo) -{ - unsigned long flags; - struct most_c_obj *c = mbo->context; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_add(&mbo->list, &c->trash_fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); -} - -static bool hdm_mbo_ready(struct most_c_obj *c) -{ - bool empty; - - if (c->enqueue_halt) - return false; - - spin_lock_irq(&c->fifo_lock); - empty = list_empty(&c->halt_fifo); - spin_unlock_irq(&c->fifo_lock); - - return !empty; -} - -static void nq_hdm_mbo(struct mbo *mbo) -{ - unsigned long flags; - struct most_c_obj *c = mbo->context; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_add_tail(&mbo->list, &c->halt_fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - wake_up_interruptible(&c->hdm_fifo_wq); -} - -static int hdm_enqueue_thread(void *data) -{ - struct most_c_obj *c = data; - struct mbo *mbo; - int ret; - typeof(c->iface->enqueue) enqueue = c->iface->enqueue; - - while (likely(!kthread_should_stop())) { - wait_event_interruptible(c->hdm_fifo_wq, - hdm_mbo_ready(c) || - kthread_should_stop()); - - mutex_lock(&c->nq_mutex); - spin_lock_irq(&c->fifo_lock); - if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) { - spin_unlock_irq(&c->fifo_lock); - mutex_unlock(&c->nq_mutex); - continue; - } - - mbo = list_pop_mbo(&c->halt_fifo); - spin_unlock_irq(&c->fifo_lock); - - if (c->cfg.direction == MOST_CH_RX) - mbo->buffer_length = c->cfg.buffer_size; - - ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo); - mutex_unlock(&c->nq_mutex); - - if (unlikely(ret)) { - pr_err("hdm enqueue failed\n"); - nq_hdm_mbo(mbo); - c->hdm_enqueue_task = NULL; - return 0; - } - } - - return 0; -} - -static int run_enqueue_thread(struct most_c_obj *c, int channel_id) -{ - struct task_struct *task = - kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d", - channel_id); - - if (IS_ERR(task)) - return PTR_ERR(task); - - c->hdm_enqueue_task = task; - return 0; -} - -/** - * arm_mbo - recycle MBO for further usage - * @mbo: buffer object - * - * This puts an MBO back to the list to have it ready for up coming - * tx transactions. - * - * In case the MBO belongs to a channel that recently has been - * poisoned, the MBO is scheduled to be trashed. - * Calls the completion handler of an attached AIM. - */ -static void arm_mbo(struct mbo *mbo) -{ - unsigned long flags; - struct most_c_obj *c; - - BUG_ON((!mbo) || (!mbo->context)); - c = mbo->context; - - if (c->is_poisoned) { - trash_mbo(mbo); - return; - } - - spin_lock_irqsave(&c->fifo_lock, flags); - ++*mbo->num_buffers_ptr; - list_add_tail(&mbo->list, &c->fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - - if (c->aim0.refs && c->aim0.ptr->tx_completion) - c->aim0.ptr->tx_completion(c->iface, c->channel_id); - - if (c->aim1.refs && c->aim1.ptr->tx_completion) - c->aim1.ptr->tx_completion(c->iface, c->channel_id); -} - -/** - * arm_mbo_chain - helper function that arms an MBO chain for the HDM - * @c: pointer to interface channel - * @dir: direction of the channel - * @compl: pointer to completion function - * - * This allocates buffer objects including the containing DMA coherent - * buffer and puts them in the fifo. - * Buffers of Rx channels are put in the kthread fifo, hence immediately - * submitted to the HDM. - * - * Returns the number of allocated and enqueued MBOs. - */ -static int arm_mbo_chain(struct most_c_obj *c, int dir, - void (*compl)(struct mbo *)) -{ - unsigned int i; - int retval; - struct mbo *mbo; - u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; - - atomic_set(&c->mbo_nq_level, 0); - - for (i = 0; i < c->cfg.num_buffers; i++) { - mbo = kzalloc(sizeof(*mbo), GFP_KERNEL); - if (!mbo) { - retval = i; - goto _exit; - } - mbo->context = c; - mbo->ifp = c->iface; - mbo->hdm_channel_id = c->channel_id; - mbo->virt_address = dma_alloc_coherent(NULL, - coherent_buf_size, - &mbo->bus_address, - GFP_KERNEL); - if (!mbo->virt_address) { - pr_info("WARN: No DMA coherent buffer.\n"); - retval = i; - goto _error1; - } - mbo->complete = compl; - mbo->num_buffers_ptr = &dummy_num_buffers; - if (dir == MOST_CH_RX) { - nq_hdm_mbo(mbo); - atomic_inc(&c->mbo_nq_level); - } else { - arm_mbo(mbo); - } - } - return i; - -_error1: - kfree(mbo); -_exit: - return retval; -} - -/** - * most_submit_mbo - submits an MBO to fifo - * @mbo: pointer to the MBO - */ -void most_submit_mbo(struct mbo *mbo) -{ - if (WARN_ONCE(!mbo || !mbo->context, - "bad mbo or missing channel reference\n")) - return; - - nq_hdm_mbo(mbo); -} -EXPORT_SYMBOL_GPL(most_submit_mbo); - -/** - * most_write_completion - write completion handler - * @mbo: pointer to MBO - * - * This recycles the MBO for further usage. In case the channel has been - * poisoned, the MBO is scheduled to be trashed. - */ -static void most_write_completion(struct mbo *mbo) -{ - struct most_c_obj *c; - - BUG_ON((!mbo) || (!mbo->context)); - - c = mbo->context; - if (mbo->status == MBO_E_INVAL) - pr_info("WARN: Tx MBO status: invalid\n"); - if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) - trash_mbo(mbo); - else - arm_mbo(mbo); -} - -/** - * get_channel_by_iface - get pointer to channel object - * @iface: pointer to interface instance - * @id: channel ID - * - * This retrieves a pointer to a channel of the given interface and channel ID. - */ -static struct -most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) -{ - struct most_inst_obj *i; - - if (unlikely(!iface)) { - pr_err("Bad interface\n"); - return NULL; - } - if (unlikely((id < 0) || (id >= iface->num_channels))) { - pr_err("Channel index (%d) out of range\n", id); - return NULL; - } - i = iface->priv; - if (unlikely(!i)) { - pr_err("interface is not registered\n"); - return NULL; - } - return i->channel[id]; -} - -int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) -{ - struct most_c_obj *c = get_channel_by_iface(iface, id); - unsigned long flags; - int empty; - - if (unlikely(!c)) - return -EINVAL; - - if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || - (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) - return 0; - - spin_lock_irqsave(&c->fifo_lock, flags); - empty = list_empty(&c->fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - return !empty; -} -EXPORT_SYMBOL_GPL(channel_has_mbo); - -/** - * most_get_mbo - get pointer to an MBO of pool - * @iface: pointer to interface instance - * @id: channel ID - * - * This attempts to get a free buffer out of the channel fifo. - * Returns a pointer to MBO on success or NULL otherwise. - */ -struct mbo *most_get_mbo(struct most_interface *iface, int id, - struct most_aim *aim) -{ - struct mbo *mbo; - struct most_c_obj *c; - unsigned long flags; - int *num_buffers_ptr; - - c = get_channel_by_iface(iface, id); - if (unlikely(!c)) - return NULL; - - if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || - (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) - return NULL; - - if (aim == c->aim0.ptr) - num_buffers_ptr = &c->aim0.num_buffers; - else if (aim == c->aim1.ptr) - num_buffers_ptr = &c->aim1.num_buffers; - else - num_buffers_ptr = &dummy_num_buffers; - - spin_lock_irqsave(&c->fifo_lock, flags); - if (list_empty(&c->fifo)) { - spin_unlock_irqrestore(&c->fifo_lock, flags); - return NULL; - } - mbo = list_pop_mbo(&c->fifo); - --*num_buffers_ptr; - spin_unlock_irqrestore(&c->fifo_lock, flags); - - mbo->num_buffers_ptr = num_buffers_ptr; - mbo->buffer_length = c->cfg.buffer_size; - return mbo; -} -EXPORT_SYMBOL_GPL(most_get_mbo); - -/** - * most_put_mbo - return buffer to pool - * @mbo: buffer object - */ -void most_put_mbo(struct mbo *mbo) -{ - struct most_c_obj *c = mbo->context; - - if (c->cfg.direction == MOST_CH_TX) { - arm_mbo(mbo); - return; - } - nq_hdm_mbo(mbo); - atomic_inc(&c->mbo_nq_level); -} -EXPORT_SYMBOL_GPL(most_put_mbo); - -/** - * most_read_completion - read completion handler - * @mbo: pointer to MBO - * - * This function is called by the HDM when data has been received from the - * hardware and copied to the buffer of the MBO. - * - * In case the channel has been poisoned it puts the buffer in the trash queue. - * Otherwise, it passes the buffer to an AIM for further processing. - */ -static void most_read_completion(struct mbo *mbo) -{ - struct most_c_obj *c = mbo->context; - - if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) { - trash_mbo(mbo); - return; - } - - if (mbo->status == MBO_E_INVAL) { - nq_hdm_mbo(mbo); - atomic_inc(&c->mbo_nq_level); - return; - } - - if (atomic_sub_and_test(1, &c->mbo_nq_level)) - c->is_starving = 1; - - if (c->aim0.refs && c->aim0.ptr->rx_completion && - c->aim0.ptr->rx_completion(mbo) == 0) - return; - - if (c->aim1.refs && c->aim1.ptr->rx_completion && - c->aim1.ptr->rx_completion(mbo) == 0) - return; - - most_put_mbo(mbo); -} - -/** - * most_start_channel - prepares a channel for communication - * @iface: pointer to interface instance - * @id: channel ID - * - * This prepares the channel for usage. Cross-checks whether the - * channel's been properly configured. - * - * Returns 0 on success or error code otherwise. - */ -int most_start_channel(struct most_interface *iface, int id, - struct most_aim *aim) -{ - int num_buffer; - int ret; - struct most_c_obj *c = get_channel_by_iface(iface, id); - - if (unlikely(!c)) - return -EINVAL; - - mutex_lock(&c->start_mutex); - if (c->aim0.refs + c->aim1.refs > 0) - goto out; /* already started by other aim */ - - if (!try_module_get(iface->mod)) { - pr_info("failed to acquire HDM lock\n"); - mutex_unlock(&c->start_mutex); - return -ENOLCK; - } - - c->cfg.extra_len = 0; - if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { - pr_info("channel configuration failed. Go check settings...\n"); - ret = -EINVAL; - goto error; - } - - init_waitqueue_head(&c->hdm_fifo_wq); - - if (c->cfg.direction == MOST_CH_RX) - num_buffer = arm_mbo_chain(c, c->cfg.direction, - most_read_completion); - else - num_buffer = arm_mbo_chain(c, c->cfg.direction, - most_write_completion); - if (unlikely(!num_buffer)) { - pr_info("failed to allocate memory\n"); - ret = -ENOMEM; - goto error; - } - - ret = run_enqueue_thread(c, id); - if (ret) - goto error; - - c->is_starving = 0; - c->aim0.num_buffers = c->cfg.num_buffers / 2; - c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers; - atomic_set(&c->mbo_ref, num_buffer); - -out: - if (aim == c->aim0.ptr) - c->aim0.refs++; - if (aim == c->aim1.ptr) - c->aim1.refs++; - mutex_unlock(&c->start_mutex); - return 0; - -error: - module_put(iface->mod); - mutex_unlock(&c->start_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(most_start_channel); - -/** - * most_stop_channel - stops a running channel - * @iface: pointer to interface instance - * @id: channel ID - */ -int most_stop_channel(struct most_interface *iface, int id, - struct most_aim *aim) -{ - struct most_c_obj *c; - - if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { - pr_err("Bad interface or index out of range\n"); - return -EINVAL; - } - c = get_channel_by_iface(iface, id); - if (unlikely(!c)) - return -EINVAL; - - mutex_lock(&c->start_mutex); - if (c->aim0.refs + c->aim1.refs >= 2) - goto out; - - if (c->hdm_enqueue_task) - kthread_stop(c->hdm_enqueue_task); - c->hdm_enqueue_task = NULL; - - if (iface->mod) - module_put(iface->mod); - - c->is_poisoned = true; - if (c->iface->poison_channel(c->iface, c->channel_id)) { - pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id, - c->iface->description); - mutex_unlock(&c->start_mutex); - return -EAGAIN; - } - flush_trash_fifo(c); - flush_channel_fifos(c); - -#ifdef CMPL_INTERRUPTIBLE - if (wait_for_completion_interruptible(&c->cleanup)) { - pr_info("Interrupted while clean up ch %d\n", c->channel_id); - mutex_unlock(&c->start_mutex); - return -EINTR; - } -#else - wait_for_completion(&c->cleanup); -#endif - c->is_poisoned = false; - -out: - if (aim == c->aim0.ptr) - c->aim0.refs--; - if (aim == c->aim1.ptr) - c->aim1.refs--; - mutex_unlock(&c->start_mutex); - return 0; -} -EXPORT_SYMBOL_GPL(most_stop_channel); - -/** - * most_register_aim - registers an AIM (driver) with the core - * @aim: instance of AIM to be registered - */ -int most_register_aim(struct most_aim *aim) -{ - struct most_aim_obj *aim_obj; - - if (!aim) { - pr_err("Bad driver\n"); - return -EINVAL; - } - aim_obj = create_most_aim_obj(aim->name); - if (!aim_obj) { - pr_info("failed to alloc driver object\n"); - return -ENOMEM; - } - aim_obj->driver = aim; - aim->context = aim_obj; - pr_info("registered new application interfacing module %s\n", - aim->name); - list_add_tail(&aim_obj->list, &aim_list); - return 0; -} -EXPORT_SYMBOL_GPL(most_register_aim); - -/** - * most_deregister_aim - deregisters an AIM (driver) with the core - * @aim: AIM to be removed - */ -int most_deregister_aim(struct most_aim *aim) -{ - struct most_aim_obj *aim_obj; - struct most_c_obj *c, *tmp; - struct most_inst_obj *i, *i_tmp; - - if (!aim) { - pr_err("Bad driver\n"); - return -EINVAL; - } - - aim_obj = aim->context; - if (!aim_obj) { - pr_info("driver not registered.\n"); - return -EINVAL; - } - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (c->aim0.ptr == aim || c->aim1.ptr == aim) - aim->disconnect_channel( - c->iface, c->channel_id); - if (c->aim0.ptr == aim) - c->aim0.ptr = NULL; - if (c->aim1.ptr == aim) - c->aim1.ptr = NULL; - } - } - list_del(&aim_obj->list); - destroy_most_aim_obj(aim_obj); - pr_info("deregistering application interfacing module %s\n", aim->name); - return 0; -} -EXPORT_SYMBOL_GPL(most_deregister_aim); - -/** - * most_register_interface - registers an interface with core - * @iface: pointer to the instance of the interface description. - * - * Allocates and initializes a new interface instance and all of its channels. - * Returns a pointer to kobject or an error pointer. - */ -struct kobject *most_register_interface(struct most_interface *iface) -{ - unsigned int i; - int id; - char name[STRING_SIZE]; - char channel_name[STRING_SIZE]; - struct most_c_obj *c; - struct most_inst_obj *inst; - - if (!iface || !iface->enqueue || !iface->configure || - !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { - pr_err("Bad interface or channel overflow\n"); - return ERR_PTR(-EINVAL); - } - - id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); - if (id < 0) { - pr_info("Failed to alloc mdev ID\n"); - return ERR_PTR(id); - } - snprintf(name, STRING_SIZE, "mdev%d", id); - - inst = create_most_inst_obj(name); - if (!inst) { - pr_info("Failed to allocate interface instance\n"); - ida_simple_remove(&mdev_id, id); - return ERR_PTR(-ENOMEM); - } - - iface->priv = inst; - INIT_LIST_HEAD(&inst->channel_list); - inst->iface = iface; - inst->dev_id = id; - list_add_tail(&inst->list, &instance_list); - - for (i = 0; i < iface->num_channels; i++) { - const char *name_suffix = iface->channel_vector[i].name_suffix; - - if (!name_suffix) - snprintf(channel_name, STRING_SIZE, "ch%d", i); - else - snprintf(channel_name, STRING_SIZE, "%s", name_suffix); - - /* this increments the reference count of this instance */ - c = create_most_c_obj(channel_name, &inst->kobj); - if (!c) - goto free_instance; - inst->channel[i] = c; - c->is_starving = 0; - c->iface = iface; - c->inst = inst; - c->channel_id = i; - c->keep_mbo = false; - c->enqueue_halt = false; - c->is_poisoned = false; - c->cfg.direction = 0; - c->cfg.data_type = 0; - c->cfg.num_buffers = 0; - c->cfg.buffer_size = 0; - c->cfg.subbuffer_size = 0; - c->cfg.packets_per_xact = 0; - spin_lock_init(&c->fifo_lock); - INIT_LIST_HEAD(&c->fifo); - INIT_LIST_HEAD(&c->trash_fifo); - INIT_LIST_HEAD(&c->halt_fifo); - init_completion(&c->cleanup); - atomic_set(&c->mbo_ref, 0); - mutex_init(&c->start_mutex); - mutex_init(&c->nq_mutex); - list_add_tail(&c->list, &inst->channel_list); - } - pr_info("registered new MOST device mdev%d (%s)\n", - inst->dev_id, iface->description); - return &inst->kobj; - -free_instance: - pr_info("Failed allocate channel(s)\n"); - list_del(&inst->list); - ida_simple_remove(&mdev_id, id); - destroy_most_inst_obj(inst); - return ERR_PTR(-ENOMEM); -} -EXPORT_SYMBOL_GPL(most_register_interface); - -/** - * most_deregister_interface - deregisters an interface with core - * @iface: pointer to the interface instance description. - * - * Before removing an interface instance from the list, all running - * channels are stopped and poisoned. - */ -void most_deregister_interface(struct most_interface *iface) -{ - struct most_inst_obj *i = iface->priv; - struct most_c_obj *c; - - if (unlikely(!i)) { - pr_info("Bad Interface\n"); - return; - } - pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, - iface->description); - - list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, - c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, - c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; - } - - ida_simple_remove(&mdev_id, i->dev_id); - list_del(&i->list); - destroy_most_inst_obj(i); -} -EXPORT_SYMBOL_GPL(most_deregister_interface); - -/** - * most_stop_enqueue - prevents core from enqueueing MBOs - * @iface: pointer to interface - * @id: channel id - * - * This is called by an HDM that _cannot_ attend to its duties and - * is imminent to get run over by the core. The core is not going to - * enqueue any further packets unless the flagging HDM calls - * most_resume enqueue(). - */ -void most_stop_enqueue(struct most_interface *iface, int id) -{ - struct most_c_obj *c = get_channel_by_iface(iface, id); - - if (!c) - return; - - mutex_lock(&c->nq_mutex); - c->enqueue_halt = true; - mutex_unlock(&c->nq_mutex); -} -EXPORT_SYMBOL_GPL(most_stop_enqueue); - -/** - * most_resume_enqueue - allow core to enqueue MBOs again - * @iface: pointer to interface - * @id: channel id - * - * This clears the enqueue halt flag and enqueues all MBOs currently - * sitting in the wait fifo. - */ -void most_resume_enqueue(struct most_interface *iface, int id) -{ - struct most_c_obj *c = get_channel_by_iface(iface, id); - - if (!c) - return; - - mutex_lock(&c->nq_mutex); - c->enqueue_halt = false; - mutex_unlock(&c->nq_mutex); - - wake_up_interruptible(&c->hdm_fifo_wq); -} -EXPORT_SYMBOL_GPL(most_resume_enqueue); - -static int __init most_init(void) -{ - int err; - - pr_info("init()\n"); - INIT_LIST_HEAD(&instance_list); - INIT_LIST_HEAD(&aim_list); - ida_init(&mdev_id); - - err = bus_register(&most_bus); - if (err) { - pr_info("Cannot register most bus\n"); - return err; - } - - most_class = class_create(THIS_MODULE, "most"); - if (IS_ERR(most_class)) { - pr_info("No udev support.\n"); - err = PTR_ERR(most_class); - goto exit_bus; - } - - err = driver_register(&mostcore); - if (err) { - pr_info("Cannot register core driver\n"); - goto exit_class; - } - - core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(core_dev)) { - err = PTR_ERR(core_dev); - goto exit_driver; - } - - most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); - if (!most_aim_kset) { - err = -ENOMEM; - goto exit_class_container; - } - - most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); - if (!most_inst_kset) { - err = -ENOMEM; - goto exit_driver_kset; - } - - return 0; - -exit_driver_kset: - kset_unregister(most_aim_kset); -exit_class_container: - device_destroy(most_class, 0); -exit_driver: - driver_unregister(&mostcore); -exit_class: - class_destroy(most_class); -exit_bus: - bus_unregister(&most_bus); - return err; -} - -static void __exit most_exit(void) -{ - struct most_inst_obj *i, *i_tmp; - struct most_aim_obj *d, *d_tmp; - - pr_info("exit core module\n"); - list_for_each_entry_safe(d, d_tmp, &aim_list, list) { - destroy_most_aim_obj(d); - } - - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_del(&i->list); - destroy_most_inst_obj(i); - } - kset_unregister(most_inst_kset); - kset_unregister(most_aim_kset); - device_destroy(most_class, 0); - driver_unregister(&mostcore); - class_destroy(most_class); - bus_unregister(&most_bus); - ida_destroy(&mdev_id); -} - -module_init(most_init); -module_exit(most_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); -MODULE_DESCRIPTION("Core module of stacked MOST Linux driver"); diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/net/Kconfig index 4c66b24cf73c..795330ba94ef 100644 --- a/drivers/staging/most/aim-network/Kconfig +++ b/drivers/staging/most/net/Kconfig @@ -2,12 +2,12 @@ # MOST Networking configuration # -config AIM_NETWORK - tristate "Networking AIM" +config MOST_NET + tristate "Net" depends on NET ---help--- Say Y here if you want to commumicate via a networking device. To compile this driver as a module, choose M here: the - module will be called aim_network. + module will be called most_net. diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile new file mode 100644 index 000000000000..54500aa77be8 --- /dev/null +++ b/drivers/staging/most/net/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_NET) += most_net.o + +most_net-objs := net.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/net/net.c index 936f013c350e..33606584e50e 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/net/net.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Networking AIM - Networking Application Interface Module for MostCore + * net.c - Networking component for Mostcore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -21,7 +15,7 @@ #include <linux/list.h> #include <linux/wait.h> #include <linux/kobject.h> -#include "mostcore.h" +#include "most/core.h" #define MEP_HDR_LEN 8 #define MDP_HDR_LEN 16 @@ -74,7 +68,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ -static struct most_aim aim; +static struct core_component comp; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) { @@ -184,15 +178,15 @@ static int most_nd_open(struct net_device *dev) mutex_lock(&probe_disc_mt); - if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) { + if (most_start_channel(nd->iface, nd->rx.ch_id, &comp)) { netdev_err(dev, "most_start_channel() failed\n"); ret = -EBUSY; goto unlock; } - if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) { + if (most_start_channel(nd->iface, nd->tx.ch_id, &comp)) { netdev_err(dev, "most_start_channel() failed\n"); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); + most_stop_channel(nd->iface, nd->rx.ch_id, &comp); ret = -EBUSY; goto unlock; } @@ -218,8 +212,8 @@ static int most_nd_stop(struct net_device *dev) netif_stop_queue(dev); if (nd->iface->request_netinfo) nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); - most_stop_channel(nd->iface, nd->tx.ch_id, &aim); + most_stop_channel(nd->iface, nd->rx.ch_id, &comp); + most_stop_channel(nd->iface, nd->tx.ch_id, &comp); return 0; } @@ -231,7 +225,7 @@ static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb, struct mbo *mbo; int ret; - mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim); + mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &comp); if (!mbo) { netif_stop_queue(dev); @@ -296,9 +290,8 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) return nd; } -static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, - struct kobject *parent, char *name) +static int comp_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, char *name) { struct net_dev_context *nd; struct net_dev_channel *ch; @@ -353,8 +346,8 @@ unlock: return ret; } -static int aim_disconnect_channel(struct most_interface *iface, - int channel_idx) +static int comp_disconnect_channel(struct most_interface *iface, + int channel_idx) { struct net_dev_context *nd; struct net_dev_channel *ch; @@ -400,8 +393,8 @@ unlock: return ret; } -static int aim_resume_tx_channel(struct most_interface *iface, - int channel_idx) +static int comp_resume_tx_channel(struct most_interface *iface, + int channel_idx) { struct net_dev_context *nd; @@ -419,7 +412,7 @@ put_nd: return 0; } -static int aim_rx_data(struct mbo *mbo) +static int comp_rx_data(struct mbo *mbo) { const u32 zero = 0; struct net_dev_context *nd; @@ -501,24 +494,24 @@ put_nd: return ret; } -static struct most_aim aim = { - .name = "networking", - .probe_channel = aim_probe_channel, - .disconnect_channel = aim_disconnect_channel, - .tx_completion = aim_resume_tx_channel, - .rx_completion = aim_rx_data, +static struct core_component comp = { + .name = "net", + .probe_channel = comp_probe_channel, + .disconnect_channel = comp_disconnect_channel, + .tx_completion = comp_resume_tx_channel, + .rx_completion = comp_rx_data, }; static int __init most_net_init(void) { spin_lock_init(&list_lock); mutex_init(&probe_disc_mt); - return most_register_aim(&aim); + return most_register_component(&comp); } static void __exit most_net_exit(void) { - most_deregister_aim(&aim); + most_deregister_component(&comp); } /** @@ -564,4 +557,4 @@ module_init(most_net_init); module_exit(most_net_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); -MODULE_DESCRIPTION("Networking Application Interface Module for MostCore"); +MODULE_DESCRIPTION("Networking Component Module for Mostcore"); diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/sound/Kconfig index 3194c219ff14..115262a58a42 100644 --- a/drivers/staging/most/aim-sound/Kconfig +++ b/drivers/staging/most/sound/Kconfig @@ -2,12 +2,12 @@ # MOST ALSA configuration # -config AIM_SOUND - tristate "ALSA AIM" +config MOST_SOUND + tristate "Sound" depends on SND select SND_PCM ---help--- Say Y here if you want to commumicate via ALSA/sound devices. To compile this driver as a module, choose M here: the - module will be called aim_sound. + module will be called most_sound. diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile new file mode 100644 index 000000000000..eee8774e38cb --- /dev/null +++ b/drivers/staging/most/sound/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_SOUND) += most_sound.o + +most_sound-objs := sound.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/sound/sound.c index ea1366a44008..83cec21c85b8 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * sound.c - Audio Application Interface Module for Mostcore + * sound.c - Sound component for Mostcore * * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -22,12 +16,12 @@ #include <sound/pcm_params.h> #include <linux/sched.h> #include <linux/kthread.h> -#include <mostcore.h> +#include <most/core.h> #define DRIVER_NAME "sound" static struct list_head dev_list; -static struct most_aim audio_aim; +static struct core_component comp; /** * struct channel - private structure to keep channel specific data @@ -240,7 +234,7 @@ static int playback_thread(void *data) kthread_should_stop() || (channel->is_stream_running && (mbo = most_get_mbo(channel->iface, channel->id, - &audio_aim)))); + &comp)))); if (!mbo) continue; @@ -283,7 +277,7 @@ static int pcm_open(struct snd_pcm_substream *substream) } } - if (most_start_channel(channel->iface, channel->id, &audio_aim)) { + if (most_start_channel(channel->iface, channel->id, &comp)) { pr_err("most_start_channel() failed!\n"); if (cfg->direction == MOST_CH_TX) kthread_stop(channel->playback_task); @@ -310,7 +304,7 @@ static int pcm_close(struct snd_pcm_substream *substream) if (channel->cfg->direction == MOST_CH_TX) kthread_stop(channel->playback_task); - most_stop_channel(channel->iface, channel->id, &audio_aim); + most_stop_channel(channel->iface, channel->id, &comp); return 0; } @@ -545,7 +539,6 @@ error: * @iface: pointer to interface instance * @channel_id: channel index/ID * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) * @arg_list: string that provides the name of the device to be created in /dev * plus the desired audio resolution * @@ -555,7 +548,7 @@ error: */ static int audio_probe_channel(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, - struct kobject *parent, char *arg_list) + char *arg_list) { struct channel *channel; struct snd_card *card; @@ -724,9 +717,9 @@ static int audio_tx_completion(struct most_interface *iface, int channel_id) } /** - * Initialization of the struct most_aim + * Initialization of the struct core_component */ -static struct most_aim audio_aim = { +static struct core_component comp = { .name = DRIVER_NAME, .probe_channel = audio_probe_channel, .disconnect_channel = audio_disconnect_channel, @@ -740,7 +733,7 @@ static int __init audio_init(void) INIT_LIST_HEAD(&dev_list); - return most_register_aim(&audio_aim); + return most_register_component(&comp); } static void __exit audio_exit(void) @@ -754,7 +747,7 @@ static void __exit audio_exit(void) snd_card_free(channel->card); } - most_deregister_aim(&audio_aim); + most_deregister_component(&comp); } module_init(audio_init); @@ -762,4 +755,4 @@ module_exit(audio_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); -MODULE_DESCRIPTION("Audio Application Interface Module for MostCore"); +MODULE_DESCRIPTION("Sound Component Module for Mostcore"); diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/usb/Kconfig index 487f1f34776c..ebbdb573a9a6 100644 --- a/drivers/staging/most/hdm-usb/Kconfig +++ b/drivers/staging/most/usb/Kconfig @@ -2,13 +2,12 @@ # MOST USB configuration # -config HDM_USB - tristate "USB HDM" +config MOST_USB + tristate "USB" depends on USB && NET - ---help--- Say Y here if you want to connect via USB to network tranceiver. This device driver depends on the networking AIM. To compile this driver as a module, choose M here: the - module will be called hdm_usb. + module will be called most_usb. diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile new file mode 100644 index 000000000000..18d28cba4fbf --- /dev/null +++ b/drivers/staging/most/usb/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_USB) += most_usb.o + +most_usb-objs := usb.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/usb/usb.c index 667dacac81f0..8d23075ae165 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/usb/usb.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * hdm_usb.c - Hardware dependent module for USB + * usb.c - Hardware dependent module for USB * * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -29,7 +23,7 @@ #include <linux/dma-mapping.h> #include <linux/etherdevice.h> #include <linux/uaccess.h> -#include "mostcore.h" +#include "most/core.h" #define USB_MTU 512 #define NO_ISOCHRONOUS_URB 0 @@ -70,12 +64,12 @@ * @reg_addr: register address for arbitrary DCI access */ struct most_dci_obj { - struct kobject kobj; + struct device dev; struct usb_device *usb_device; u16 reg_addr; }; -#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) +#define to_dci_obj(p) container_of(p, struct most_dci_obj, dev) struct most_dev; @@ -90,7 +84,6 @@ struct clear_hold_work { /** * struct most_dev - holds all usb interface specific stuff - * @parent: parent object in sysfs * @usb_device: pointer to usb device * @iface: hardware interface * @cap: channel capabilities @@ -108,7 +101,6 @@ struct clear_hold_work { * @poll_work_obj: work for polling link status */ struct most_dev { - struct kobject *parent; struct usb_device *usb_device; struct most_interface iface; struct most_channel_capability *cap; @@ -817,6 +809,21 @@ static void wq_clear_halt(struct work_struct *wq_obj) if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); + /* If the functional Stall condition has been set on an + * asynchronous rx channel, we need to clear the tx channel + * too, since the hardware runs its clean-up sequence on both + * channels, as they are physically one on the network. + * + * The USB interface that exposes the asynchronous channels + * contains always two endpoints, and two only. + */ + if (mdev->conf[channel].data_type == MOST_CH_ASYNC && + mdev->conf[channel].direction == MOST_CH_RX) { + int peer = 1 - channel; + int snd_pipe = usb_sndbulkpipe(mdev->usb_device, + mdev->ep_address[peer]); + usb_clear_halt(mdev->usb_device, snd_pipe); + } mdev->is_channel_healthy[channel] = true; most_resume_enqueue(&mdev->iface, channel); mutex_unlock(&mdev->io_mutex); @@ -840,94 +847,6 @@ static const struct usb_device_id usbid[] = { { } /* Terminating entry */ }; -#define MOST_DCI_RO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0444, show_value, NULL) - -#define MOST_DCI_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0644, show_value, store_value) - -#define MOST_DCI_WO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0200, NULL, store_value) - -/** - * struct most_dci_attribute - to access the attributes of a dci object - * @attr: attributes of a dci object - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_dci_attribute { - struct attribute attr; - ssize_t (*show)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - char *buf); - ssize_t (*store)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) - -/** - * dci_attr_show - show function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->show) - return -EIO; - - return dci_attr->show(dci_obj, dci_attr, buf); -} - -/** - * dci_attr_store - store function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t dci_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->store) - return -EIO; - - return dci_attr->store(dci_obj, dci_attr, buf, len); -} - -static const struct sysfs_ops most_dci_sysfs_ops = { - .show = dci_attr_show, - .store = dci_attr_store, -}; - -/** - * most_dci_release - release function for dci object - * @kobj: pointer to kobject - * - * This frees the memory allocated for the dci object - */ -static void most_dci_release(struct kobject *kobj) -{ - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - kfree(dci_obj); -} - struct regs { const char *name; u16 reg; @@ -968,10 +887,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size, #define get_static_reg_addr(regs, name, reg_addr) \ get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) -static ssize_t show_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, char *buf) +static ssize_t value_show(struct device *dev, struct device_attribute *attr, + char *buf) { const char *name = attr->attr.name; + struct most_dci_obj *dci_obj = to_dci_obj(dev); u16 val; u16 reg_addr; int err; @@ -992,13 +912,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, return snprintf(buf, PAGE_SIZE, "%04x\n", val); } -static ssize_t store_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, +static ssize_t value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u16 val; u16 reg_addr; const char *name = attr->attr.name; + struct most_dci_obj *dci_obj = to_dci_obj(dev); struct usb_device *usb_dev = dci_obj->usb_device; int err = kstrtou16(buf, 16, &val); @@ -1025,86 +945,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, return count; } -static MOST_DCI_RO_ATTR(ni_state); -static MOST_DCI_RO_ATTR(packet_bandwidth); -static MOST_DCI_RO_ATTR(node_address); -static MOST_DCI_RO_ATTR(node_position); -static MOST_DCI_WO_ATTR(sync_ep); -static MOST_DCI_ATTR(mep_filter); -static MOST_DCI_ATTR(mep_hash0); -static MOST_DCI_ATTR(mep_hash1); -static MOST_DCI_ATTR(mep_hash2); -static MOST_DCI_ATTR(mep_hash3); -static MOST_DCI_ATTR(mep_eui48_hi); -static MOST_DCI_ATTR(mep_eui48_mi); -static MOST_DCI_ATTR(mep_eui48_lo); -static MOST_DCI_ATTR(arb_address); -static MOST_DCI_ATTR(arb_value); - -/** - * most_dci_def_attrs - array of default attribute files of the dci object - */ -static struct attribute *most_dci_def_attrs[] = { - &most_dci_attr_ni_state.attr, - &most_dci_attr_packet_bandwidth.attr, - &most_dci_attr_node_address.attr, - &most_dci_attr_node_position.attr, - &most_dci_attr_sync_ep.attr, - &most_dci_attr_mep_filter.attr, - &most_dci_attr_mep_hash0.attr, - &most_dci_attr_mep_hash1.attr, - &most_dci_attr_mep_hash2.attr, - &most_dci_attr_mep_hash3.attr, - &most_dci_attr_mep_eui48_hi.attr, - &most_dci_attr_mep_eui48_mi.attr, - &most_dci_attr_mep_eui48_lo.attr, - &most_dci_attr_arb_address.attr, - &most_dci_attr_arb_value.attr, +static DEVICE_ATTR(ni_state, 0444, value_show, NULL); +static DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL); +static DEVICE_ATTR(node_address, 0444, value_show, NULL); +static DEVICE_ATTR(node_position, 0444, value_show, NULL); +static DEVICE_ATTR(sync_ep, 0200, NULL, value_store); +static DEVICE_ATTR(mep_filter, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash0, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash1, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash2, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash3, 0644, value_show, value_store); +static DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store); +static DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store); +static DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store); +static DEVICE_ATTR(arb_address, 0644, value_show, value_store); +static DEVICE_ATTR(arb_value, 0644, value_show, value_store); + +static struct attribute *dci_attrs[] = { + &dev_attr_ni_state.attr, + &dev_attr_packet_bandwidth.attr, + &dev_attr_node_address.attr, + &dev_attr_node_position.attr, + &dev_attr_sync_ep.attr, + &dev_attr_mep_filter.attr, + &dev_attr_mep_hash0.attr, + &dev_attr_mep_hash1.attr, + &dev_attr_mep_hash2.attr, + &dev_attr_mep_hash3.attr, + &dev_attr_mep_eui48_hi.attr, + &dev_attr_mep_eui48_mi.attr, + &dev_attr_mep_eui48_lo.attr, + &dev_attr_arb_address.attr, + &dev_attr_arb_value.attr, NULL, }; -/** - * DCI ktype - */ -static struct kobj_type most_dci_ktype = { - .sysfs_ops = &most_dci_sysfs_ops, - .release = most_dci_release, - .default_attrs = most_dci_def_attrs, +static struct attribute_group dci_attr_group = { + .attrs = dci_attrs, }; -/** - * create_most_dci_obj - allocates a dci object - * @parent: parent kobject - * - * This creates a dci object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct -most_dci_obj *create_most_dci_obj(struct kobject *parent) -{ - struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); - int retval; - - if (!most_dci) - return NULL; - - retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent, - "dci"); - if (retval) { - kobject_put(&most_dci->kobj); - return NULL; - } - return most_dci; -} - -/** - * destroy_most_dci_obj - DCI object release function - * @p: pointer to dci object - */ -static void destroy_most_dci_obj(struct most_dci_obj *p) -{ - kobject_put(&p->kobj); -} +static const struct attribute_group *dci_attr_groups[] = { + &dci_attr_group, + NULL, +}; /** * hdm_probe - probe function of USB device driver @@ -1168,8 +1051,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) goto exit_free1; mdev->iface.channel_vector = mdev->cap; - mdev->iface.priv = NULL; - mdev->ep_address = kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL); if (!mdev->ep_address) @@ -1217,20 +1098,15 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) usb_dev->config->desc.bConfigurationValue, usb_iface_desc->desc.bInterfaceNumber); - mdev->parent = most_register_interface(&mdev->iface); - if (IS_ERR(mdev->parent)) { - ret = PTR_ERR(mdev->parent); + ret = most_register_interface(&mdev->iface); + if (ret) goto exit_free4; - } mutex_lock(&mdev->io_mutex); if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { - /* this increments the reference count of the instance - * object of the core - */ - mdev->dci = create_most_dci_obj(mdev->parent); + mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL); if (!mdev->dci) { mutex_unlock(&mdev->io_mutex); most_deregister_interface(&mdev->iface); @@ -1238,12 +1114,21 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) goto exit_free4; } - kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); + mdev->dci->dev.init_name = "dci"; + mdev->dci->dev.parent = &mdev->iface.dev; + mdev->dci->dev.groups = dci_attr_groups; + if (device_register(&mdev->dci->dev)) { + mutex_unlock(&mdev->io_mutex); + most_deregister_interface(&mdev->iface); + ret = -ENOMEM; + goto exit_free5; + } mdev->dci->usb_device = mdev->usb_device; } mutex_unlock(&mdev->io_mutex); return 0; - +exit_free5: + kfree(mdev->dci); exit_free4: kfree(mdev->busy_urbs); exit_free3: @@ -1283,7 +1168,8 @@ static void hdm_disconnect(struct usb_interface *interface) del_timer_sync(&mdev->link_stat_timer); cancel_work_sync(&mdev->poll_work_obj); - destroy_most_dci_obj(mdev->dci); + device_unregister(&mdev->dci->dev); + kfree(mdev->dci); most_deregister_interface(&mdev->iface); kfree(mdev->busy_urbs); diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/video/Kconfig index d70eaaf0936c..ce6af4f951a6 100644 --- a/drivers/staging/most/aim-v4l2/Kconfig +++ b/drivers/staging/most/video/Kconfig @@ -2,11 +2,11 @@ # MOST V4L2 configuration # -config AIM_V4L2 - tristate "V4L2 AIM" +config MOST_VIDEO + tristate "Video" depends on VIDEO_V4L2 ---help--- Say Y here if you want to commumicate via Video 4 Linux. To compile this driver as a module, choose M here: the - module will be called aim_v4l2.
\ No newline at end of file + module will be called most_video. diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile new file mode 100644 index 000000000000..1c8e520e02a2 --- /dev/null +++ b/drivers/staging/most/video/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_VIDEO) += most_video.o + +most_video-objs := video.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/video/video.c index e0748416aee5..098873851646 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/video/video.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * V4L2 AIM - V4L2 Application Interface Module for MostCore + * video.c - V4L2 component for Mostcore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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 file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -27,11 +21,11 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-fh.h> -#include "mostcore.h" +#include "most/core.h" -#define V4L2_AIM_MAX_INPUT 1 +#define V4L2_CMP_MAX_INPUT 1 -static struct most_aim aim_info; +static struct core_component comp; struct most_video_dev { struct most_interface *iface; @@ -52,7 +46,7 @@ struct most_video_dev { wait_queue_head_t wait_data; }; -struct aim_fh { +struct comp_fh { /* must be the first field of this struct! */ struct v4l2_fh fh; struct most_video_dev *mdev; @@ -72,14 +66,14 @@ static inline struct mbo *get_top_mbo(struct most_video_dev *mdev) return list_first_entry(&mdev->pending_mbos, struct mbo, list); } -static int aim_vdev_open(struct file *filp) +static int comp_vdev_open(struct file *filp) { int ret; struct video_device *vdev = video_devdata(filp); struct most_video_dev *mdev = video_drvdata(filp); - struct aim_fh *fh; + struct comp_fh *fh; - v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_vdev_open()\n"); switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: @@ -104,7 +98,7 @@ static int aim_vdev_open(struct file *filp) v4l2_fh_add(&fh->fh); - ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info); + ret = most_start_channel(mdev->iface, mdev->ch_idx, &comp); if (ret) { v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n"); goto err_rm; @@ -122,13 +116,13 @@ err_dec: return ret; } -static int aim_vdev_close(struct file *filp) +static int comp_vdev_close(struct file *filp) { - struct aim_fh *fh = filp->private_data; + struct comp_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; struct mbo *mbo, *tmp; - v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_vdev_close()\n"); /* * We need to put MBOs back before we call most_stop_channel() @@ -148,7 +142,7 @@ static int aim_vdev_close(struct file *filp) spin_lock_irq(&mdev->list_lock); } spin_unlock_irq(&mdev->list_lock); - most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info); + most_stop_channel(mdev->iface, mdev->ch_idx, &comp); mdev->mute = false; v4l2_fh_del(&fh->fh); @@ -159,10 +153,10 @@ static int aim_vdev_close(struct file *filp) return 0; } -static ssize_t aim_vdev_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos) +static ssize_t comp_vdev_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) { - struct aim_fh *fh = filp->private_data; + struct comp_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; int ret = 0; @@ -209,9 +203,9 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, return ret; } -static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) +static unsigned int comp_vdev_poll(struct file *filp, poll_table *wait) { - struct aim_fh *fh = filp->private_data; + struct comp_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; unsigned int mask = 0; @@ -224,7 +218,7 @@ static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) return mask; } -static void aim_set_format_struct(struct v4l2_format *f) +static void comp_set_format_struct(struct v4l2_format *f) { f->fmt.pix.width = 8; f->fmt.pix.height = 8; @@ -236,8 +230,8 @@ static void aim_set_format_struct(struct v4l2_format *f) f->fmt.pix.priv = 0; } -static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, - struct v4l2_format *format) +static int comp_set_format(struct most_video_dev *mdev, unsigned int cmd, + struct v4l2_format *format) { if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) return -EINVAL; @@ -245,7 +239,7 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, if (cmd == VIDIOC_TRY_FMT) return 0; - aim_set_format_struct(format); + comp_set_format_struct(format); return 0; } @@ -253,12 +247,12 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n"); - strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); + strlcpy(cap->driver, "v4l2_component", sizeof(cap->driver)); strlcpy(cap->card, "MOST", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "%s", mdev->iface->description); @@ -273,7 +267,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index); @@ -292,36 +286,36 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n"); - aim_set_format_struct(f); + comp_set_format_struct(f); return 0; } static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - return aim_set_format(mdev, VIDIOC_TRY_FMT, f); + return comp_set_format(mdev, VIDIOC_TRY_FMT, f); } static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - return aim_set_format(mdev, VIDIOC_S_FMT, f); + return comp_set_format(mdev, VIDIOC_S_FMT, f); } static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n"); @@ -333,10 +327,10 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *input) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - if (input->index >= V4L2_AIM_MAX_INPUT) + if (input->index >= V4L2_CMP_MAX_INPUT) return -EINVAL; strcpy(input->name, "MOST Video"); @@ -350,7 +344,7 @@ static int vidioc_enum_input(struct file *file, void *priv, static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; *i = mdev->ctrl_input; return 0; @@ -358,23 +352,23 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) static int vidioc_s_input(struct file *file, void *priv, unsigned int index) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index); - if (index >= V4L2_AIM_MAX_INPUT) + if (index >= V4L2_CMP_MAX_INPUT) return -EINVAL; mdev->ctrl_input = index; return 0; } -static const struct v4l2_file_operations aim_fops = { +static const struct v4l2_file_operations comp_fops = { .owner = THIS_MODULE, - .open = aim_vdev_open, - .release = aim_vdev_close, - .read = aim_vdev_read, - .poll = aim_vdev_poll, + .open = comp_vdev_open, + .release = comp_vdev_close, + .read = comp_vdev_read, + .poll = comp_vdev_poll, .unlocked_ioctl = video_ioctl2, }; @@ -390,8 +384,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static const struct video_device aim_videodev_template = { - .fops = &aim_fops, +static const struct video_device comp_videodev_template = { + .fops = &comp_fops, .release = video_device_release, .ioctl_ops = &video_ioctl_ops, .tvnorms = V4L2_STD_UNKNOWN, @@ -399,7 +393,7 @@ static const struct video_device aim_videodev_template = { /**************************************************************************/ -static struct most_video_dev *get_aim_dev( +static struct most_video_dev *get_comp_dev( struct most_interface *iface, int channel_idx) { struct most_video_dev *mdev; @@ -416,11 +410,11 @@ static struct most_video_dev *get_aim_dev( return NULL; } -static int aim_rx_data(struct mbo *mbo) +static int comp_rx_data(struct mbo *mbo) { unsigned long flags; struct most_video_dev *mdev = - get_aim_dev(mbo->ifp, mbo->hdm_channel_id); + get_comp_dev(mbo->ifp, mbo->hdm_channel_id); if (!mdev) return -EIO; @@ -437,11 +431,11 @@ static int aim_rx_data(struct mbo *mbo) return 0; } -static int aim_register_videodev(struct most_video_dev *mdev) +static int comp_register_videodev(struct most_video_dev *mdev) { int ret; - v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_register_videodev()\n"); init_waitqueue_head(&mdev->wait_data); @@ -451,7 +445,7 @@ static int aim_register_videodev(struct most_video_dev *mdev) return -ENOMEM; /* Fill the video capture device struct */ - *mdev->vdev = aim_videodev_template; + *mdev->vdev = comp_videodev_template; mdev->vdev->v4l2_dev = &mdev->v4l2_dev; mdev->vdev->lock = &mdev->lock; snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s", @@ -469,14 +463,14 @@ static int aim_register_videodev(struct most_video_dev *mdev) return ret; } -static void aim_unregister_videodev(struct most_video_dev *mdev) +static void comp_unregister_videodev(struct most_video_dev *mdev) { - v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_unregister_videodev()\n"); video_unregister_device(mdev->vdev); } -static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) +static void comp_v4l2_dev_release(struct v4l2_device *v4l2_dev) { struct most_video_dev *mdev = container_of(v4l2_dev, struct most_video_dev, v4l2_dev); @@ -485,14 +479,13 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) kfree(mdev); } -static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, - struct kobject *parent, char *name) +static int comp_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, char *name) { int ret; - struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + struct most_video_dev *mdev = get_comp_dev(iface, channel_idx); - pr_info("aim_probe_channel(%s)\n", name); + pr_info("comp_probe_channel(%s)\n", name); if (mdev) { pr_err("channel already linked\n"); @@ -520,7 +513,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, INIT_LIST_HEAD(&mdev->pending_mbos); mdev->iface = iface; mdev->ch_idx = channel_idx; - mdev->v4l2_dev.release = aim_v4l2_dev_release; + mdev->v4l2_dev.release = comp_v4l2_dev_release; /* Create the v4l2_device */ strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name)); @@ -531,14 +524,14 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, return ret; } - ret = aim_register_videodev(mdev); + ret = comp_register_videodev(mdev); if (ret) goto err_unreg; spin_lock_irq(&list_lock); list_add(&mdev->list, &video_devices); spin_unlock_irq(&list_lock); - v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n"); + v4l2_info(&mdev->v4l2_dev, "comp_probe_channel() done\n"); return 0; err_unreg: @@ -547,48 +540,48 @@ err_unreg: return ret; } -static int aim_disconnect_channel(struct most_interface *iface, - int channel_idx) +static int comp_disconnect_channel(struct most_interface *iface, + int channel_idx) { - struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + struct most_video_dev *mdev = get_comp_dev(iface, channel_idx); if (!mdev) { pr_err("no such channel is linked\n"); return -ENOENT; } - v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_disconnect_channel()\n"); spin_lock_irq(&list_lock); list_del(&mdev->list); spin_unlock_irq(&list_lock); - aim_unregister_videodev(mdev); + comp_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); v4l2_device_put(&mdev->v4l2_dev); return 0; } -static struct most_aim aim_info = { - .name = "v4l", - .probe_channel = aim_probe_channel, - .disconnect_channel = aim_disconnect_channel, - .rx_completion = aim_rx_data, +static struct core_component comp_info = { + .name = "video", + .probe_channel = comp_probe_channel, + .disconnect_channel = comp_disconnect_channel, + .rx_completion = comp_rx_data, }; -static int __init aim_init(void) +static int __init comp_init(void) { spin_lock_init(&list_lock); - return most_register_aim(&aim_info); + return most_register_component(&comp); } -static void __exit aim_exit(void) +static void __exit comp_exit(void) { struct most_video_dev *mdev, *tmp; /* * As the mostcore currently doesn't call disconnect_channel() - * for linked channels while we call most_deregister_aim() + * for linked channels while we call most_deregister_component() * we simulate this call here. * This must be fixed in core. */ @@ -597,20 +590,20 @@ static void __exit aim_exit(void) list_del(&mdev->list); spin_unlock_irq(&list_lock); - aim_unregister_videodev(mdev); + comp_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); v4l2_device_put(&mdev->v4l2_dev); spin_lock_irq(&list_lock); } spin_unlock_irq(&list_lock); - most_deregister_aim(&aim_info); + most_deregister_component(&comp_info); BUG_ON(!list_empty(&video_devices)); } -module_init(aim_init); -module_exit(aim_exit); +module_init(comp_init); +module_exit(comp_exit); -MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore"); +MODULE_DESCRIPTION("V4L2 Component Module for Mostcore"); MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/ncpfs/Kconfig b/drivers/staging/ncpfs/Kconfig new file mode 100644 index 000000000000..c931cf22a1f6 --- /dev/null +++ b/drivers/staging/ncpfs/Kconfig @@ -0,0 +1,108 @@ +# +# NCP Filesystem configuration +# +config NCP_FS + tristate "NCP file system support (to mount NetWare volumes)" + depends on IPX!=n || INET + help + NCP (NetWare Core Protocol) is a protocol that runs over IPX and is + used by Novell NetWare clients to talk to file servers. It is to + IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you + to mount NetWare file server volumes and to access them just like + any other Unix directory. For details, please read the file + <file:Documentation/filesystems/ncpfs.txt> in the kernel source and + the IPX-HOWTO from <http://www.tldp.org/docs.html#howto>. + + You do not have to say Y here if you want your Linux box to act as a + file *server* for Novell NetWare clients. + + General information about how to connect Linux, Windows machines and + Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>. + + To compile this as a module, choose M here: the module will be called + ncpfs. Say N unless you are connected to a Novell network. + +config NCPFS_PACKET_SIGNING + bool "Packet signatures" + depends on NCP_FS + help + NCP allows packets to be signed for stronger security. If you want + security, say Y. Normal users can leave it off. To be able to use + packet signing you must use ncpfs > 2.0.12. + +config NCPFS_IOCTL_LOCKING + bool "Proprietary file locking" + depends on NCP_FS + help + Allows locking of records on remote volumes. Say N unless you have + special applications which are able to utilize this locking scheme. + +config NCPFS_STRONG + bool "Clear remove/delete inhibit when needed" + depends on NCP_FS + help + Allows manipulation of files flagged as Delete or Rename Inhibit. + To use this feature you must mount volumes with the ncpmount + parameter "-s" (ncpfs-2.0.12 and newer). Say Y unless you are not + mounting volumes with -f 444. + +config NCPFS_NFS_NS + bool "Use NFS namespace if available" + depends on NCP_FS + help + Allows you to utilize NFS namespace on NetWare servers. It brings + you case sensitive filenames. Say Y. You can disable it at + mount-time with the `-N nfs' parameter of ncpmount. + +config NCPFS_OS2_NS + bool "Use LONG (OS/2) namespace if available" + depends on NCP_FS + help + Allows you to utilize OS2/LONG namespace on NetWare servers. + Filenames in this namespace are limited to 255 characters, they are + case insensitive, and case in names is preserved. Say Y. You can + disable it at mount time with the -N os2 parameter of ncpmount. + +config NCPFS_SMALLDOS + bool "Lowercase DOS filenames" + depends on NCP_FS + ---help--- + If you say Y here, every filename on a NetWare server volume using + the OS2/LONG namespace and created under DOS or on a volume using + DOS namespace will be converted to lowercase characters. + Saying N here will give you these filenames in uppercase. + + This is only a cosmetic option since the OS2/LONG namespace is case + insensitive. The only major reason for this option is backward + compatibility when moving from DOS to OS2/LONG namespace support. + Long filenames (created by Win95) will not be affected. + + This option does not solve the problem that filenames appear + differently under Linux and under Windows, since Windows does an + additional conversions on the client side. You can achieve similar + effects by saying Y to "Allow using of Native Language Support" + below. + +config NCPFS_NLS + bool "Use Native Language Support" + depends on NCP_FS + select NLS + help + Allows you to use codepages and I/O charsets for file name + translation between the server file system and input/output. This + may be useful, if you want to access the server with other operating + systems, e.g. Windows 95. See also NLS for more Information. + + To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer. + +config NCPFS_EXTRAS + bool "Enable symbolic links and execute flags" + depends on NCP_FS + help + This enables the use of symbolic links and an execute permission + bit on NCPFS. The file server need not have long name space or NFS + name space loaded for these to work. + + To use the new attributes, it is recommended to use the flags + '-f 600 -d 755' on the ncpmount command line. + diff --git a/drivers/staging/ncpfs/Makefile b/drivers/staging/ncpfs/Makefile new file mode 100644 index 000000000000..66fe5f878817 --- /dev/null +++ b/drivers/staging/ncpfs/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the linux ncp filesystem routines. +# + +obj-$(CONFIG_NCP_FS) += ncpfs.o + +ncpfs-y := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ + ncpsign_kernel.o getopt.o + +ncpfs-$(CONFIG_NCPFS_EXTRAS) += symlink.o +ncpfs-$(CONFIG_NCPFS_NFS_NS) += symlink.o + +# If you want debugging output, please uncomment the following line +# ccflags-y := -DDEBUG_NCP=1 + +CFLAGS_ncplib_kernel.o := -finline-functions diff --git a/drivers/staging/ncpfs/TODO b/drivers/staging/ncpfs/TODO new file mode 100644 index 000000000000..9b6d38b7e248 --- /dev/null +++ b/drivers/staging/ncpfs/TODO @@ -0,0 +1,4 @@ +The ncpfs code will be removed soon from the kernel tree as it is old and +obsolete and broken. + +Don't worry about fixing up anything here, it's not needed. diff --git a/drivers/staging/ncpfs/dir.c b/drivers/staging/ncpfs/dir.c new file mode 100644 index 000000000000..0c57c5c5d40a --- /dev/null +++ b/drivers/staging/ncpfs/dir.c @@ -0,0 +1,1232 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dir.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998, 1999 Wolfram Pienkoss for NLS + * Modified 1999 Wolfram Pienkoss for directory caching + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + + +#include <linux/time.h> +#include <linux/errno.h> +#include <linux/stat.h> +#include <linux/kernel.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/namei.h> +#include <linux/uaccess.h> +#include <asm/byteorder.h> + +#include "ncp_fs.h" + +static void ncp_read_volume_list(struct file *, struct dir_context *, + struct ncp_cache_control *); +static void ncp_do_readdir(struct file *, struct dir_context *, + struct ncp_cache_control *); + +static int ncp_readdir(struct file *, struct dir_context *); + +static int ncp_create(struct inode *, struct dentry *, umode_t, bool); +static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); +static int ncp_unlink(struct inode *, struct dentry *); +static int ncp_mkdir(struct inode *, struct dentry *, umode_t); +static int ncp_rmdir(struct inode *, struct dentry *); +static int ncp_rename(struct inode *, struct dentry *, + struct inode *, struct dentry *, unsigned int); +static int ncp_mknod(struct inode * dir, struct dentry *dentry, + umode_t mode, dev_t rdev); +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) +extern int ncp_symlink(struct inode *, struct dentry *, const char *); +#else +#define ncp_symlink NULL +#endif + +const struct file_operations ncp_dir_operations = +{ + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = ncp_readdir, + .unlocked_ioctl = ncp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ncp_compat_ioctl, +#endif +}; + +const struct inode_operations ncp_dir_inode_operations = +{ + .create = ncp_create, + .lookup = ncp_lookup, + .unlink = ncp_unlink, + .symlink = ncp_symlink, + .mkdir = ncp_mkdir, + .rmdir = ncp_rmdir, + .mknod = ncp_mknod, + .rename = ncp_rename, + .setattr = ncp_notify_change, +}; + +/* + * Dentry operations routines + */ +static int ncp_lookup_validate(struct dentry *, unsigned int); +static int ncp_hash_dentry(const struct dentry *, struct qstr *); +static int ncp_compare_dentry(const struct dentry *, + unsigned int, const char *, const struct qstr *); +static int ncp_delete_dentry(const struct dentry *); +static void ncp_d_prune(struct dentry *dentry); + +const struct dentry_operations ncp_dentry_operations = +{ + .d_revalidate = ncp_lookup_validate, + .d_hash = ncp_hash_dentry, + .d_compare = ncp_compare_dentry, + .d_delete = ncp_delete_dentry, + .d_prune = ncp_d_prune, +}; + +#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) + +static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) +{ +#ifdef CONFIG_NCPFS_SMALLDOS + int ns = ncp_namespace(i); + + if ((ns == NW_NS_DOS) +#ifdef CONFIG_NCPFS_OS2_NS + || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) +#endif /* CONFIG_NCPFS_OS2_NS */ + ) + return 0; +#endif /* CONFIG_NCPFS_SMALLDOS */ + return 1; +} + +#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) + +static inline int ncp_case_sensitive(const struct inode *i) +{ +#ifdef CONFIG_NCPFS_NFS_NS + return ncp_namespace(i) == NW_NS_NFS; +#else + return 0; +#endif /* CONFIG_NCPFS_NFS_NS */ +} + +/* + * Note: leave the hash unchanged if the directory + * is case-sensitive. + */ +static int +ncp_hash_dentry(const struct dentry *dentry, struct qstr *this) +{ + struct inode *inode = d_inode_rcu(dentry); + + if (!inode) + return 0; + + if (!ncp_case_sensitive(inode)) { + struct nls_table *t; + unsigned long hash; + int i; + + t = NCP_IO_TABLE(dentry->d_sb); + hash = init_name_hash(dentry); + for (i=0; i<this->len ; i++) + hash = partial_name_hash(ncp_tolower(t, this->name[i]), + hash); + this->hash = end_name_hash(hash); + } + return 0; +} + +static int +ncp_compare_dentry(const struct dentry *dentry, + unsigned int len, const char *str, const struct qstr *name) +{ + struct inode *pinode; + + if (len != name->len) + return 1; + + pinode = d_inode_rcu(dentry->d_parent); + if (!pinode) + return 1; + + if (ncp_case_sensitive(pinode)) + return strncmp(str, name->name, len); + + return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len); +} + +/* + * This is the callback from dput() when d_count is going to 0. + * We use this to unhash dentries with bad inodes. + * Closing files can be safely postponed until iput() - it's done there anyway. + */ +static int +ncp_delete_dentry(const struct dentry * dentry) +{ + struct inode *inode = d_inode(dentry); + + if (inode) { + if (is_bad_inode(inode)) + return 1; + } else + { + /* N.B. Unhash negative dentries? */ + } + return 0; +} + +static inline int +ncp_single_volume(struct ncp_server *server) +{ + return (server->m.mounted_vol[0] != '\0'); +} + +static inline int ncp_is_server_root(struct inode *inode) +{ + return !ncp_single_volume(NCP_SERVER(inode)) && + is_root_inode(inode); +} + + +/* + * This is the callback when the dcache has a lookup hit. + */ + + +#ifdef CONFIG_NCPFS_STRONG +/* try to delete a readonly file (NW R bit set) */ + +static int +ncp_force_unlink(struct inode *dir, struct dentry* dentry) +{ + int res=0x9c,res2; + struct nw_modify_dos_info info; + __le32 old_nwattr; + struct inode *inode; + + memset(&info, 0, sizeof(info)); + + /* remove the Read-Only flag on the NW server */ + inode = d_inode(dentry); + + old_nwattr = NCP_FINFO(inode)->nwattr; + info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); + if (res2) + goto leave_me; + + /* now try again the delete operation */ + res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); + + if (res) /* delete failed, set R bit again */ + { + info.attributes = old_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); + if (res2) + goto leave_me; + } +leave_me: + return(res); +} +#endif /* CONFIG_NCPFS_STRONG */ + +#ifdef CONFIG_NCPFS_STRONG +static int +ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, + struct inode *new_dir, struct dentry* new_dentry, char *_new_name) +{ + struct nw_modify_dos_info info; + int res=0x90,res2; + struct inode *old_inode = d_inode(old_dentry); + __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr; + __le32 new_nwattr = 0; /* shut compiler warning */ + int old_nwattr_changed = 0; + int new_nwattr_changed = 0; + + memset(&info, 0, sizeof(info)); + + /* remove the Read-Only flag on the NW server */ + + info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); + if (!res2) + old_nwattr_changed = 1; + if (new_dentry && d_really_is_positive(new_dentry)) { + new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr; + info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); + if (!res2) + new_nwattr_changed = 1; + } + /* now try again the rename operation */ + /* but only if something really happened */ + if (new_nwattr_changed || old_nwattr_changed) { + res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), + old_dir, _old_name, + new_dir, _new_name); + } + if (res) + goto leave_me; + /* file was successfully renamed, so: + do not set attributes on old file - it no longer exists + copy attributes from old file to new */ + new_nwattr_changed = old_nwattr_changed; + new_nwattr = old_nwattr; + old_nwattr_changed = 0; + +leave_me:; + if (old_nwattr_changed) { + info.attributes = old_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); + /* ignore errors */ + } + if (new_nwattr_changed) { + info.attributes = new_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); + /* ignore errors */ + } + return(res); +} +#endif /* CONFIG_NCPFS_STRONG */ + + +static int +ncp_lookup_validate(struct dentry *dentry, unsigned int flags) +{ + struct ncp_server *server; + struct dentry *parent; + struct inode *dir; + struct ncp_entry_info finfo; + int res, val = 0, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + if (dentry == dentry->d_sb->s_root) + return 1; + + if (flags & LOOKUP_RCU) + return -ECHILD; + + parent = dget_parent(dentry); + dir = d_inode(parent); + + if (d_really_is_negative(dentry)) + goto finished; + + server = NCP_SERVER(dir); + + /* + * Inspired by smbfs: + * The default validation is based on dentry age: + * We set the max age at mount time. (But each + * successful server lookup renews the timestamp.) + */ + val = NCP_TEST_AGE(server, dentry); + if (val) + goto finished; + + ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n", + dentry, NCP_GET_AGE(dentry)); + + len = sizeof(__name); + if (ncp_is_server_root(dir)) { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, 1); + if (!res) { + res = ncp_lookup_volume(server, __name, &(finfo.i)); + if (!res) + ncp_update_known_namespace(server, finfo.i.volNumber, NULL); + } + } else { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (!res) + res = ncp_obtain_info(server, dir, __name, &(finfo.i)); + } + finfo.volume = finfo.i.volNumber; + ncp_dbg(2, "looked for %pd/%s, res=%d\n", + dentry->d_parent, __name, res); + /* + * If we didn't find it, or if it has a different dirEntNum to + * what we remember, it's not valid any more. + */ + if (!res) { + struct inode *inode = d_inode(dentry); + + inode_lock(inode); + if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) { + ncp_new_dentry(dentry); + val=1; + } else + ncp_dbg(2, "found, but dirEntNum changed\n"); + + ncp_update_inode2(inode, &finfo); + inode_unlock(inode); + } + +finished: + ncp_dbg(2, "result=%d\n", val); + dput(parent); + return val; +} + +static time_t ncp_obtain_mtime(struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + struct ncp_server *server = NCP_SERVER(inode); + struct nw_info_struct i; + + if (!ncp_conn_valid(server) || ncp_is_server_root(inode)) + return 0; + + if (ncp_obtain_info(server, inode, NULL, &i)) + return 0; + + return ncp_date_dos2unix(i.modifyTime, i.modifyDate); +} + +static inline void +ncp_invalidate_dircache_entries(struct dentry *parent) +{ + struct ncp_server *server = NCP_SERVER(d_inode(parent)); + struct dentry *dentry; + + spin_lock(&parent->d_lock); + list_for_each_entry(dentry, &parent->d_subdirs, d_child) { + dentry->d_fsdata = NULL; + ncp_age_dentry(server, dentry); + } + spin_unlock(&parent->d_lock); +} + +static int ncp_readdir(struct file *file, struct dir_context *ctx) +{ + struct dentry *dentry = file->f_path.dentry; + struct inode *inode = d_inode(dentry); + struct page *page = NULL; + struct ncp_server *server = NCP_SERVER(inode); + union ncp_dir_cache *cache = NULL; + struct ncp_cache_control ctl; + int result, mtime_valid = 0; + time_t mtime = 0; + + ctl.page = NULL; + ctl.cache = NULL; + + ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos); + + result = -EIO; + /* Do not generate '.' and '..' when server is dead. */ + if (!ncp_conn_valid(server)) + goto out; + + result = 0; + if (!dir_emit_dots(file, ctx)) + goto out; + + page = grab_cache_page(&inode->i_data, 0); + if (!page) + goto read_really; + + ctl.cache = cache = kmap(page); + ctl.head = cache->head; + + if (!PageUptodate(page) || !ctl.head.eof) + goto init_cache; + + if (ctx->pos == 2) { + if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) + goto init_cache; + + mtime = ncp_obtain_mtime(dentry); + mtime_valid = 1; + if ((!mtime) || (mtime != ctl.head.mtime)) + goto init_cache; + } + + if (ctx->pos > ctl.head.end) + goto finished; + + ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2); + ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; + ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; + + for (;;) { + if (ctl.ofs != 0) { + ctl.page = find_lock_page(&inode->i_data, ctl.ofs); + if (!ctl.page) + goto invalid_cache; + ctl.cache = kmap(ctl.page); + if (!PageUptodate(ctl.page)) + goto invalid_cache; + } + while (ctl.idx < NCP_DIRCACHE_SIZE) { + struct dentry *dent; + bool over; + + spin_lock(&dentry->d_lock); + if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) { + spin_unlock(&dentry->d_lock); + goto invalid_cache; + } + dent = ctl.cache->dentry[ctl.idx]; + if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) { + spin_unlock(&dentry->d_lock); + goto invalid_cache; + } + spin_unlock(&dentry->d_lock); + if (d_really_is_negative(dent)) { + dput(dent); + goto invalid_cache; + } + over = !dir_emit(ctx, dent->d_name.name, + dent->d_name.len, + d_inode(dent)->i_ino, DT_UNKNOWN); + dput(dent); + if (over) + goto finished; + ctx->pos += 1; + ctl.idx += 1; + if (ctx->pos > ctl.head.end) + goto finished; + } + if (ctl.page) { + kunmap(ctl.page); + SetPageUptodate(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + ctl.page = NULL; + } + ctl.idx = 0; + ctl.ofs += 1; + } +invalid_cache: + if (ctl.page) { + kunmap(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + ctl.page = NULL; + } + ctl.cache = cache; +init_cache: + ncp_invalidate_dircache_entries(dentry); + if (!mtime_valid) { + mtime = ncp_obtain_mtime(dentry); + mtime_valid = 1; + } + ctl.head.mtime = mtime; + ctl.head.time = jiffies; + ctl.head.eof = 0; + ctl.fpos = 2; + ctl.ofs = 0; + ctl.idx = NCP_DIRCACHE_START; + ctl.filled = 0; + ctl.valid = 1; +read_really: + spin_lock(&dentry->d_lock); + NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE; + spin_unlock(&dentry->d_lock); + if (ncp_is_server_root(inode)) { + ncp_read_volume_list(file, ctx, &ctl); + } else { + ncp_do_readdir(file, ctx, &ctl); + } + ctl.head.end = ctl.fpos - 1; + ctl.head.eof = ctl.valid; +finished: + if (ctl.page) { + kunmap(ctl.page); + SetPageUptodate(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + } + if (page) { + cache->head = ctl.head; + kunmap(page); + SetPageUptodate(page); + unlock_page(page); + put_page(page); + } +out: + return result; +} + +static void ncp_d_prune(struct dentry *dentry) +{ + if (!dentry->d_fsdata) /* not referenced from page cache */ + return; + NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE; +} + +static int +ncp_fill_cache(struct file *file, struct dir_context *ctx, + struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, + int inval_childs) +{ + struct dentry *newdent, *dentry = file->f_path.dentry; + struct inode *dir = d_inode(dentry); + struct ncp_cache_control ctl = *ctrl; + struct qstr qname; + int valid = 0; + int hashed = 0; + ino_t ino = 0; + __u8 __name[NCP_MAXPATHLEN + 1]; + + qname.len = sizeof(__name); + if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len, + entry->i.entryName, entry->i.nameLen, + !ncp_preserve_entry_case(dir, entry->i.NSCreator))) + return 1; /* I'm not sure */ + + qname.name = __name; + + newdent = d_hash_and_lookup(dentry, &qname); + if (IS_ERR(newdent)) + goto end_advance; + if (!newdent) { + newdent = d_alloc(dentry, &qname); + if (!newdent) + goto end_advance; + } else { + hashed = 1; + + /* If case sensitivity changed for this volume, all entries below this one + should be thrown away. This entry itself is not affected, as its case + sensitivity is controlled by its own parent. */ + if (inval_childs) + shrink_dcache_parent(newdent); + + /* + * NetWare's OS2 namespace is case preserving yet case + * insensitive. So we update dentry's name as received from + * server. Parent dir's i_mutex is locked because we're in + * readdir. + */ + dentry_update_name_case(newdent, &qname); + } + + if (d_really_is_negative(newdent)) { + struct inode *inode; + + entry->opened = 0; + entry->ino = iunique(dir->i_sb, 2); + inode = ncp_iget(dir->i_sb, entry); + if (inode) { + d_instantiate(newdent, inode); + if (!hashed) + d_rehash(newdent); + } else { + spin_lock(&dentry->d_lock); + NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE; + spin_unlock(&dentry->d_lock); + } + } else { + struct inode *inode = d_inode(newdent); + + inode_lock_nested(inode, I_MUTEX_CHILD); + ncp_update_inode2(inode, entry); + inode_unlock(inode); + } + + if (ctl.idx >= NCP_DIRCACHE_SIZE) { + if (ctl.page) { + kunmap(ctl.page); + SetPageUptodate(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + } + ctl.cache = NULL; + ctl.idx -= NCP_DIRCACHE_SIZE; + ctl.ofs += 1; + ctl.page = grab_cache_page(&dir->i_data, ctl.ofs); + if (ctl.page) + ctl.cache = kmap(ctl.page); + } + if (ctl.cache) { + if (d_really_is_positive(newdent)) { + newdent->d_fsdata = newdent; + ctl.cache->dentry[ctl.idx] = newdent; + ino = d_inode(newdent)->i_ino; + ncp_new_dentry(newdent); + } + valid = 1; + } + dput(newdent); +end_advance: + if (!valid) + ctl.valid = 0; + if (!ctl.filled && (ctl.fpos == ctx->pos)) { + if (!ino) + ino = iunique(dir->i_sb, 2); + ctl.filled = !dir_emit(ctx, qname.name, qname.len, + ino, DT_UNKNOWN); + if (!ctl.filled) + ctx->pos += 1; + } + ctl.fpos += 1; + ctl.idx += 1; + *ctrl = ctl; + return (ctl.valid || !ctl.filled); +} + +static void +ncp_read_volume_list(struct file *file, struct dir_context *ctx, + struct ncp_cache_control *ctl) +{ + struct inode *inode = file_inode(file); + struct ncp_server *server = NCP_SERVER(inode); + struct ncp_volume_info info; + struct ncp_entry_info entry; + int i; + + ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos); + + for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { + int inval_dentry; + + if (ncp_get_volume_info_with_number(server, i, &info) != 0) + return; + if (!strlen(info.volume_name)) + continue; + + ncp_dbg(1, "found vol: %s\n", info.volume_name); + + if (ncp_lookup_volume(server, info.volume_name, + &entry.i)) { + ncp_dbg(1, "could not lookup vol %s\n", + info.volume_name); + continue; + } + inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); + entry.volume = entry.i.volNumber; + if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry)) + return; + } +} + +static void +ncp_do_readdir(struct file *file, struct dir_context *ctx, + struct ncp_cache_control *ctl) +{ + struct inode *dir = file_inode(file); + struct ncp_server *server = NCP_SERVER(dir); + struct nw_search_sequence seq; + struct ncp_entry_info entry; + int err; + void* buf; + int more; + size_t bufsize; + + ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos); + ncp_vdbg("init %pD, volnum=%d, dirent=%u\n", + file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); + + err = ncp_initialize_search(server, dir, &seq); + if (err) { + ncp_dbg(1, "init failed, err=%d\n", err); + return; + } + /* We MUST NOT use server->buffer_size handshaked with server if we are + using UDP, as for UDP server uses max. buffer size determined by + MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). + So we use 128KB, just to be sure, as there is no way how to know + this value in advance. */ + bufsize = 131072; + buf = vmalloc(bufsize); + if (!buf) + return; + do { + int cnt; + char* rpl; + size_t rpls; + + err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls); + if (err) /* Error */ + break; + if (!cnt) /* prevent endless loop */ + break; + while (cnt--) { + size_t onerpl; + + if (rpls < offsetof(struct nw_info_struct, entryName)) + break; /* short packet */ + ncp_extract_file_info(rpl, &entry.i); + onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen; + if (rpls < onerpl) + break; /* short packet */ + (void)ncp_obtain_nfs_info(server, &entry.i); + rpl += onerpl; + rpls -= onerpl; + entry.volume = entry.i.volNumber; + if (!ncp_fill_cache(file, ctx, ctl, &entry, 0)) + break; + } + } while (more); + vfree(buf); + return; +} + +int ncp_conn_logged_in(struct super_block *sb) +{ + struct ncp_server* server = NCP_SBP(sb); + int result; + + if (ncp_single_volume(server)) { + int len; + struct dentry* dent; + __u32 volNumber; + __le32 dirEntNum; + __le32 DosDirNum; + __u8 __name[NCP_MAXPATHLEN + 1]; + + len = sizeof(__name); + result = ncp_io2vol(server, __name, &len, server->m.mounted_vol, + strlen(server->m.mounted_vol), 1); + if (result) + goto out; + result = -ENOENT; + if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { + ncp_vdbg("%s not found\n", server->m.mounted_vol); + goto out; + } + dent = sb->s_root; + if (dent) { + struct inode* ino = d_inode(dent); + if (ino) { + ncp_update_known_namespace(server, volNumber, NULL); + NCP_FINFO(ino)->volNumber = volNumber; + NCP_FINFO(ino)->dirEntNum = dirEntNum; + NCP_FINFO(ino)->DosDirNum = DosDirNum; + result = 0; + } else { + ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n"); + } + } else { + ncp_dbg(1, "sb->s_root == NULL!\n"); + } + } else + result = 0; + +out: + return result; +} + +static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) +{ + struct ncp_server *server = NCP_SERVER(dir); + struct inode *inode = NULL; + struct ncp_entry_info finfo; + int error, res, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + error = -EIO; + if (!ncp_conn_valid(server)) + goto finished; + + ncp_vdbg("server lookup for %pd2\n", dentry); + + len = sizeof(__name); + if (ncp_is_server_root(dir)) { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, 1); + if (!res) + res = ncp_lookup_volume(server, __name, &(finfo.i)); + if (!res) + ncp_update_known_namespace(server, finfo.i.volNumber, NULL); + } else { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (!res) + res = ncp_obtain_info(server, dir, __name, &(finfo.i)); + } + ncp_vdbg("looked for %pd2, res=%d\n", dentry, res); + /* + * If we didn't find an entry, make a negative dentry. + */ + if (res) + goto add_entry; + + /* + * Create an inode for the entry. + */ + finfo.opened = 0; + finfo.ino = iunique(dir->i_sb, 2); + finfo.volume = finfo.i.volNumber; + error = -EACCES; + inode = ncp_iget(dir->i_sb, &finfo); + + if (inode) { + ncp_new_dentry(dentry); +add_entry: + d_add(dentry, inode); + error = 0; + } + +finished: + ncp_vdbg("result=%d\n", error); + return ERR_PTR(error); +} + +/* + * This code is common to create, mkdir, and mknod. + */ +static int ncp_instantiate(struct inode *dir, struct dentry *dentry, + struct ncp_entry_info *finfo) +{ + struct inode *inode; + int error = -EINVAL; + + finfo->ino = iunique(dir->i_sb, 2); + inode = ncp_iget(dir->i_sb, finfo); + if (!inode) + goto out_close; + d_instantiate(dentry,inode); + error = 0; +out: + return error; + +out_close: + ncp_vdbg("%pd2 failed, closing file\n", dentry); + ncp_close_file(NCP_SERVER(dir), finfo->file_handle); + goto out; +} + +int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode, + dev_t rdev, __le32 attributes) +{ + struct ncp_server *server = NCP_SERVER(dir); + struct ncp_entry_info finfo; + int error, result, len; + int opmode; + __u8 __name[NCP_MAXPATHLEN + 1]; + + ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode); + + ncp_age_dentry(server, dentry); + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (error) + goto out; + + error = -EACCES; + + if (S_ISREG(mode) && + (server->m.flags & NCP_MOUNT_EXTRAS) && + (mode & S_IXUGO)) + attributes |= aSYSTEM | aSHARED; + + result = ncp_open_create_file_or_subdir(server, dir, __name, + OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, + attributes, AR_READ | AR_WRITE, &finfo); + opmode = O_RDWR; + if (result) { + result = ncp_open_create_file_or_subdir(server, dir, __name, + OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, + attributes, AR_WRITE, &finfo); + if (result) { + if (result == 0x87) + error = -ENAMETOOLONG; + else if (result < 0) + error = result; + ncp_dbg(1, "%pd2 failed\n", dentry); + goto out; + } + opmode = O_WRONLY; + } + finfo.access = opmode; + if (ncp_is_nfs_extras(server, finfo.volume)) { + finfo.i.nfs.mode = mode; + finfo.i.nfs.rdev = new_encode_dev(rdev); + if (ncp_modify_nfs_info(server, finfo.volume, + finfo.i.dirEntNum, + mode, new_encode_dev(rdev)) != 0) + goto out; + } + + error = ncp_instantiate(dir, dentry, &finfo); +out: + return error; +} + +static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + return ncp_create_new(dir, dentry, mode, 0, 0); +} + +static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct ncp_entry_info finfo; + struct ncp_server *server = NCP_SERVER(dir); + int error, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + ncp_dbg(1, "making %pd2\n", dentry); + + ncp_age_dentry(server, dentry); + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (error) + goto out; + + error = ncp_open_create_file_or_subdir(server, dir, __name, + OC_MODE_CREATE, aDIR, + cpu_to_le16(0xffff), + &finfo); + if (error == 0) { + if (ncp_is_nfs_extras(server, finfo.volume)) { + mode |= S_IFDIR; + finfo.i.nfs.mode = mode; + if (ncp_modify_nfs_info(server, + finfo.volume, + finfo.i.dirEntNum, + mode, 0) != 0) + goto out; + } + error = ncp_instantiate(dir, dentry, &finfo); + } else if (error > 0) { + error = -EACCES; + } +out: + return error; +} + +static int ncp_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct ncp_server *server = NCP_SERVER(dir); + int error, result, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + ncp_dbg(1, "removing %pd2\n", dentry); + + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (error) + goto out; + + result = ncp_del_file_or_subdir(server, dir, __name); + switch (result) { + case 0x00: + error = 0; + break; + case 0x85: /* unauthorized to delete file */ + case 0x8A: /* unauthorized to delete file */ + error = -EACCES; + break; + case 0x8F: + case 0x90: /* read only */ + error = -EPERM; + break; + case 0x9F: /* in use by another client */ + error = -EBUSY; + break; + case 0xA0: /* directory not empty */ + error = -ENOTEMPTY; + break; + case 0xFF: /* someone deleted file */ + error = -ENOENT; + break; + default: + error = result < 0 ? result : -EACCES; + break; + } +out: + return error; +} + +static int ncp_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + struct ncp_server *server; + int error; + + server = NCP_SERVER(dir); + ncp_dbg(1, "unlinking %pd2\n", dentry); + + /* + * Check whether to close the file ... + */ + if (inode) { + ncp_vdbg("closing file\n"); + ncp_make_closed(inode); + } + + error = ncp_del_file_or_subdir2(server, dentry); +#ifdef CONFIG_NCPFS_STRONG + /* 9C is Invalid path.. It should be 8F, 90 - read only, but + it is not :-( */ + if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ + error = ncp_force_unlink(dir, dentry); + } +#endif + switch (error) { + case 0x00: + ncp_dbg(1, "removed %pd2\n", dentry); + break; + case 0x85: + case 0x8A: + error = -EACCES; + break; + case 0x8D: /* some files in use */ + case 0x8E: /* all files in use */ + error = -EBUSY; + break; + case 0x8F: /* some read only */ + case 0x90: /* all read only */ + case 0x9C: /* !!! returned when in-use or read-only by NW4 */ + error = -EPERM; + break; + case 0xFF: + error = -ENOENT; + break; + default: + error = error < 0 ? error : -EACCES; + break; + } + return error; +} + +static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + struct ncp_server *server = NCP_SERVER(old_dir); + int error; + int old_len, new_len; + __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; + + if (flags) + return -EINVAL; + + ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry); + + ncp_age_dentry(server, old_dentry); + ncp_age_dentry(server, new_dentry); + + old_len = sizeof(__old_name); + error = ncp_io2vol(server, __old_name, &old_len, + old_dentry->d_name.name, old_dentry->d_name.len, + !ncp_preserve_case(old_dir)); + if (error) + goto out; + + new_len = sizeof(__new_name); + error = ncp_io2vol(server, __new_name, &new_len, + new_dentry->d_name.name, new_dentry->d_name.len, + !ncp_preserve_case(new_dir)); + if (error) + goto out; + + error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name, + new_dir, __new_name); +#ifdef CONFIG_NCPFS_STRONG + if ((error == 0x90 || error == 0x8B || error == -EACCES) && + server->m.flags & NCP_MOUNT_STRONG) { /* RO */ + error = ncp_force_rename(old_dir, old_dentry, __old_name, + new_dir, new_dentry, __new_name); + } +#endif + switch (error) { + case 0x00: + ncp_dbg(1, "renamed %pd -> %pd\n", + old_dentry, new_dentry); + ncp_d_prune(old_dentry); + ncp_d_prune(new_dentry); + break; + case 0x9E: + error = -ENAMETOOLONG; + break; + case 0xFF: + error = -ENOENT; + break; + default: + error = error < 0 ? error : -EACCES; + break; + } +out: + return error; +} + +static int ncp_mknod(struct inode * dir, struct dentry *dentry, + umode_t mode, dev_t rdev) +{ + if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { + ncp_dbg(1, "mode = 0%ho\n", mode); + return ncp_create_new(dir, dentry, mode, rdev, 0); + } + return -EPERM; /* Strange, but true */ +} + +/* The following routines are taken directly from msdos-fs */ + +/* Linear day numbers of the respective 1sts in non-leap years. */ + +static int day_n[] = +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; +/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + +static int utc2local(int time) +{ + return time - sys_tz.tz_minuteswest * 60; +} + +static int local2utc(int time) +{ + return time + sys_tz.tz_minuteswest * 60; +} + +/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ +int +ncp_date_dos2unix(__le16 t, __le16 d) +{ + unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d); + int month, year, secs; + + /* first subtract and mask after that... Otherwise, if + date == 0, bad things happen */ + month = ((date >> 5) - 1) & 15; + year = date >> 9; + secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + + 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + + year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653); + /* days since 1.1.70 plus 80's leap day */ + return local2utc(secs); +} + + +/* Convert linear UNIX date to a MS-DOS time/date pair. */ +void +ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date) +{ + int day, year, nl_day, month; + + unix_date = utc2local(unix_date); + *time = cpu_to_le16( + (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + + (((unix_date / 3600) % 24) << 11)); + day = unix_date / 86400 - 3652; + year = day / 365; + if ((year + 3) / 4 + 365 * year > day) + year--; + day -= (year + 3) / 4 + 365 * year; + if (day == 59 && !(year & 3)) { + nl_day = day; + month = 2; + } else { + nl_day = (year & 3) || day <= 59 ? day : day - 1; + for (month = 1; month < 12; month++) + if (day_n[month] > nl_day) + break; + } + *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9)); +} diff --git a/drivers/staging/ncpfs/file.c b/drivers/staging/ncpfs/file.c new file mode 100644 index 000000000000..8f8cc0334ddd --- /dev/null +++ b/drivers/staging/ncpfs/file.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * file.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/uaccess.h> + +#include <linux/time.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fcntl.h> +#include <linux/stat.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/sched.h> + +#include "ncp_fs.h" + +static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync) +{ + return file_write_and_wait_range(file, start, end); +} + +/* + * Open a file with the specified read/write mode. + */ +int ncp_make_open(struct inode *inode, int right) +{ + int error; + int access; + + error = -EINVAL; + if (!inode) { + pr_err("%s: got NULL inode\n", __func__); + goto out; + } + + ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n", + atomic_read(&NCP_FINFO(inode)->opened), + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum); + error = -EACCES; + mutex_lock(&NCP_FINFO(inode)->open_mutex); + if (!atomic_read(&NCP_FINFO(inode)->opened)) { + struct ncp_entry_info finfo; + int result; + + /* tries max. rights */ + finfo.access = O_RDWR; + result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), + inode, NULL, OC_MODE_OPEN, + 0, AR_READ | AR_WRITE, &finfo); + if (!result) + goto update; + /* RDWR did not succeeded, try readonly or writeonly as requested */ + switch (right) { + case O_RDONLY: + finfo.access = O_RDONLY; + result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), + inode, NULL, OC_MODE_OPEN, + 0, AR_READ, &finfo); + break; + case O_WRONLY: + finfo.access = O_WRONLY; + result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), + inode, NULL, OC_MODE_OPEN, + 0, AR_WRITE, &finfo); + break; + } + if (result) { + ncp_vdbg("failed, result=%d\n", result); + goto out_unlock; + } + /* + * Update the inode information. + */ + update: + ncp_update_inode(inode, &finfo); + atomic_set(&NCP_FINFO(inode)->opened, 1); + } + + access = NCP_FINFO(inode)->access; + ncp_vdbg("file open, access=%x\n", access); + if (access == right || access == O_RDWR) { + atomic_inc(&NCP_FINFO(inode)->opened); + error = 0; + } + +out_unlock: + mutex_unlock(&NCP_FINFO(inode)->open_mutex); +out: + return error; +} + +static ssize_t +ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + size_t already_read = 0; + off_t pos = iocb->ki_pos; + size_t bufsize; + int error; + void *freepage; + size_t freelen; + + ncp_dbg(1, "enter %pD2\n", file); + + if (!iov_iter_count(to)) + return 0; + if (pos > inode->i_sb->s_maxbytes) + return 0; + iov_iter_truncate(to, inode->i_sb->s_maxbytes - pos); + + error = ncp_make_open(inode, O_RDONLY); + if (error) { + ncp_dbg(1, "open failed, error=%d\n", error); + return error; + } + + bufsize = NCP_SERVER(inode)->buffer_size; + + error = -EIO; + freelen = ncp_read_bounce_size(bufsize); + freepage = vmalloc(freelen); + if (!freepage) + goto outrel; + error = 0; + /* First read in as much as possible for each bufsize. */ + while (iov_iter_count(to)) { + int read_this_time; + size_t to_read = min_t(size_t, + bufsize - (pos % bufsize), + iov_iter_count(to)); + + error = ncp_read_bounce(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_read, to, &read_this_time, + freepage, freelen); + if (error) { + error = -EIO; /* NW errno -> Linux errno */ + break; + } + pos += read_this_time; + already_read += read_this_time; + + if (read_this_time != to_read) + break; + } + vfree(freepage); + + iocb->ki_pos = pos; + + file_accessed(file); + + ncp_dbg(1, "exit %pD2\n", file); +outrel: + ncp_inode_close(inode); + return already_read ? already_read : error; +} + +static ssize_t +ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + size_t already_written = 0; + size_t bufsize; + int errno; + void *bouncebuffer; + off_t pos; + + ncp_dbg(1, "enter %pD2\n", file); + errno = generic_write_checks(iocb, from); + if (errno <= 0) + return errno; + + errno = ncp_make_open(inode, O_WRONLY); + if (errno) { + ncp_dbg(1, "open failed, error=%d\n", errno); + return errno; + } + bufsize = NCP_SERVER(inode)->buffer_size; + + errno = file_update_time(file); + if (errno) + goto outrel; + + bouncebuffer = vmalloc(bufsize); + if (!bouncebuffer) { + errno = -EIO; /* -ENOMEM */ + goto outrel; + } + pos = iocb->ki_pos; + while (iov_iter_count(from)) { + int written_this_time; + size_t to_write = min_t(size_t, + bufsize - (pos % bufsize), + iov_iter_count(from)); + + if (!copy_from_iter_full(bouncebuffer, to_write, from)) { + errno = -EFAULT; + break; + } + if (ncp_write_kernel(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_write, bouncebuffer, &written_this_time) != 0) { + errno = -EIO; + break; + } + pos += written_this_time; + already_written += written_this_time; + + if (written_this_time != to_write) + break; + } + vfree(bouncebuffer); + + iocb->ki_pos = pos; + + if (pos > i_size_read(inode)) { + inode_lock(inode); + if (pos > i_size_read(inode)) + i_size_write(inode, pos); + inode_unlock(inode); + } + ncp_dbg(1, "exit %pD2\n", file); +outrel: + ncp_inode_close(inode); + return already_written ? already_written : errno; +} + +static int ncp_release(struct inode *inode, struct file *file) { + if (ncp_make_closed(inode)) { + ncp_dbg(1, "failed to close\n"); + } + return 0; +} + +const struct file_operations ncp_file_operations = +{ + .llseek = generic_file_llseek, + .read_iter = ncp_file_read_iter, + .write_iter = ncp_file_write_iter, + .unlocked_ioctl = ncp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ncp_compat_ioctl, +#endif + .mmap = ncp_mmap, + .release = ncp_release, + .fsync = ncp_fsync, +}; + +const struct inode_operations ncp_file_inode_operations = +{ + .setattr = ncp_notify_change, +}; diff --git a/drivers/staging/ncpfs/getopt.c b/drivers/staging/ncpfs/getopt.c new file mode 100644 index 000000000000..5c941bef14c4 --- /dev/null +++ b/drivers/staging/ncpfs/getopt.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * getopt.c + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include <linux/string.h> + +#include <asm/errno.h> + +#include "getopt.h" + +/** + * ncp_getopt - option parser + * @caller: name of the caller, for error messages + * @options: the options string + * @opts: an array of &struct option entries controlling parser operations + * @optopt: output; will contain the current option + * @optarg: output; will contain the value (if one exists) + * @value: output; may be NULL; will be overwritten with the integer value + * of the current argument. + * + * Helper to parse options on the format used by mount ("a=b,c=d,e,f"). + * Returns opts->val if a matching entry in the 'opts' array is found, + * 0 when no more tokens are found, -1 if an error is encountered. + */ +int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value) +{ + char *token; + char *val; + + do { + if ((token = strsep(options, ",")) == NULL) + return 0; + } while (*token == '\0'); + if (optopt) + *optopt = token; + + if ((val = strchr (token, '=')) != NULL) { + *val++ = 0; + } + *optarg = val; + for (; opts->name; opts++) { + if (!strcmp(opts->name, token)) { + if (!val) { + if (opts->has_arg & OPT_NOPARAM) { + return opts->val; + } + pr_info("%s: the %s option requires an argument\n", + caller, token); + return -EINVAL; + } + if (opts->has_arg & OPT_INT) { + int rc = kstrtoul(val, 0, value); + + if (rc) { + pr_info("%s: invalid numeric value in %s=%s\n", + caller, token, val); + return rc; + } + return opts->val; + } + if (opts->has_arg & OPT_STRING) { + return opts->val; + } + pr_info("%s: unexpected argument %s to the %s option\n", + caller, val, token); + return -EINVAL; + } + } + pr_info("%s: Unrecognized mount option %s\n", caller, token); + return -EOPNOTSUPP; +} diff --git a/drivers/staging/ncpfs/getopt.h b/drivers/staging/ncpfs/getopt.h new file mode 100644 index 000000000000..30f0da317670 --- /dev/null +++ b/drivers/staging/ncpfs/getopt.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_GETOPT_H +#define _LINUX_GETOPT_H + +#define OPT_NOPARAM 1 +#define OPT_INT 2 +#define OPT_STRING 4 +struct ncp_option { + const char *name; + unsigned int has_arg; + int val; +}; + +extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value); + +#endif /* _LINUX_GETOPT_H */ diff --git a/drivers/staging/ncpfs/inode.c b/drivers/staging/ncpfs/inode.c new file mode 100644 index 000000000000..41de88cdc053 --- /dev/null +++ b/drivers/staging/ncpfs/inode.c @@ -0,0 +1,1066 @@ +/* + * inode.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998 Wolfram Pienkoss for NLS + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> + +#include <linux/uaccess.h> +#include <asm/byteorder.h> + +#include <linux/time.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/stat.h> +#include <linux/errno.h> +#include <linux/file.h> +#include <linux/fcntl.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/init.h> +#include <linux/vfs.h> +#include <linux/mount.h> +#include <linux/seq_file.h> +#include <linux/sched/signal.h> +#include <linux/namei.h> + +#include <net/sock.h> + +#include "ncp_fs.h" +#include "getopt.h" + +#define NCP_DEFAULT_FILE_MODE 0600 +#define NCP_DEFAULT_DIR_MODE 0700 +#define NCP_DEFAULT_TIME_OUT 10 +#define NCP_DEFAULT_RETRY_COUNT 20 + +static void ncp_evict_inode(struct inode *); +static void ncp_put_super(struct super_block *); +static int ncp_statfs(struct dentry *, struct kstatfs *); +static int ncp_show_options(struct seq_file *, struct dentry *); + +static struct kmem_cache * ncp_inode_cachep; + +static struct inode *ncp_alloc_inode(struct super_block *sb) +{ + struct ncp_inode_info *ei; + ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL); + if (!ei) + return NULL; + return &ei->vfs_inode; +} + +static void ncp_i_callback(struct rcu_head *head) +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); +} + +static void ncp_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, ncp_i_callback); +} + +static void init_once(void *foo) +{ + struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; + + mutex_init(&ei->open_mutex); + inode_init_once(&ei->vfs_inode); +} + +static int init_inodecache(void) +{ + ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", + sizeof(struct ncp_inode_info), + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD|SLAB_ACCOUNT), + init_once); + if (ncp_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + +static void destroy_inodecache(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(ncp_inode_cachep); +} + +static int ncp_remount(struct super_block *sb, int *flags, char* data) +{ + sync_filesystem(sb); + *flags |= SB_NODIRATIME; + return 0; +} + +static const struct super_operations ncp_sops = +{ + .alloc_inode = ncp_alloc_inode, + .destroy_inode = ncp_destroy_inode, + .drop_inode = generic_delete_inode, + .evict_inode = ncp_evict_inode, + .put_super = ncp_put_super, + .statfs = ncp_statfs, + .remount_fs = ncp_remount, + .show_options = ncp_show_options, +}; + +/* + * Fill in the ncpfs-specific information in the inode. + */ +static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; + NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; + NCP_FINFO(inode)->volNumber = nwinfo->volume; +} + +void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + ncp_update_dirent(inode, nwinfo); + NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; + NCP_FINFO(inode)->access = nwinfo->access; + memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, + sizeof(nwinfo->file_handle)); + ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n", + nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum); +} + +static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) +{ + /* NFS namespace mode overrides others if it's set. */ + ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode); + if (nwi->nfs.mode) { + /* XXX Security? */ + inode->i_mode = nwi->nfs.mode; + } + + inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; + + inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); + inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); + inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate); + inode->i_atime.tv_nsec = 0; + inode->i_mtime.tv_nsec = 0; + inode->i_ctime.tv_nsec = 0; +} + +static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + struct nw_info_struct *nwi = &nwinfo->i; + struct ncp_server *server = NCP_SERVER(inode); + + if (nwi->attributes & aDIR) { + inode->i_mode = server->m.dir_mode; + /* for directories dataStreamSize seems to be some + Object ID ??? */ + i_size_write(inode, NCP_BLOCK_SIZE); + } else { + u32 size; + + inode->i_mode = server->m.file_mode; + size = le32_to_cpu(nwi->dataStreamSize); + i_size_write(inode, size); +#ifdef CONFIG_NCPFS_EXTRAS + if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) + && (nwi->attributes & aSHARED)) { + switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { + case aHIDDEN: + if (server->m.flags & NCP_MOUNT_SYMLINKS) { + if (/* (size >= NCP_MIN_SYMLINK_SIZE) + && */ (size <= NCP_MAX_SYMLINK_SIZE)) { + inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; + NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; + break; + } + } + /* FALLTHROUGH */ + case 0: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= S_IRUGO; + break; + case aSYSTEM: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO; + break; + /* case aSYSTEM|aHIDDEN: */ + default: + /* reserved combination */ + break; + } + } +#endif + } + if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO; +} + +void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) +{ + NCP_FINFO(inode)->flags = 0; + if (!atomic_read(&NCP_FINFO(inode)->opened)) { + NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; + ncp_update_attrs(inode, nwinfo); + } + + ncp_update_dates(inode, &nwinfo->i); + ncp_update_dirent(inode, nwinfo); +} + +/* + * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes. + */ +static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + struct ncp_server *server = NCP_SERVER(inode); + + NCP_FINFO(inode)->flags = 0; + + ncp_update_attrs(inode, nwinfo); + + ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode); + + set_nlink(inode, 1); + inode->i_uid = server->m.uid; + inode->i_gid = server->m.gid; + + ncp_update_dates(inode, &nwinfo->i); + ncp_update_inode(inode, nwinfo); +} + +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) +static const struct inode_operations ncp_symlink_inode_operations = { + .get_link = page_get_link, + .setattr = ncp_notify_change, +}; +#endif + +/* + * Get a new inode. + */ +struct inode * +ncp_iget(struct super_block *sb, struct ncp_entry_info *info) +{ + struct inode *inode; + + if (info == NULL) { + pr_err("%s: info is NULL\n", __func__); + return NULL; + } + + inode = new_inode(sb); + if (inode) { + atomic_set(&NCP_FINFO(inode)->opened, info->opened); + + inode->i_ino = info->ino; + ncp_set_attr(inode, info); + if (S_ISREG(inode->i_mode)) { + inode->i_op = &ncp_file_inode_operations; + inode->i_fop = &ncp_file_operations; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &ncp_dir_inode_operations; + inode->i_fop = &ncp_dir_operations; +#ifdef CONFIG_NCPFS_NFS_NS + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + init_special_inode(inode, inode->i_mode, + new_decode_dev(info->i.nfs.rdev)); +#endif +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &ncp_symlink_inode_operations; + inode_nohighmem(inode); + inode->i_data.a_ops = &ncp_symlink_aops; +#endif + } else { + make_bad_inode(inode); + } + insert_inode_hash(inode); + } else + pr_err("%s: iget failed!\n", __func__); + return inode; +} + +static void +ncp_evict_inode(struct inode *inode) +{ + truncate_inode_pages_final(&inode->i_data); + clear_inode(inode); + + if (S_ISDIR(inode->i_mode)) { + ncp_dbg(2, "put directory %ld\n", inode->i_ino); + } + + if (ncp_make_closed(inode) != 0) { + /* We can't do anything but complain. */ + pr_err("%s: could not close\n", __func__); + } +} + +static void ncp_stop_tasks(struct ncp_server *server) { + struct sock* sk = server->ncp_sock->sk; + + lock_sock(sk); + sk->sk_error_report = server->error_report; + sk->sk_data_ready = server->data_ready; + sk->sk_write_space = server->write_space; + release_sock(sk); + del_timer_sync(&server->timeout_tm); + + flush_work(&server->rcv.tq); + if (sk->sk_socket->type == SOCK_STREAM) + flush_work(&server->tx.tq); + else + flush_work(&server->timeout_tq); +} + +static int ncp_show_options(struct seq_file *seq, struct dentry *root) +{ + struct ncp_server *server = NCP_SBP(root->d_sb); + unsigned int tmp; + + if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID)) + seq_printf(seq, ",uid=%u", + from_kuid_munged(&init_user_ns, server->m.uid)); + if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID)) + seq_printf(seq, ",gid=%u", + from_kgid_munged(&init_user_ns, server->m.gid)); + if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID)) + seq_printf(seq, ",owner=%u", + from_kuid_munged(&init_user_ns, server->m.mounted_uid)); + tmp = server->m.file_mode & S_IALLUGO; + if (tmp != NCP_DEFAULT_FILE_MODE) + seq_printf(seq, ",mode=0%o", tmp); + tmp = server->m.dir_mode & S_IALLUGO; + if (tmp != NCP_DEFAULT_DIR_MODE) + seq_printf(seq, ",dirmode=0%o", tmp); + if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) { + tmp = server->m.time_out * 100 / HZ; + seq_printf(seq, ",timeout=%u", tmp); + } + if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT) + seq_printf(seq, ",retry=%u", server->m.retry_count); + if (server->m.flags != 0) + seq_printf(seq, ",flags=%lu", server->m.flags); + if (server->m.wdog_pid != NULL) + seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid)); + + return 0; +} + +static const struct ncp_option ncp_opts[] = { + { "uid", OPT_INT, 'u' }, + { "gid", OPT_INT, 'g' }, + { "owner", OPT_INT, 'o' }, + { "mode", OPT_INT, 'm' }, + { "dirmode", OPT_INT, 'd' }, + { "timeout", OPT_INT, 't' }, + { "retry", OPT_INT, 'r' }, + { "flags", OPT_INT, 'f' }, + { "wdogpid", OPT_INT, 'w' }, + { "ncpfd", OPT_INT, 'n' }, + { "infofd", OPT_INT, 'i' }, /* v5 */ + { "version", OPT_INT, 'v' }, + { NULL, 0, 0 } }; + +static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { + int optval; + char *optarg; + unsigned long optint; + int version = 0; + int ret; + + data->flags = 0; + data->int_flags = 0; + data->mounted_uid = GLOBAL_ROOT_UID; + data->wdog_pid = NULL; + data->ncp_fd = ~0; + data->time_out = NCP_DEFAULT_TIME_OUT; + data->retry_count = NCP_DEFAULT_RETRY_COUNT; + data->uid = GLOBAL_ROOT_UID; + data->gid = GLOBAL_ROOT_GID; + data->file_mode = NCP_DEFAULT_FILE_MODE; + data->dir_mode = NCP_DEFAULT_DIR_MODE; + data->info_fd = -1; + data->mounted_vol[0] = 0; + + while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { + ret = optval; + if (ret < 0) + goto err; + switch (optval) { + case 'u': + data->uid = make_kuid(current_user_ns(), optint); + if (!uid_valid(data->uid)) { + ret = -EINVAL; + goto err; + } + break; + case 'g': + data->gid = make_kgid(current_user_ns(), optint); + if (!gid_valid(data->gid)) { + ret = -EINVAL; + goto err; + } + break; + case 'o': + data->mounted_uid = make_kuid(current_user_ns(), optint); + if (!uid_valid(data->mounted_uid)) { + ret = -EINVAL; + goto err; + } + break; + case 'm': + data->file_mode = optint; + break; + case 'd': + data->dir_mode = optint; + break; + case 't': + data->time_out = optint; + break; + case 'r': + data->retry_count = optint; + break; + case 'f': + data->flags = optint; + break; + case 'w': + data->wdog_pid = find_get_pid(optint); + break; + case 'n': + data->ncp_fd = optint; + break; + case 'i': + data->info_fd = optint; + break; + case 'v': + ret = -ECHRNG; + if (optint < NCP_MOUNT_VERSION_V4) + goto err; + if (optint > NCP_MOUNT_VERSION_V5) + goto err; + version = optint; + break; + + } + } + return 0; +err: + put_pid(data->wdog_pid); + data->wdog_pid = NULL; + return ret; +} + +static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) +{ + struct ncp_mount_data_kernel data; + struct ncp_server *server; + struct inode *root_inode; + struct socket *sock; + int error; + int default_bufsize; +#ifdef CONFIG_NCPFS_PACKET_SIGNING + int options; +#endif + struct ncp_entry_info finfo; + + memset(&data, 0, sizeof(data)); + server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); + if (!server) + return -ENOMEM; + sb->s_fs_info = server; + + error = -EFAULT; + if (raw_data == NULL) + goto out; + switch (*(int*)raw_data) { + case NCP_MOUNT_VERSION: + { + struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; + + data.flags = md->flags; + data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; + data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); + data.wdog_pid = find_get_pid(md->wdog_pid); + data.ncp_fd = md->ncp_fd; + data.time_out = md->time_out; + data.retry_count = md->retry_count; + data.uid = make_kuid(current_user_ns(), md->uid); + data.gid = make_kgid(current_user_ns(), md->gid); + data.file_mode = md->file_mode; + data.dir_mode = md->dir_mode; + data.info_fd = -1; + memcpy(data.mounted_vol, md->mounted_vol, + NCP_VOLNAME_LEN+1); + } + break; + case NCP_MOUNT_VERSION_V4: + { + struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; + + data.flags = md->flags; + data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); + data.wdog_pid = find_get_pid(md->wdog_pid); + data.ncp_fd = md->ncp_fd; + data.time_out = md->time_out; + data.retry_count = md->retry_count; + data.uid = make_kuid(current_user_ns(), md->uid); + data.gid = make_kgid(current_user_ns(), md->gid); + data.file_mode = md->file_mode; + data.dir_mode = md->dir_mode; + data.info_fd = -1; + } + break; + default: + error = -ECHRNG; + if (memcmp(raw_data, "vers", 4) == 0) { + error = ncp_parse_options(&data, raw_data); + } + if (error) + goto out; + break; + } + error = -EINVAL; + if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || + !gid_valid(data.gid)) + goto out; + sock = sockfd_lookup(data.ncp_fd, &error); + if (!sock) + goto out; + + if (sock->type == SOCK_STREAM) + default_bufsize = 0xF000; + else + default_bufsize = 1024; + + sb->s_flags |= SB_NODIRATIME; /* probably even noatime */ + sb->s_maxbytes = 0xFFFFFFFFU; + sb->s_blocksize = 1024; /* Eh... Is this correct? */ + sb->s_blocksize_bits = 10; + sb->s_magic = NCP_SUPER_MAGIC; + sb->s_op = &ncp_sops; + sb->s_d_op = &ncp_dentry_operations; + + server = NCP_SBP(sb); + memset(server, 0, sizeof(*server)); + + error = super_setup_bdi(sb); + if (error) + goto out_fput; + + server->ncp_sock = sock; + + if (data.info_fd != -1) { + struct socket *info_sock = sockfd_lookup(data.info_fd, &error); + if (!info_sock) + goto out_fput; + server->info_sock = info_sock; + error = -EBADFD; + if (info_sock->type != SOCK_STREAM) + goto out_fput2; + } + +/* server->lock = 0; */ + mutex_init(&server->mutex); + server->packet = NULL; +/* server->buffer_size = 0; */ +/* server->conn_status = 0; */ +/* server->root_dentry = NULL; */ +/* server->root_setuped = 0; */ + mutex_init(&server->root_setup_lock); +#ifdef CONFIG_NCPFS_PACKET_SIGNING +/* server->sign_wanted = 0; */ +/* server->sign_active = 0; */ +#endif + init_rwsem(&server->auth_rwsem); + server->auth.auth_type = NCP_AUTH_NONE; +/* server->auth.object_name_len = 0; */ +/* server->auth.object_name = NULL; */ +/* server->auth.object_type = 0; */ +/* server->priv.len = 0; */ +/* server->priv.data = NULL; */ + + server->m = data; + /* Although anything producing this is buggy, it happens + now because of PATH_MAX changes.. */ + if (server->m.time_out < 1) { + server->m.time_out = 10; + pr_info("You need to recompile your ncpfs utils..\n"); + } + server->m.time_out = server->m.time_out * HZ / 100; + server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; + server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; + +#ifdef CONFIG_NCPFS_NLS + /* load the default NLS charsets */ + server->nls_vol = load_nls_default(); + server->nls_io = load_nls_default(); +#endif /* CONFIG_NCPFS_NLS */ + + atomic_set(&server->dentry_ttl, 0); /* no caching */ + + INIT_LIST_HEAD(&server->tx.requests); + mutex_init(&server->rcv.creq_mutex); + server->tx.creq = NULL; + server->rcv.creq = NULL; + + timer_setup(&server->timeout_tm, ncpdgram_timeout_call, 0); +#undef NCP_PACKET_SIZE +#define NCP_PACKET_SIZE 131072 + error = -ENOMEM; + server->packet_size = NCP_PACKET_SIZE; + server->packet = vmalloc(NCP_PACKET_SIZE); + if (server->packet == NULL) + goto out_nls; + server->txbuf = vmalloc(NCP_PACKET_SIZE); + if (server->txbuf == NULL) + goto out_packet; + server->rxbuf = vmalloc(NCP_PACKET_SIZE); + if (server->rxbuf == NULL) + goto out_txbuf; + + lock_sock(sock->sk); + server->data_ready = sock->sk->sk_data_ready; + server->write_space = sock->sk->sk_write_space; + server->error_report = sock->sk->sk_error_report; + sock->sk->sk_user_data = server; + sock->sk->sk_data_ready = ncp_tcp_data_ready; + sock->sk->sk_error_report = ncp_tcp_error_report; + if (sock->type == SOCK_STREAM) { + server->rcv.ptr = (unsigned char*)&server->rcv.buf; + server->rcv.len = 10; + server->rcv.state = 0; + INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); + INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); + sock->sk->sk_write_space = ncp_tcp_write_space; + } else { + INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); + INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); + } + release_sock(sock->sk); + + ncp_lock_server(server); + error = ncp_connect(server); + ncp_unlock_server(server); + if (error < 0) + goto out_rxbuf; + ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb)); + + error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (ncp_negotiate_size_and_options(server, default_bufsize, + NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) + { + if (options != NCP_DEFAULT_OPTIONS) + { + if (ncp_negotiate_size_and_options(server, + default_bufsize, + options & 2, + &(server->buffer_size), &options) != 0) + + { + goto out_disconnect; + } + } + ncp_lock_server(server); + if (options & 2) + server->sign_wanted = 1; + ncp_unlock_server(server); + } + else +#endif /* CONFIG_NCPFS_PACKET_SIGNING */ + if (ncp_negotiate_buffersize(server, default_bufsize, + &(server->buffer_size)) != 0) + goto out_disconnect; + ncp_dbg(1, "bufsize = %d\n", server->buffer_size); + + memset(&finfo, 0, sizeof(finfo)); + finfo.i.attributes = aDIR; + finfo.i.dataStreamSize = 0; /* ignored */ + finfo.i.dirEntNum = 0; + finfo.i.DosDirNum = 0; +#ifdef CONFIG_NCPFS_SMALLDOS + finfo.i.NSCreator = NW_NS_DOS; +#endif + finfo.volume = NCP_NUMBER_OF_VOLUMES; + /* set dates of mountpoint to Jan 1, 1986; 00:00 */ + finfo.i.creationTime = finfo.i.modifyTime + = cpu_to_le16(0x0000); + finfo.i.creationDate = finfo.i.modifyDate + = finfo.i.lastAccessDate + = cpu_to_le16(0x0C21); + finfo.i.nameLen = 0; + finfo.i.entryName[0] = '\0'; + + finfo.opened = 0; + finfo.ino = 2; /* tradition */ + + server->name_space[finfo.volume] = NW_NS_DOS; + + error = -ENOMEM; + root_inode = ncp_iget(sb, &finfo); + if (!root_inode) + goto out_disconnect; + ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber); + sb->s_root = d_make_root(root_inode); + if (!sb->s_root) + goto out_disconnect; + return 0; + +out_disconnect: + ncp_lock_server(server); + ncp_disconnect(server); + ncp_unlock_server(server); +out_rxbuf: + ncp_stop_tasks(server); + vfree(server->rxbuf); +out_txbuf: + vfree(server->txbuf); +out_packet: + vfree(server->packet); +out_nls: +#ifdef CONFIG_NCPFS_NLS + unload_nls(server->nls_io); + unload_nls(server->nls_vol); +#endif + mutex_destroy(&server->rcv.creq_mutex); + mutex_destroy(&server->root_setup_lock); + mutex_destroy(&server->mutex); +out_fput2: + if (server->info_sock) + sockfd_put(server->info_sock); +out_fput: + sockfd_put(sock); +out: + put_pid(data.wdog_pid); + sb->s_fs_info = NULL; + kfree(server); + return error; +} + +static void delayed_free(struct rcu_head *p) +{ + struct ncp_server *server = container_of(p, struct ncp_server, rcu); +#ifdef CONFIG_NCPFS_NLS + /* unload the NLS charsets */ + unload_nls(server->nls_vol); + unload_nls(server->nls_io); +#endif /* CONFIG_NCPFS_NLS */ + kfree(server); +} + +static void ncp_put_super(struct super_block *sb) +{ + struct ncp_server *server = NCP_SBP(sb); + + ncp_lock_server(server); + ncp_disconnect(server); + ncp_unlock_server(server); + + ncp_stop_tasks(server); + + mutex_destroy(&server->rcv.creq_mutex); + mutex_destroy(&server->root_setup_lock); + mutex_destroy(&server->mutex); + + if (server->info_sock) + sockfd_put(server->info_sock); + sockfd_put(server->ncp_sock); + kill_pid(server->m.wdog_pid, SIGTERM, 1); + put_pid(server->m.wdog_pid); + + kfree(server->priv.data); + kfree(server->auth.object_name); + vfree(server->rxbuf); + vfree(server->txbuf); + vfree(server->packet); + call_rcu(&server->rcu, delayed_free); +} + +static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct dentry* d; + struct inode* i; + struct ncp_inode_info* ni; + struct ncp_server* s; + struct ncp_volume_info vi; + struct super_block *sb = dentry->d_sb; + int err; + __u8 dh; + + d = sb->s_root; + if (!d) { + goto dflt; + } + i = d_inode(d); + if (!i) { + goto dflt; + } + ni = NCP_FINFO(i); + if (!ni) { + goto dflt; + } + s = NCP_SBP(sb); + if (!s) { + goto dflt; + } + if (!s->m.mounted_vol[0]) { + goto dflt; + } + + err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh); + if (err) { + goto dflt; + } + err = ncp_get_directory_info(s, dh, &vi); + ncp_dirhandle_free(s, dh); + if (err) { + goto dflt; + } + buf->f_type = NCP_SUPER_MAGIC; + buf->f_bsize = vi.sectors_per_block * 512; + buf->f_blocks = vi.total_blocks; + buf->f_bfree = vi.free_blocks; + buf->f_bavail = vi.free_blocks; + buf->f_files = vi.total_dir_entries; + buf->f_ffree = vi.available_dir_entries; + buf->f_namelen = 12; + return 0; + + /* We cannot say how much disk space is left on a mounted + NetWare Server, because free space is distributed over + volumes, and the current user might have disk quotas. So + free space is not that simple to determine. Our decision + here is to err conservatively. */ + +dflt:; + buf->f_type = NCP_SUPER_MAGIC; + buf->f_bsize = NCP_BLOCK_SIZE; + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_namelen = 12; + return 0; +} + +int ncp_notify_change(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = d_inode(dentry); + int result = 0; + __le32 info_mask; + struct nw_modify_dos_info info; + struct ncp_server *server; + + result = -EIO; + + server = NCP_SERVER(inode); + if (!server) /* How this could happen? */ + goto out; + + result = -EPERM; + if (IS_DEADDIR(d_inode(dentry))) + goto out; + + /* ageing the dentry to force validation */ + ncp_age_dentry(server, dentry); + + result = setattr_prepare(dentry, attr); + if (result < 0) + goto out; + + result = -EPERM; + if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid)) + goto out; + + if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid)) + goto out; + + if (((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & + ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) + goto out; + + info_mask = 0; + memset(&info, 0, sizeof(info)); + +#if 1 + if ((attr->ia_valid & ATTR_MODE) != 0) + { + umode_t newmode = attr->ia_mode; + + info_mask |= DM_ATTRIBUTES; + + if (S_ISDIR(inode->i_mode)) { + newmode &= server->m.dir_mode; + } else { +#ifdef CONFIG_NCPFS_EXTRAS + if (server->m.flags & NCP_MOUNT_EXTRAS) { + /* any non-default execute bit set */ + if (newmode & ~server->m.file_mode & S_IXUGO) + info.attributes |= aSHARED | aSYSTEM; + /* read for group/world and not in default file_mode */ + else if (newmode & ~server->m.file_mode & S_IRUGO) + info.attributes |= aSHARED; + } else +#endif + newmode &= server->m.file_mode; + } + if (newmode & S_IWUGO) + info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + else + info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + +#ifdef CONFIG_NCPFS_NFS_NS + if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { + result = ncp_modify_nfs_info(server, + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum, + attr->ia_mode, 0); + if (result != 0) + goto out; + info.attributes &= ~(aSHARED | aSYSTEM); + { + /* mark partial success */ + struct iattr tmpattr; + + tmpattr.ia_valid = ATTR_MODE; + tmpattr.ia_mode = attr->ia_mode; + + setattr_copy(inode, &tmpattr); + mark_inode_dirty(inode); + } + } +#endif + } +#endif + + /* Do SIZE before attributes, otherwise mtime together with size does not work... + */ + if ((attr->ia_valid & ATTR_SIZE) != 0) { + int written; + + ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size); + + if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { + result = -EACCES; + goto out; + } + ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + attr->ia_size, 0, "", &written); + + /* According to ndir, the changes only take effect after + closing the file */ + ncp_inode_close(inode); + result = ncp_make_closed(inode); + if (result) + goto out; + + if (attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); + mark_inode_dirty(inode); + } + } + if ((attr->ia_valid & ATTR_CTIME) != 0) { + info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); + ncp_date_unix2dos(attr->ia_ctime.tv_sec, + &info.creationTime, &info.creationDate); + } + if ((attr->ia_valid & ATTR_MTIME) != 0) { + info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); + ncp_date_unix2dos(attr->ia_mtime.tv_sec, + &info.modifyTime, &info.modifyDate); + } + if ((attr->ia_valid & ATTR_ATIME) != 0) { + __le16 dummy; + info_mask |= (DM_LAST_ACCESS_DATE); + ncp_date_unix2dos(attr->ia_atime.tv_sec, + &dummy, &info.lastAccessDate); + } + if (info_mask != 0) { + result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), + inode, info_mask, &info); + if (result != 0) { + if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { + /* NetWare seems not to allow this. I + do not know why. So, just tell the + user everything went fine. This is + a terrible hack, but I do not know + how to do this correctly. */ + result = 0; + } else + goto out; + } +#ifdef CONFIG_NCPFS_STRONG + if ((!result) && (info_mask & DM_ATTRIBUTES)) + NCP_FINFO(inode)->nwattr = info.attributes; +#endif + } + if (result) + goto out; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + +out: + if (result > 0) + result = -EACCES; + return result; +} + +static struct dentry *ncp_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) +{ + return mount_nodev(fs_type, flags, data, ncp_fill_super); +} + +static struct file_system_type ncp_fs_type = { + .owner = THIS_MODULE, + .name = "ncpfs", + .mount = ncp_mount, + .kill_sb = kill_anon_super, + .fs_flags = FS_BINARY_MOUNTDATA, +}; +MODULE_ALIAS_FS("ncpfs"); + +static int __init init_ncp_fs(void) +{ + int err; + ncp_dbg(1, "called\n"); + + err = init_inodecache(); + if (err) + goto out1; + err = register_filesystem(&ncp_fs_type); + if (err) + goto out; + return 0; +out: + destroy_inodecache(); +out1: + return err; +} + +static void __exit exit_ncp_fs(void) +{ + ncp_dbg(1, "called\n"); + unregister_filesystem(&ncp_fs_type); + destroy_inodecache(); +} + +module_init(init_ncp_fs) +module_exit(exit_ncp_fs) +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/ncpfs/ioctl.c b/drivers/staging/ncpfs/ioctl.c new file mode 100644 index 000000000000..d378b98cd7b6 --- /dev/null +++ b/drivers/staging/ncpfs/ioctl.c @@ -0,0 +1,923 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ioctl.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998, 1999 Wolfram Pienkoss for NLS + * + */ + +#include <linux/capability.h> +#include <linux/compat.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/ioctl.h> +#include <linux/time.h> +#include <linux/mm.h> +#include <linux/mount.h> +#include <linux/slab.h> +#include <linux/highuid.h> +#include <linux/vmalloc.h> +#include <linux/sched.h> +#include <linux/cred.h> + +#include <linux/uaccess.h> + +#include "ncp_fs.h" + +/* maximum limit for ncp_objectname_ioctl */ +#define NCP_OBJECT_NAME_MAX_LEN 4096 +/* maximum limit for ncp_privatedata_ioctl */ +#define NCP_PRIVATE_DATA_MAX_LEN 8192 +/* maximum negotiable packet size */ +#define NCP_PACKET_SIZE_INTERNAL 65536 + +static int +ncp_get_fs_info(struct ncp_server * server, struct inode *inode, + struct ncp_fs_info __user *arg) +{ + struct ncp_fs_info info; + + if (copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; + + if (info.version != NCP_GET_FS_INFO_VERSION) { + ncp_dbg(1, "info.version invalid: %d\n", info.version); + return -EINVAL; + } + /* TODO: info.addr = server->m.serv_addr; */ + SET_UID(info.mounted_uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid)); + info.connection = server->connection; + info.buffer_size = server->buffer_size; + info.volume_number = NCP_FINFO(inode)->volNumber; + info.directory_id = NCP_FINFO(inode)->DosDirNum; + + if (copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +static int +ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode, + struct ncp_fs_info_v2 __user * arg) +{ + struct ncp_fs_info_v2 info2; + + if (copy_from_user(&info2, arg, sizeof(info2))) + return -EFAULT; + + if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { + ncp_dbg(1, "info.version invalid: %d\n", info2.version); + return -EINVAL; + } + info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + info2.connection = server->connection; + info2.buffer_size = server->buffer_size; + info2.volume_number = NCP_FINFO(inode)->volNumber; + info2.directory_id = NCP_FINFO(inode)->DosDirNum; + info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; + + if (copy_to_user(arg, &info2, sizeof(info2))) + return -EFAULT; + return 0; +} + +#ifdef CONFIG_COMPAT +struct compat_ncp_objectname_ioctl +{ + s32 auth_type; + u32 object_name_len; + compat_caddr_t object_name; /* a userspace data, in most cases user name */ +}; + +struct compat_ncp_fs_info_v2 { + s32 version; + u32 mounted_uid; + u32 connection; + u32 buffer_size; + + u32 volume_number; + u32 directory_id; + + u32 dummy1; + u32 dummy2; + u32 dummy3; +}; + +struct compat_ncp_ioctl_request { + u32 function; + u32 size; + compat_caddr_t data; +}; + +struct compat_ncp_privatedata_ioctl +{ + u32 len; + compat_caddr_t data; /* ~1000 for NDS */ +}; + +#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2) +#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request) +#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl) +#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl) +#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl) +#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) + +static int +ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode, + struct compat_ncp_fs_info_v2 __user * arg) +{ + struct compat_ncp_fs_info_v2 info2; + + if (copy_from_user(&info2, arg, sizeof(info2))) + return -EFAULT; + + if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { + ncp_dbg(1, "info.version invalid: %d\n", info2.version); + return -EINVAL; + } + info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + info2.connection = server->connection; + info2.buffer_size = server->buffer_size; + info2.volume_number = NCP_FINFO(inode)->volNumber; + info2.directory_id = NCP_FINFO(inode)->DosDirNum; + info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; + + if (copy_to_user(arg, &info2, sizeof(info2))) + return -EFAULT; + return 0; +} +#endif + +#define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16) +#define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32) +#define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64) + +#ifdef CONFIG_NCPFS_NLS +/* Here we are select the iocharset and the codepage for NLS. + * Thanks Petr Vandrovec for idea and many hints. + */ +static int +ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) +{ + struct ncp_nls_ioctl user; + struct nls_table *codepage; + struct nls_table *iocharset; + struct nls_table *oldset_io; + struct nls_table *oldset_cp; + int utf8; + int err; + + if (copy_from_user(&user, arg, sizeof(user))) + return -EFAULT; + + codepage = NULL; + user.codepage[NCP_IOCSNAME_LEN] = 0; + if (!user.codepage[0] || !strcmp(user.codepage, "default")) + codepage = load_nls_default(); + else { + codepage = load_nls(user.codepage); + if (!codepage) { + return -EBADRQC; + } + } + + iocharset = NULL; + user.iocharset[NCP_IOCSNAME_LEN] = 0; + if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { + iocharset = load_nls_default(); + utf8 = 0; + } else if (!strcmp(user.iocharset, "utf8")) { + iocharset = load_nls_default(); + utf8 = 1; + } else { + iocharset = load_nls(user.iocharset); + if (!iocharset) { + unload_nls(codepage); + return -EBADRQC; + } + utf8 = 0; + } + + mutex_lock(&server->root_setup_lock); + if (server->root_setuped) { + oldset_cp = codepage; + oldset_io = iocharset; + err = -EBUSY; + } else { + if (utf8) + NCP_SET_FLAG(server, NCP_FLAG_UTF8); + else + NCP_CLR_FLAG(server, NCP_FLAG_UTF8); + oldset_cp = server->nls_vol; + server->nls_vol = codepage; + oldset_io = server->nls_io; + server->nls_io = iocharset; + err = 0; + } + mutex_unlock(&server->root_setup_lock); + unload_nls(oldset_cp); + unload_nls(oldset_io); + + return err; +} + +static int +ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) +{ + struct ncp_nls_ioctl user; + int len; + + memset(&user, 0, sizeof(user)); + mutex_lock(&server->root_setup_lock); + if (server->nls_vol && server->nls_vol->charset) { + len = strlen(server->nls_vol->charset); + if (len > NCP_IOCSNAME_LEN) + len = NCP_IOCSNAME_LEN; + strncpy(user.codepage, server->nls_vol->charset, len); + user.codepage[len] = 0; + } + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) + strcpy(user.iocharset, "utf8"); + else if (server->nls_io && server->nls_io->charset) { + len = strlen(server->nls_io->charset); + if (len > NCP_IOCSNAME_LEN) + len = NCP_IOCSNAME_LEN; + strncpy(user.iocharset, server->nls_io->charset, len); + user.iocharset[len] = 0; + } + mutex_unlock(&server->root_setup_lock); + + if (copy_to_user(arg, &user, sizeof(user))) + return -EFAULT; + return 0; +} +#endif /* CONFIG_NCPFS_NLS */ + +static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg) +{ + struct ncp_server *server = NCP_SERVER(inode); + int result; + struct ncp_ioctl_request request; + char* bouncebuffer; + void __user *argp = (void __user *)arg; + + switch (cmd) { +#ifdef CONFIG_COMPAT + case NCP_IOC_NCPREQUEST_32: +#endif + case NCP_IOC_NCPREQUEST: +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_NCPREQUEST_32) { + struct compat_ncp_ioctl_request request32; + if (copy_from_user(&request32, argp, sizeof(request32))) + return -EFAULT; + request.function = request32.function; + request.size = request32.size; + request.data = compat_ptr(request32.data); + } else +#endif + if (copy_from_user(&request, argp, sizeof(request))) + return -EFAULT; + + if ((request.function > 255) + || (request.size > + NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) { + return -EINVAL; + } + bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL); + if (!bouncebuffer) + return -ENOMEM; + if (copy_from_user(bouncebuffer, request.data, request.size)) { + vfree(bouncebuffer); + return -EFAULT; + } + ncp_lock_server(server); + + /* FIXME: We hack around in the server's structures + here to be able to use ncp_request */ + + server->has_subfunction = 0; + server->current_size = request.size; + memcpy(server->packet, bouncebuffer, request.size); + + result = ncp_request2(server, request.function, + bouncebuffer, NCP_PACKET_SIZE_INTERNAL); + if (result < 0) + result = -EIO; + else + result = server->reply_size; + ncp_unlock_server(server); + ncp_dbg(1, "copy %d bytes\n", result); + if (result >= 0) + if (copy_to_user(request.data, bouncebuffer, result)) + result = -EFAULT; + vfree(bouncebuffer); + return result; + + case NCP_IOC_CONN_LOGGED_IN: + + if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) + return -EINVAL; + mutex_lock(&server->root_setup_lock); + if (server->root_setuped) + result = -EBUSY; + else { + result = ncp_conn_logged_in(inode->i_sb); + if (result == 0) + server->root_setuped = 1; + } + mutex_unlock(&server->root_setup_lock); + return result; + + case NCP_IOC_GET_FS_INFO: + return ncp_get_fs_info(server, inode, argp); + + case NCP_IOC_GET_FS_INFO_V2: + return ncp_get_fs_info_v2(server, inode, argp); + +#ifdef CONFIG_COMPAT + case NCP_IOC_GET_FS_INFO_V2_32: + return ncp_get_compat_fs_info_v2(server, inode, argp); +#endif + /* we have too many combinations of CONFIG_COMPAT, + * CONFIG_64BIT and CONFIG_UID16, so just handle + * any of the possible ioctls */ + case NCP_IOC_GETMOUNTUID16: + { + u16 uid; + + SET_UID(uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid)); + if (put_user(uid, (u16 __user *)argp)) + return -EFAULT; + return 0; + } + case NCP_IOC_GETMOUNTUID32: + { + uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + if (put_user(uid, (u32 __user *)argp)) + return -EFAULT; + return 0; + } + case NCP_IOC_GETMOUNTUID64: + { + uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + if (put_user(uid, (u64 __user *)argp)) + return -EFAULT; + return 0; + } + case NCP_IOC_GETROOT: + { + struct ncp_setroot_ioctl sr; + + result = -EACCES; + mutex_lock(&server->root_setup_lock); + if (server->m.mounted_vol[0]) { + struct dentry* dentry = inode->i_sb->s_root; + + if (dentry) { + struct inode* s_inode = d_inode(dentry); + + if (s_inode) { + sr.volNumber = NCP_FINFO(s_inode)->volNumber; + sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; + sr.namespace = server->name_space[sr.volNumber]; + result = 0; + } else + ncp_dbg(1, "d_inode(s_root)==NULL\n"); + } else + ncp_dbg(1, "s_root==NULL\n"); + } else { + sr.volNumber = -1; + sr.namespace = 0; + sr.dirEntNum = 0; + result = 0; + } + mutex_unlock(&server->root_setup_lock); + if (!result && copy_to_user(argp, &sr, sizeof(sr))) + result = -EFAULT; + return result; + } + + case NCP_IOC_SETROOT: + { + struct ncp_setroot_ioctl sr; + __u32 vnum; + __le32 de; + __le32 dosde; + struct dentry* dentry; + + if (copy_from_user(&sr, argp, sizeof(sr))) + return -EFAULT; + mutex_lock(&server->root_setup_lock); + if (server->root_setuped) + result = -EBUSY; + else { + if (sr.volNumber < 0) { + server->m.mounted_vol[0] = 0; + vnum = NCP_NUMBER_OF_VOLUMES; + de = 0; + dosde = 0; + result = 0; + } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { + result = -EINVAL; + } else if (ncp_mount_subdir(server, sr.volNumber, + sr.namespace, sr.dirEntNum, + &vnum, &de, &dosde)) { + result = -ENOENT; + } else + result = 0; + + if (result == 0) { + dentry = inode->i_sb->s_root; + if (dentry) { + struct inode* s_inode = d_inode(dentry); + + if (s_inode) { + NCP_FINFO(s_inode)->volNumber = vnum; + NCP_FINFO(s_inode)->dirEntNum = de; + NCP_FINFO(s_inode)->DosDirNum = dosde; + server->root_setuped = 1; + } else { + ncp_dbg(1, "d_inode(s_root)==NULL\n"); + result = -EIO; + } + } else { + ncp_dbg(1, "s_root==NULL\n"); + result = -EIO; + } + } + } + mutex_unlock(&server->root_setup_lock); + + return result; + } + +#ifdef CONFIG_NCPFS_PACKET_SIGNING + case NCP_IOC_SIGN_INIT: + { + struct ncp_sign_init sign; + + if (argp) + if (copy_from_user(&sign, argp, sizeof(sign))) + return -EFAULT; + ncp_lock_server(server); + mutex_lock(&server->rcv.creq_mutex); + if (argp) { + if (server->sign_wanted) { + memcpy(server->sign_root,sign.sign_root,8); + memcpy(server->sign_last,sign.sign_last,16); + server->sign_active = 1; + } + /* ignore when signatures not wanted */ + } else { + server->sign_active = 0; + } + mutex_unlock(&server->rcv.creq_mutex); + ncp_unlock_server(server); + return 0; + } + + case NCP_IOC_SIGN_WANTED: + { + int state; + + ncp_lock_server(server); + state = server->sign_wanted; + ncp_unlock_server(server); + if (put_user(state, (int __user *)argp)) + return -EFAULT; + return 0; + } + + case NCP_IOC_SET_SIGN_WANTED: + { + int newstate; + + /* get only low 8 bits... */ + if (get_user(newstate, (unsigned char __user *)argp)) + return -EFAULT; + result = 0; + ncp_lock_server(server); + if (server->sign_active) { + /* cannot turn signatures OFF when active */ + if (!newstate) + result = -EINVAL; + } else { + server->sign_wanted = newstate != 0; + } + ncp_unlock_server(server); + return result; + } + +#endif /* CONFIG_NCPFS_PACKET_SIGNING */ + +#ifdef CONFIG_NCPFS_IOCTL_LOCKING + case NCP_IOC_LOCKUNLOCK: + { + struct ncp_lock_ioctl rqdata; + + if (copy_from_user(&rqdata, argp, sizeof(rqdata))) + return -EFAULT; + if (rqdata.origin != 0) + return -EINVAL; + /* check for cmd */ + switch (rqdata.cmd) { + case NCP_LOCK_EX: + case NCP_LOCK_SH: + if (rqdata.timeout < 0) + return -EINVAL; + if (rqdata.timeout == 0) + rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; + else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT) + rqdata.timeout = NCP_LOCK_MAX_TIMEOUT; + break; + case NCP_LOCK_LOG: + rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; /* has no effect */ + case NCP_LOCK_CLEAR: + break; + default: + return -EINVAL; + } + /* locking needs both read and write access */ + if ((result = ncp_make_open(inode, O_RDWR)) != 0) + { + return result; + } + result = -EISDIR; + if (!S_ISREG(inode->i_mode)) + goto outrel; + if (rqdata.cmd == NCP_LOCK_CLEAR) + { + result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + rqdata.offset, + rqdata.length); + if (result > 0) result = 0; /* no such lock */ + } + else + { + int lockcmd; + + switch (rqdata.cmd) + { + case NCP_LOCK_EX: lockcmd=1; break; + case NCP_LOCK_SH: lockcmd=3; break; + default: lockcmd=0; break; + } + result = ncp_LogPhysicalRecord(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + lockcmd, + rqdata.offset, + rqdata.length, + rqdata.timeout); + if (result > 0) result = -EAGAIN; + } +outrel: + ncp_inode_close(inode); + return result; + } +#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + +#ifdef CONFIG_COMPAT + case NCP_IOC_GETOBJECTNAME_32: + { + struct compat_ncp_objectname_ioctl user; + size_t outl; + + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + down_read(&server->auth_rwsem); + user.auth_type = server->auth.auth_type; + outl = user.object_name_len; + user.object_name_len = server->auth.object_name_len; + if (outl > user.object_name_len) + outl = user.object_name_len; + result = 0; + if (outl) { + if (copy_to_user(compat_ptr(user.object_name), + server->auth.object_name, + outl)) + result = -EFAULT; + } + up_read(&server->auth_rwsem); + if (!result && copy_to_user(argp, &user, sizeof(user))) + result = -EFAULT; + return result; + } +#endif + + case NCP_IOC_GETOBJECTNAME: + { + struct ncp_objectname_ioctl user; + size_t outl; + + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + down_read(&server->auth_rwsem); + user.auth_type = server->auth.auth_type; + outl = user.object_name_len; + user.object_name_len = server->auth.object_name_len; + if (outl > user.object_name_len) + outl = user.object_name_len; + result = 0; + if (outl) { + if (copy_to_user(user.object_name, + server->auth.object_name, + outl)) + result = -EFAULT; + } + up_read(&server->auth_rwsem); + if (!result && copy_to_user(argp, &user, sizeof(user))) + result = -EFAULT; + return result; + } + +#ifdef CONFIG_COMPAT + case NCP_IOC_SETOBJECTNAME_32: +#endif + case NCP_IOC_SETOBJECTNAME: + { + struct ncp_objectname_ioctl user; + void* newname; + void* oldname; + size_t oldnamelen; + void* oldprivate; + size_t oldprivatelen; + +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_SETOBJECTNAME_32) { + struct compat_ncp_objectname_ioctl user32; + if (copy_from_user(&user32, argp, sizeof(user32))) + return -EFAULT; + user.auth_type = user32.auth_type; + user.object_name_len = user32.object_name_len; + user.object_name = compat_ptr(user32.object_name); + } else +#endif + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + + if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) + return -ENOMEM; + if (user.object_name_len) { + newname = memdup_user(user.object_name, + user.object_name_len); + if (IS_ERR(newname)) + return PTR_ERR(newname); + } else { + newname = NULL; + } + down_write(&server->auth_rwsem); + oldname = server->auth.object_name; + oldnamelen = server->auth.object_name_len; + oldprivate = server->priv.data; + oldprivatelen = server->priv.len; + server->auth.auth_type = user.auth_type; + server->auth.object_name_len = user.object_name_len; + server->auth.object_name = newname; + server->priv.len = 0; + server->priv.data = NULL; + up_write(&server->auth_rwsem); + kfree(oldprivate); + kfree(oldname); + return 0; + } + +#ifdef CONFIG_COMPAT + case NCP_IOC_GETPRIVATEDATA_32: +#endif + case NCP_IOC_GETPRIVATEDATA: + { + struct ncp_privatedata_ioctl user; + size_t outl; + +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_GETPRIVATEDATA_32) { + struct compat_ncp_privatedata_ioctl user32; + if (copy_from_user(&user32, argp, sizeof(user32))) + return -EFAULT; + user.len = user32.len; + user.data = compat_ptr(user32.data); + } else +#endif + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + + down_read(&server->auth_rwsem); + outl = user.len; + user.len = server->priv.len; + if (outl > user.len) outl = user.len; + result = 0; + if (outl) { + if (copy_to_user(user.data, + server->priv.data, + outl)) + result = -EFAULT; + } + up_read(&server->auth_rwsem); + if (result) + return result; +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_GETPRIVATEDATA_32) { + struct compat_ncp_privatedata_ioctl user32; + user32.len = user.len; + user32.data = (unsigned long) user.data; + if (copy_to_user(argp, &user32, sizeof(user32))) + return -EFAULT; + } else +#endif + if (copy_to_user(argp, &user, sizeof(user))) + return -EFAULT; + + return 0; + } + +#ifdef CONFIG_COMPAT + case NCP_IOC_SETPRIVATEDATA_32: +#endif + case NCP_IOC_SETPRIVATEDATA: + { + struct ncp_privatedata_ioctl user; + void* new; + void* old; + size_t oldlen; + +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_SETPRIVATEDATA_32) { + struct compat_ncp_privatedata_ioctl user32; + if (copy_from_user(&user32, argp, sizeof(user32))) + return -EFAULT; + user.len = user32.len; + user.data = compat_ptr(user32.data); + } else +#endif + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + + if (user.len > NCP_PRIVATE_DATA_MAX_LEN) + return -ENOMEM; + if (user.len) { + new = memdup_user(user.data, user.len); + if (IS_ERR(new)) + return PTR_ERR(new); + } else { + new = NULL; + } + down_write(&server->auth_rwsem); + old = server->priv.data; + oldlen = server->priv.len; + server->priv.len = user.len; + server->priv.data = new; + up_write(&server->auth_rwsem); + kfree(old); + return 0; + } + +#ifdef CONFIG_NCPFS_NLS + case NCP_IOC_SETCHARSETS: + return ncp_set_charsets(server, argp); + + case NCP_IOC_GETCHARSETS: + return ncp_get_charsets(server, argp); + +#endif /* CONFIG_NCPFS_NLS */ + + case NCP_IOC_SETDENTRYTTL: + { + u_int32_t user; + + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + /* 20 secs at most... */ + if (user > 20000) + return -EINVAL; + user = (user * HZ) / 1000; + atomic_set(&server->dentry_ttl, user); + return 0; + } + + case NCP_IOC_GETDENTRYTTL: + { + u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ; + if (copy_to_user(argp, &user, sizeof(user))) + return -EFAULT; + return 0; + } + + } + return -EINVAL; +} + +long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct ncp_server *server = NCP_SERVER(inode); + kuid_t uid = current_uid(); + int need_drop_write = 0; + long ret; + + switch (cmd) { + case NCP_IOC_SETCHARSETS: + case NCP_IOC_CONN_LOGGED_IN: + case NCP_IOC_SETROOT: + if (!capable(CAP_SYS_ADMIN)) { + ret = -EPERM; + goto out; + } + break; + } + if (!uid_eq(server->m.mounted_uid, uid)) { + switch (cmd) { + /* + * Only mount owner can issue these ioctls. Information + * necessary to authenticate to other NDS servers are + * stored here. + */ + case NCP_IOC_GETOBJECTNAME: + case NCP_IOC_SETOBJECTNAME: + case NCP_IOC_GETPRIVATEDATA: + case NCP_IOC_SETPRIVATEDATA: +#ifdef CONFIG_COMPAT + case NCP_IOC_GETOBJECTNAME_32: + case NCP_IOC_SETOBJECTNAME_32: + case NCP_IOC_GETPRIVATEDATA_32: + case NCP_IOC_SETPRIVATEDATA_32: +#endif + ret = -EACCES; + goto out; + /* + * These require write access on the inode if user id + * does not match. Note that they do not write to the + * file... But old code did mnt_want_write, so I keep + * it as is. Of course not for mountpoint owner, as + * that breaks read-only mounts altogether as ncpmount + * needs working NCP_IOC_NCPREQUEST and + * NCP_IOC_GET_FS_INFO. Some of these codes (setdentryttl, + * signinit, setsignwanted) should be probably restricted + * to owner only, or even more to CAP_SYS_ADMIN). + */ + case NCP_IOC_GET_FS_INFO: + case NCP_IOC_GET_FS_INFO_V2: + case NCP_IOC_NCPREQUEST: + case NCP_IOC_SETDENTRYTTL: + case NCP_IOC_SIGN_INIT: + case NCP_IOC_LOCKUNLOCK: + case NCP_IOC_SET_SIGN_WANTED: +#ifdef CONFIG_COMPAT + case NCP_IOC_GET_FS_INFO_V2_32: + case NCP_IOC_NCPREQUEST_32: +#endif + ret = mnt_want_write_file(filp); + if (ret) + goto out; + need_drop_write = 1; + ret = inode_permission(inode, MAY_WRITE); + if (ret) + goto outDropWrite; + break; + /* + * Read access required. + */ + case NCP_IOC_GETMOUNTUID16: + case NCP_IOC_GETMOUNTUID32: + case NCP_IOC_GETMOUNTUID64: + case NCP_IOC_GETROOT: + case NCP_IOC_SIGN_WANTED: + ret = inode_permission(inode, MAY_READ); + if (ret) + goto out; + break; + /* + * Anybody can read these. + */ + case NCP_IOC_GETCHARSETS: + case NCP_IOC_GETDENTRYTTL: + default: + /* Three codes below are protected by CAP_SYS_ADMIN above. */ + case NCP_IOC_SETCHARSETS: + case NCP_IOC_CONN_LOGGED_IN: + case NCP_IOC_SETROOT: + break; + } + } + ret = __ncp_ioctl(inode, cmd, arg); +outDropWrite: + if (need_drop_write) + mnt_drop_write_file(filp); +out: + return ret; +} + +#ifdef CONFIG_COMPAT +long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + arg = (unsigned long) compat_ptr(arg); + ret = ncp_ioctl(file, cmd, arg); + return ret; +} +#endif diff --git a/drivers/staging/ncpfs/mmap.c b/drivers/staging/ncpfs/mmap.c new file mode 100644 index 000000000000..a5c5cf2ff007 --- /dev/null +++ b/drivers/staging/ncpfs/mmap.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mmap.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * + */ + +#include <linux/stat.h> +#include <linux/time.h> +#include <linux/kernel.h> +#include <linux/gfp.h> +#include <linux/mm.h> +#include <linux/shm.h> +#include <linux/errno.h> +#include <linux/mman.h> +#include <linux/string.h> +#include <linux/fcntl.h> +#include <linux/memcontrol.h> + +#include <linux/uaccess.h> + +#include "ncp_fs.h" + +/* + * Fill in the supplied page for mmap + * XXX: how are we excluding truncate/invalidate here? Maybe need to lock + * page? + */ +static int ncp_file_mmap_fault(struct vm_fault *vmf) +{ + struct inode *inode = file_inode(vmf->vma->vm_file); + char *pg_addr; + unsigned int already_read; + unsigned int count; + int bufsize; + int pos; /* XXX: loff_t ? */ + + /* + * ncpfs has nothing against high pages as long + * as recvmsg and memset works on it + */ + vmf->page = alloc_page(GFP_HIGHUSER); + if (!vmf->page) + return VM_FAULT_OOM; + pg_addr = kmap(vmf->page); + pos = vmf->pgoff << PAGE_SHIFT; + + count = PAGE_SIZE; + /* what we can read in one go */ + bufsize = NCP_SERVER(inode)->buffer_size; + + already_read = 0; + if (ncp_make_open(inode, O_RDONLY) >= 0) { + while (already_read < count) { + int read_this_time; + int to_read; + + to_read = bufsize - (pos % bufsize); + + to_read = min_t(unsigned int, to_read, count - already_read); + + if (ncp_read_kernel(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_read, + pg_addr + already_read, + &read_this_time) != 0) { + read_this_time = 0; + } + pos += read_this_time; + already_read += read_this_time; + + if (read_this_time < to_read) { + break; + } + } + ncp_inode_close(inode); + + } + + if (already_read < PAGE_SIZE) + memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); + flush_dcache_page(vmf->page); + kunmap(vmf->page); + + /* + * If I understand ncp_read_kernel() properly, the above always + * fetches from the network, here the analogue of disk. + * -- nyc + */ + count_vm_event(PGMAJFAULT); + count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT); + return VM_FAULT_MAJOR; +} + +static const struct vm_operations_struct ncp_file_mmap = +{ + .fault = ncp_file_mmap_fault, +}; + + +/* This is used for a general mmap of a ncp file */ +int ncp_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct inode *inode = file_inode(file); + + ncp_dbg(1, "called\n"); + + if (!ncp_conn_valid(NCP_SERVER(inode))) + return -EIO; + + /* only PAGE_COW or read-only supported now */ + if (vma->vm_flags & VM_SHARED) + return -EINVAL; + /* we do not support files bigger than 4GB... We eventually + supports just 4GB... */ + if (vma_pages(vma) + vma->vm_pgoff + > (1U << (32 - PAGE_SHIFT))) + return -EFBIG; + + vma->vm_ops = &ncp_file_mmap; + file_accessed(file); + return 0; +} diff --git a/drivers/staging/ncpfs/ncp_fs.h b/drivers/staging/ncpfs/ncp_fs.h new file mode 100644 index 000000000000..bdd262b6c198 --- /dev/null +++ b/drivers/staging/ncpfs/ncp_fs.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/ncp_fs.h> +#include "ncp_fs_i.h" +#include "ncp_fs_sb.h" + +#undef NCPFS_PARANOIA +#ifdef NCPFS_PARANOIA +#define ncp_vdbg(fmt, ...) \ + pr_debug(fmt, ##__VA_ARGS__) +#else +#define ncp_vdbg(fmt, ...) \ +do { \ + if (0) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) +#endif + +#ifndef DEBUG_NCP +#define DEBUG_NCP 0 +#endif + +#if DEBUG_NCP > 0 && !defined(DEBUG) +#define DEBUG +#endif + +#define ncp_dbg(level, fmt, ...) \ +do { \ + if (level <= DEBUG_NCP) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) + +#define NCP_MAX_RPC_TIMEOUT (6*HZ) + + +struct ncp_entry_info { + struct nw_info_struct i; + ino_t ino; + int opened; + int access; + unsigned int volume; + __u8 file_handle[6]; +}; + +static inline struct ncp_server *NCP_SBP(const struct super_block *sb) +{ + return sb->s_fs_info; +} + +#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) +static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode) +{ + return container_of(inode, struct ncp_inode_info, vfs_inode); +} + +/* linux/fs/ncpfs/inode.c */ +int ncp_notify_change(struct dentry *, struct iattr *); +struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *); +void ncp_update_inode(struct inode *, struct ncp_entry_info *); +void ncp_update_inode2(struct inode *, struct ncp_entry_info *); + +/* linux/fs/ncpfs/dir.c */ +extern const struct inode_operations ncp_dir_inode_operations; +extern const struct file_operations ncp_dir_operations; +extern const struct dentry_operations ncp_dentry_operations; +int ncp_conn_logged_in(struct super_block *); +int ncp_date_dos2unix(__le16 time, __le16 date); +void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); + +/* linux/fs/ncpfs/ioctl.c */ +long ncp_ioctl(struct file *, unsigned int, unsigned long); +long ncp_compat_ioctl(struct file *, unsigned int, unsigned long); + +/* linux/fs/ncpfs/sock.c */ +int ncp_request2(struct ncp_server *server, int function, + void* reply, int max_reply_size); +static inline int ncp_request(struct ncp_server *server, int function) { + return ncp_request2(server, function, server->packet, server->packet_size); +} +int ncp_connect(struct ncp_server *server); +int ncp_disconnect(struct ncp_server *server); +void ncp_lock_server(struct ncp_server *server); +void ncp_unlock_server(struct ncp_server *server); + +/* linux/fs/ncpfs/symlink.c */ +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) +extern const struct address_space_operations ncp_symlink_aops; +int ncp_symlink(struct inode*, struct dentry*, const char*); +#endif + +/* linux/fs/ncpfs/file.c */ +extern const struct inode_operations ncp_file_inode_operations; +extern const struct file_operations ncp_file_operations; +int ncp_make_open(struct inode *, int); + +/* linux/fs/ncpfs/mmap.c */ +int ncp_mmap(struct file *, struct vm_area_struct *); + +/* linux/fs/ncpfs/ncplib_kernel.c */ +int ncp_make_closed(struct inode *); + +#include "ncplib_kernel.h" diff --git a/drivers/staging/ncpfs/ncp_fs_i.h b/drivers/staging/ncpfs/ncp_fs_i.h new file mode 100644 index 000000000000..3432bafb53a5 --- /dev/null +++ b/drivers/staging/ncpfs/ncp_fs_i.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncp_fs_i.h + * + * Copyright (C) 1995 Volker Lendecke + * + */ + +#ifndef _LINUX_NCP_FS_I +#define _LINUX_NCP_FS_I + +/* + * This is the ncpfs part of the inode structure. This must contain + * all the information we need to work with an inode after creation. + */ +struct ncp_inode_info { + __le32 dirEntNum; + __le32 DosDirNum; + __u8 volNumber; + __le32 nwattr; + struct mutex open_mutex; + atomic_t opened; + int access; + int flags; +#define NCPI_KLUDGE_SYMLINK 0x0001 +#define NCPI_DIR_CACHE 0x0002 + __u8 file_handle[6]; + struct inode vfs_inode; +}; + +#endif /* _LINUX_NCP_FS_I */ diff --git a/drivers/staging/ncpfs/ncp_fs_sb.h b/drivers/staging/ncpfs/ncp_fs_sb.h new file mode 100644 index 000000000000..f06cde4adf71 --- /dev/null +++ b/drivers/staging/ncpfs/ncp_fs_sb.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncp_fs_sb.h + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * + */ + +#ifndef _NCP_FS_SB +#define _NCP_FS_SB + +#include <linux/types.h> +#include <linux/ncp_mount.h> +#include <linux/net.h> +#include <linux/mutex.h> +#include <linux/backing-dev.h> +#include <linux/workqueue.h> + +#define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */ + +struct sock; + +struct ncp_mount_data_kernel { + unsigned long flags; /* NCP_MOUNT_* flags */ + unsigned int int_flags; /* internal flags */ +#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001 + kuid_t mounted_uid; /* Who may umount() this filesystem? */ + struct pid *wdog_pid; /* Who cares for our watchdog packets? */ + unsigned int ncp_fd; /* The socket to the ncp port */ + unsigned int time_out; /* How long should I wait after + sending a NCP request? */ + unsigned int retry_count; /* And how often should I retry? */ + unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; + kuid_t uid; + kgid_t gid; + umode_t file_mode; + umode_t dir_mode; + int info_fd; +}; + +struct ncp_server { + struct rcu_head rcu; + struct ncp_mount_data_kernel m; /* Nearly all of the mount data is of + interest for us later, so we store + it completely. */ + + __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; + + struct socket *ncp_sock;/* ncp socket */ + struct socket *info_sock; + + u8 sequence; + u8 task; + u16 connection; /* Remote connection number */ + + u8 completion; /* Status message from server */ + u8 conn_status; /* Bit 4 = 1 ==> Server going down, no + requests allowed anymore. + Bit 0 = 1 ==> Server is down. */ + + int buffer_size; /* Negotiated bufsize */ + + int reply_size; /* Size of last reply */ + + int packet_size; + unsigned char *packet; /* Here we prepare requests and + receive replies */ + unsigned char *txbuf; /* Storage for current request */ + unsigned char *rxbuf; /* Storage for reply to current request */ + + int lock; /* To prevent mismatch in protocols. */ + struct mutex mutex; + + int current_size; /* for packet preparation */ + int has_subfunction; + int ncp_reply_size; + + int root_setuped; + struct mutex root_setup_lock; + + /* info for packet signing */ + int sign_wanted; /* 1=Server needs signed packets */ + int sign_active; /* 0=don't do signing, 1=do */ + char sign_root[8]; /* generated from password and encr. key */ + char sign_last[16]; + + /* Authentication info: NDS or BINDERY, username */ + struct { + int auth_type; + size_t object_name_len; + void* object_name; + int object_type; + } auth; + /* Password info */ + struct { + size_t len; + void* data; + } priv; + struct rw_semaphore auth_rwsem; + + /* nls info: codepage for volume and charset for I/O */ + struct nls_table *nls_vol; + struct nls_table *nls_io; + + /* maximum age in jiffies */ + atomic_t dentry_ttl; + + /* miscellaneous */ + unsigned int flags; + + spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */ + + void (*data_ready)(struct sock* sk); + void (*error_report)(struct sock* sk); + void (*write_space)(struct sock* sk); /* STREAM mode only */ + struct { + struct work_struct tq; /* STREAM/DGRAM: data/error ready */ + struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */ + struct mutex creq_mutex; /* DGRAM only: lock accesses to rcv.creq */ + + unsigned int state; /* STREAM only: receiver state */ + struct { + __u32 magic __packed; + __u32 len __packed; + __u16 type __packed; + __u16 p1 __packed; + __u16 p2 __packed; + __u16 p3 __packed; + __u16 type2 __packed; + } buf; /* STREAM only: temporary buffer */ + unsigned char* ptr; /* STREAM only: pointer to data */ + size_t len; /* STREAM only: length of data to receive */ + } rcv; + struct { + struct list_head requests; /* STREAM only: queued requests */ + struct work_struct tq; /* STREAM only: transmitter ready */ + struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */ + } tx; + struct timer_list timeout_tm; /* DGRAM only: timeout timer */ + struct work_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */ + int timeout_last; /* DGRAM only: current timeout length */ + int timeout_retries; /* DGRAM only: retries left */ + struct { + size_t len; + __u8 data[128]; + } unexpected_packet; +}; + +extern void ncp_tcp_rcv_proc(struct work_struct *work); +extern void ncp_tcp_tx_proc(struct work_struct *work); +extern void ncpdgram_rcv_proc(struct work_struct *work); +extern void ncpdgram_timeout_proc(struct work_struct *work); +extern void ncpdgram_timeout_call(struct timer_list *t); +extern void ncp_tcp_data_ready(struct sock* sk); +extern void ncp_tcp_write_space(struct sock* sk); +extern void ncp_tcp_error_report(struct sock* sk); + +#define NCP_FLAG_UTF8 1 + +#define NCP_CLR_FLAG(server, flag) ((server)->flags &= ~(flag)) +#define NCP_SET_FLAG(server, flag) ((server)->flags |= (flag)) +#define NCP_IS_FLAG(server, flag) ((server)->flags & (flag)) + +static inline int ncp_conn_valid(struct ncp_server *server) +{ + return ((server->conn_status & 0x11) == 0); +} + +static inline void ncp_invalidate_conn(struct ncp_server *server) +{ + server->conn_status |= 0x01; +} + +#endif diff --git a/drivers/staging/ncpfs/ncplib_kernel.c b/drivers/staging/ncpfs/ncplib_kernel.c new file mode 100644 index 000000000000..804adfebba2f --- /dev/null +++ b/drivers/staging/ncpfs/ncplib_kernel.c @@ -0,0 +1,1322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ncplib_kernel.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1999 Wolfram Pienkoss for NLS + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include "ncp_fs.h" + +static inline void assert_server_locked(struct ncp_server *server) +{ + if (server->lock == 0) { + ncp_dbg(1, "server not locked!\n"); + } +} + +static void ncp_add_byte(struct ncp_server *server, __u8 x) +{ + assert_server_locked(server); + *(__u8 *) (&(server->packet[server->current_size])) = x; + server->current_size += 1; + return; +} + +static void ncp_add_word(struct ncp_server *server, __le16 x) +{ + assert_server_locked(server); + put_unaligned(x, (__le16 *) (&(server->packet[server->current_size]))); + server->current_size += 2; + return; +} + +static void ncp_add_be16(struct ncp_server *server, __u16 x) +{ + assert_server_locked(server); + put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size]))); + server->current_size += 2; +} + +static void ncp_add_dword(struct ncp_server *server, __le32 x) +{ + assert_server_locked(server); + put_unaligned(x, (__le32 *) (&(server->packet[server->current_size]))); + server->current_size += 4; + return; +} + +static void ncp_add_be32(struct ncp_server *server, __u32 x) +{ + assert_server_locked(server); + put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size]))); + server->current_size += 4; +} + +static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) { + ncp_add_dword(server, cpu_to_le32(x)); +} + +static void ncp_add_mem(struct ncp_server *server, const void *source, int size) +{ + assert_server_locked(server); + memcpy(&(server->packet[server->current_size]), source, size); + server->current_size += size; + return; +} + +static void ncp_add_pstring(struct ncp_server *server, const char *s) +{ + int len = strlen(s); + assert_server_locked(server); + if (len > 255) { + ncp_dbg(1, "string too long: %s\n", s); + len = 255; + } + ncp_add_byte(server, len); + ncp_add_mem(server, s, len); + return; +} + +static inline void ncp_init_request(struct ncp_server *server) +{ + ncp_lock_server(server); + + server->current_size = sizeof(struct ncp_request_header); + server->has_subfunction = 0; +} + +static inline void ncp_init_request_s(struct ncp_server *server, int subfunction) +{ + ncp_lock_server(server); + + server->current_size = sizeof(struct ncp_request_header) + 2; + ncp_add_byte(server, subfunction); + + server->has_subfunction = 1; +} + +static inline char * +ncp_reply_data(struct ncp_server *server, int offset) +{ + return &(server->packet[sizeof(struct ncp_reply_header) + offset]); +} + +static inline u8 BVAL(const void *data) +{ + return *(const u8 *)data; +} + +static u8 ncp_reply_byte(struct ncp_server *server, int offset) +{ + return *(const u8 *)ncp_reply_data(server, offset); +} + +static inline u16 WVAL_LH(const void *data) +{ + return get_unaligned_le16(data); +} + +static u16 +ncp_reply_le16(struct ncp_server *server, int offset) +{ + return get_unaligned_le16(ncp_reply_data(server, offset)); +} + +static u16 +ncp_reply_be16(struct ncp_server *server, int offset) +{ + return get_unaligned_be16(ncp_reply_data(server, offset)); +} + +static inline u32 DVAL_LH(const void *data) +{ + return get_unaligned_le32(data); +} + +static __le32 +ncp_reply_dword(struct ncp_server *server, int offset) +{ + return get_unaligned((__le32 *)ncp_reply_data(server, offset)); +} + +static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) { + return le32_to_cpu(ncp_reply_dword(server, offset)); +} + +int +ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target) +{ + int result; + + ncp_init_request(server); + ncp_add_be16(server, size); + + if ((result = ncp_request(server, 33)) != 0) { + ncp_unlock_server(server); + return result; + } + *target = min_t(unsigned int, ncp_reply_be16(server, 0), size); + + ncp_unlock_server(server); + return 0; +} + + +/* options: + * bit 0 ipx checksum + * bit 1 packet signing + */ +int +ncp_negotiate_size_and_options(struct ncp_server *server, + int size, int options, int *ret_size, int *ret_options) { + int result; + + /* there is minimum */ + if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE; + + ncp_init_request(server); + ncp_add_be16(server, size); + ncp_add_byte(server, options); + + if ((result = ncp_request(server, 0x61)) != 0) + { + ncp_unlock_server(server); + return result; + } + + /* NCP over UDP returns 0 (!!!) */ + result = ncp_reply_be16(server, 0); + if (result >= NCP_BLOCK_SIZE) + size = min(result, size); + *ret_size = size; + *ret_options = ncp_reply_byte(server, 4); + + ncp_unlock_server(server); + return 0; +} + +int ncp_get_volume_info_with_number(struct ncp_server* server, + int n, struct ncp_volume_info* target) { + int result; + int len; + + ncp_init_request_s(server, 44); + ncp_add_byte(server, n); + + if ((result = ncp_request(server, 22)) != 0) { + goto out; + } + target->total_blocks = ncp_reply_dword_lh(server, 0); + target->free_blocks = ncp_reply_dword_lh(server, 4); + target->purgeable_blocks = ncp_reply_dword_lh(server, 8); + target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12); + target->total_dir_entries = ncp_reply_dword_lh(server, 16); + target->available_dir_entries = ncp_reply_dword_lh(server, 20); + target->sectors_per_block = ncp_reply_byte(server, 28); + + memset(&(target->volume_name), 0, sizeof(target->volume_name)); + + result = -EIO; + len = ncp_reply_byte(server, 29); + if (len > NCP_VOLNAME_LEN) { + ncp_dbg(1, "volume name too long: %d\n", len); + goto out; + } + memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); + result = 0; +out: + ncp_unlock_server(server); + return result; +} + +int ncp_get_directory_info(struct ncp_server* server, __u8 n, + struct ncp_volume_info* target) { + int result; + int len; + + ncp_init_request_s(server, 45); + ncp_add_byte(server, n); + + if ((result = ncp_request(server, 22)) != 0) { + goto out; + } + target->total_blocks = ncp_reply_dword_lh(server, 0); + target->free_blocks = ncp_reply_dword_lh(server, 4); + target->purgeable_blocks = 0; + target->not_yet_purgeable_blocks = 0; + target->total_dir_entries = ncp_reply_dword_lh(server, 8); + target->available_dir_entries = ncp_reply_dword_lh(server, 12); + target->sectors_per_block = ncp_reply_byte(server, 20); + + memset(&(target->volume_name), 0, sizeof(target->volume_name)); + + result = -EIO; + len = ncp_reply_byte(server, 21); + if (len > NCP_VOLNAME_LEN) { + ncp_dbg(1, "volume name too long: %d\n", len); + goto out; + } + memcpy(&(target->volume_name), ncp_reply_data(server, 22), len); + result = 0; +out: + ncp_unlock_server(server); + return result; +} + +int +ncp_close_file(struct ncp_server *server, const char *file_id) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + + result = ncp_request(server, 66); + ncp_unlock_server(server); + return result; +} + +int +ncp_make_closed(struct inode *inode) +{ + int err; + + err = 0; + mutex_lock(&NCP_FINFO(inode)->open_mutex); + if (atomic_read(&NCP_FINFO(inode)->opened) == 1) { + atomic_set(&NCP_FINFO(inode)->opened, 0); + err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); + + if (!err) + ncp_vdbg("volnum=%d, dirent=%u, error=%d\n", + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum, err); + } + mutex_unlock(&NCP_FINFO(inode)->open_mutex); + return err; +} + +static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num, + __le32 dir_base, int have_dir_base, + const char *path) +{ + ncp_add_byte(server, vol_num); + ncp_add_dword(server, dir_base); + if (have_dir_base != 0) { + ncp_add_byte(server, 1); /* dir_base */ + } else { + ncp_add_byte(server, 0xff); /* no handle */ + } + if (path != NULL) { + ncp_add_byte(server, 1); /* 1 component */ + ncp_add_pstring(server, path); + } else { + ncp_add_byte(server, 0); + } +} + +int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent, + __u8* dirhandle) { + int result; + + ncp_init_request(server); + ncp_add_byte(server, 12); /* subfunction */ + ncp_add_byte(server, NW_NS_DOS); + ncp_add_byte(server, 0); + ncp_add_word(server, 0); + ncp_add_handle_path(server, volnum, dirent, 1, NULL); + if ((result = ncp_request(server, 87)) == 0) { + *dirhandle = ncp_reply_byte(server, 0); + } + ncp_unlock_server(server); + return result; +} + +int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) { + int result; + + ncp_init_request_s(server, 20); + ncp_add_byte(server, dirhandle); + result = ncp_request(server, 22); + ncp_unlock_server(server); + return result; +} + +void ncp_extract_file_info(const void *structure, struct nw_info_struct *target) +{ + const __u8 *name_len; + const int info_struct_size = offsetof(struct nw_info_struct, nameLen); + + memcpy(target, structure, info_struct_size); + name_len = structure + info_struct_size; + target->nameLen = *name_len; + memcpy(target->entryName, name_len + 1, *name_len); + target->entryName[*name_len] = '\0'; + target->volNumber = le32_to_cpu(target->volNumber); + return; +} + +#ifdef CONFIG_NCPFS_NFS_NS +static inline void ncp_extract_nfs_info(const unsigned char *structure, + struct nw_nfs_info *target) +{ + target->mode = DVAL_LH(structure); + target->rdev = DVAL_LH(structure + 8); +} +#endif + +int ncp_obtain_nfs_info(struct ncp_server *server, + struct nw_info_struct *target) + +{ + int result = 0; +#ifdef CONFIG_NCPFS_NFS_NS + __u32 volnum = target->volNumber; + + if (ncp_is_nfs_extras(server, volnum)) { + ncp_init_request(server); + ncp_add_byte(server, 19); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, NW_NS_NFS); + ncp_add_byte(server, 0); + ncp_add_byte(server, volnum); + ncp_add_dword(server, target->dirEntNum); + /* We must retrieve both nlinks and rdev, otherwise some server versions + report zeroes instead of valid data */ + ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV); + + if ((result = ncp_request(server, 87)) == 0) { + ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs); + ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n", + target->entryName, target->nfs.mode, + target->nfs.rdev); + } else { + target->nfs.mode = 0; + target->nfs.rdev = 0; + } + ncp_unlock_server(server); + + } else +#endif + { + target->nfs.mode = 0; + target->nfs.rdev = 0; + } + return result; +} + +/* + * Returns information for a (one-component) name relative to + * the specified directory. + */ +int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path, + struct nw_info_struct *target) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int result; + + if (target == NULL) { + pr_err("%s: invalid call\n", __func__); + return -EINVAL; + } + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */ + ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, volnum, dirent, 1, path); + + if ((result = ncp_request(server, 87)) != 0) + goto out; + ncp_extract_file_info(ncp_reply_data(server, 0), target); + ncp_unlock_server(server); + + result = ncp_obtain_nfs_info(server, target); + return result; + +out: + ncp_unlock_server(server); + return result; +} + +#ifdef CONFIG_NCPFS_NFS_NS +static int +ncp_obtain_DOS_dir_base(struct ncp_server *server, + __u8 ns, __u8 volnum, __le32 dirent, + const char *path, /* At most 1 component */ + __le32 *DOS_dir_base) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, ns); + ncp_add_byte(server, ns); + ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ + ncp_add_dword(server, RIM_DIRECTORY); + ncp_add_handle_path(server, volnum, dirent, 1, path); + + if ((result = ncp_request(server, 87)) == 0) + { + if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34); + } + ncp_unlock_server(server); + return result; +} +#endif /* CONFIG_NCPFS_NFS_NS */ + +static inline int +ncp_get_known_namespace(struct ncp_server *server, __u8 volume) +{ +#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) + int result; + __u8 *namespace; + __u16 no_namespaces; + + ncp_init_request(server); + ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */ + ncp_add_word(server, 0); + ncp_add_byte(server, volume); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return NW_NS_DOS; /* not result ?? */ + } + + result = NW_NS_DOS; + no_namespaces = ncp_reply_le16(server, 0); + namespace = ncp_reply_data(server, 2); + + while (no_namespaces > 0) { + ncp_dbg(1, "found %d on %d\n", *namespace, volume); + +#ifdef CONFIG_NCPFS_NFS_NS + if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) + { + result = NW_NS_NFS; + break; + } +#endif /* CONFIG_NCPFS_NFS_NS */ +#ifdef CONFIG_NCPFS_OS2_NS + if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2)) + { + result = NW_NS_OS2; + } +#endif /* CONFIG_NCPFS_OS2_NS */ + namespace += 1; + no_namespaces -= 1; + } + ncp_unlock_server(server); + return result; +#else /* neither OS2 nor NFS - only DOS */ + return NW_NS_DOS; +#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */ +} + +int +ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns) +{ + int ns = ncp_get_known_namespace(server, volume); + + if (ret_ns) + *ret_ns = ns; + + ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]); + + if (server->name_space[volume] == ns) + return 0; + server->name_space[volume] = ns; + return 1; +} + +static int +ncp_ObtainSpecificDirBase(struct ncp_server *server, + __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base, + const char *path, /* At most 1 component */ + __le32 *dirEntNum, __le32 *DosDirNum) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, nsSrc); + ncp_add_byte(server, nsDst); + ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, vol_num, dir_base, 1, path); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + if (dirEntNum) + *dirEntNum = ncp_reply_dword(server, 0x30); + if (DosDirNum) + *DosDirNum = ncp_reply_dword(server, 0x34); + ncp_unlock_server(server); + return 0; +} + +int +ncp_mount_subdir(struct ncp_server *server, + __u8 volNumber, __u8 srcNS, __le32 dirEntNum, + __u32* volume, __le32* newDirEnt, __le32* newDosEnt) +{ + int dstNS; + int result; + + ncp_update_known_namespace(server, volNumber, &dstNS); + if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, + dirEntNum, NULL, newDirEnt, newDosEnt)) != 0) + { + return result; + } + *volume = volNumber; + server->m.mounted_vol[1] = 0; + server->m.mounted_vol[0] = 'X'; + return 0; +} + +int +ncp_get_volume_root(struct ncp_server *server, + const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent) +{ + int result; + + ncp_dbg(1, "looking up vol %s\n", volname); + + ncp_init_request(server); + ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */ + ncp_add_byte(server, 0); /* DOS namespace */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + + ncp_add_byte(server, 0); /* faked volume number */ + ncp_add_dword(server, 0); /* faked dir_base */ + ncp_add_byte(server, 0xff); /* Don't have a dir_base */ + ncp_add_byte(server, 1); /* 1 path component */ + ncp_add_pstring(server, volname); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + *dirent = *dosdirent = ncp_reply_dword(server, 4); + *volume = ncp_reply_byte(server, 8); + ncp_unlock_server(server); + return 0; +} + +int +ncp_lookup_volume(struct ncp_server *server, + const char *volname, struct nw_info_struct *target) +{ + int result; + + memset(target, 0, sizeof(*target)); + result = ncp_get_volume_root(server, volname, + &target->volNumber, &target->dirEntNum, &target->DosDirNum); + if (result) { + return result; + } + ncp_update_known_namespace(server, target->volNumber, NULL); + target->nameLen = strlen(volname); + memcpy(target->entryName, volname, target->nameLen+1); + target->attributes = aDIR; + /* set dates to Jan 1, 1986 00:00 */ + target->creationTime = target->modifyTime = cpu_to_le16(0x0000); + target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21); + target->nfs.mode = 0; + return 0; +} + +int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server, + struct inode *dir, + const char *path, + __le32 info_mask, + const struct nw_modify_dos_info *info) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int result; + + ncp_init_request(server); + ncp_add_byte(server, 7); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, cpu_to_le16(0x8006)); /* search attribs: all */ + + ncp_add_dword(server, info_mask); + ncp_add_mem(server, info, sizeof(*info)); + ncp_add_handle_path(server, volnum, dirent, 1, path); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + +int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, + struct inode *dir, + __le32 info_mask, + const struct nw_modify_dos_info *info) +{ + return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL, + info_mask, info); +} + +#ifdef CONFIG_NCPFS_NFS_NS +int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent, + __u32 mode, __u32 rdev) + +{ + int result = 0; + + ncp_init_request(server); + if (server->name_space[volnum] == NW_NS_NFS) { + ncp_add_byte(server, 25); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, NW_NS_NFS); + ncp_add_byte(server, volnum); + ncp_add_dword(server, dirent); + /* we must always operate on both nlinks and rdev, otherwise + rdev is not set */ + ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV); + ncp_add_dword_lh(server, mode); + ncp_add_dword_lh(server, 1); /* nlinks */ + ncp_add_dword_lh(server, rdev); + result = ncp_request(server, 87); + } + ncp_unlock_server(server); + return result; +} +#endif + + +static int +ncp_DeleteNSEntry(struct ncp_server *server, + __u8 have_dir_base, __u8 volnum, __le32 dirent, + const char* name, __u8 ns, __le16 attr) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 8); /* subfunction */ + ncp_add_byte(server, ns); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, attr); /* search attribs: all */ + ncp_add_handle_path(server, volnum, dirent, have_dir_base, name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + +int +ncp_del_file_or_subdir2(struct ncp_server *server, + struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + __u8 volnum; + __le32 dirent; + + if (!inode) { + return 0xFF; /* Any error */ + } + volnum = NCP_FINFO(inode)->volNumber; + dirent = NCP_FINFO(inode)->DosDirNum; + return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006)); +} + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct inode *dir, const char *name) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int name_space; + + name_space = server->name_space[volnum]; +#ifdef CONFIG_NCPFS_NFS_NS + if (name_space == NW_NS_NFS) + { + int result; + + result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent); + if (result) return result; + name = NULL; + name_space = NW_NS_DOS; + } +#endif /* CONFIG_NCPFS_NFS_NS */ + return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006)); +} + +static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) +{ + __le16 *dest = (__le16 *) ret; + dest[1] = cpu_to_le16(v0); + dest[2] = cpu_to_le16(v1); + dest[0] = cpu_to_le16(v0 + 1); + return; +} + +/* If both dir and name are NULL, then in target there's already a + looked-up entry that wants to be opened. */ +int ncp_open_create_file_or_subdir(struct ncp_server *server, + struct inode *dir, const char *name, + int open_create_mode, + __le32 create_attributes, + __le16 desired_acc_rights, + struct ncp_entry_info *target) +{ + __le16 search_attribs = cpu_to_le16(0x0006); + __u8 volnum; + __le32 dirent; + int result; + + volnum = NCP_FINFO(dir)->volNumber; + dirent = NCP_FINFO(dir)->dirEntNum; + + if ((create_attributes & aDIR) != 0) { + search_attribs |= cpu_to_le16(0x8000); + } + ncp_init_request(server); + ncp_add_byte(server, 1); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, open_create_mode); + ncp_add_word(server, search_attribs); + ncp_add_dword(server, RIM_ALL); + ncp_add_dword(server, create_attributes); + /* The desired acc rights seem to be the inherited rights mask + for directories */ + ncp_add_word(server, desired_acc_rights); + ncp_add_handle_path(server, volnum, dirent, 1, name); + + if ((result = ncp_request(server, 87)) != 0) + goto out; + if (!(create_attributes & aDIR)) + target->opened = 1; + + /* in target there's a new finfo to fill */ + ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i)); + target->volume = target->i.volNumber; + ConvertToNWfromDWORD(ncp_reply_le16(server, 0), + ncp_reply_le16(server, 2), + target->file_handle); + + ncp_unlock_server(server); + + (void)ncp_obtain_nfs_info(server, &(target->i)); + return 0; + +out: + ncp_unlock_server(server); + return result; +} + +int +ncp_initialize_search(struct ncp_server *server, struct inode *dir, + struct nw_search_sequence *target) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int result; + + ncp_init_request(server); + ncp_add_byte(server, 2); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, volnum, dirent, 1, NULL); + + result = ncp_request(server, 87); + if (result) + goto out; + memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); + +out: + ncp_unlock_server(server); + return result; +} + +int ncp_search_for_fileset(struct ncp_server *server, + struct nw_search_sequence *seq, + int* more, + int* cnt, + char* buffer, + size_t bufsize, + char** rbuf, + size_t* rsize) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 20); + ncp_add_byte(server, server->name_space[seq->volNumber]); + ncp_add_byte(server, 0); /* datastream */ + ncp_add_word(server, cpu_to_le16(0x8006)); + ncp_add_dword(server, RIM_ALL); + ncp_add_word(server, cpu_to_le16(32767)); /* max returned items */ + ncp_add_mem(server, seq, 9); +#ifdef CONFIG_NCPFS_NFS_NS + if (server->name_space[seq->volNumber] == NW_NS_NFS) { + ncp_add_byte(server, 0); /* 0 byte pattern */ + } else +#endif + { + ncp_add_byte(server, 2); /* 2 byte pattern */ + ncp_add_byte(server, 0xff); /* following is a wildcard */ + ncp_add_byte(server, '*'); + } + result = ncp_request2(server, 87, buffer, bufsize); + if (result) { + ncp_unlock_server(server); + return result; + } + if (server->ncp_reply_size < 12) { + ncp_unlock_server(server); + return 0xFF; + } + *rsize = server->ncp_reply_size - 12; + ncp_unlock_server(server); + buffer = buffer + sizeof(struct ncp_reply_header); + *rbuf = buffer + 12; + *cnt = WVAL_LH(buffer + 10); + *more = BVAL(buffer + 9); + memcpy(seq, buffer, 9); + return 0; +} + +static int +ncp_RenameNSEntry(struct ncp_server *server, + struct inode *old_dir, const char *old_name, __le16 old_type, + struct inode *new_dir, const char *new_name) +{ + int result = -EINVAL; + + if ((old_dir == NULL) || (old_name == NULL) || + (new_dir == NULL) || (new_name == NULL)) + goto out; + + ncp_init_request(server); + ncp_add_byte(server, 4); /* subfunction */ + ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]); + ncp_add_byte(server, 1); /* rename flag */ + ncp_add_word(server, old_type); /* search attributes */ + + /* source Handle Path */ + ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber); + ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 source component */ + + /* dest Handle Path */ + ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber); + ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 destination component */ + + /* source path string */ + ncp_add_pstring(server, old_name); + /* dest path string */ + ncp_add_pstring(server, new_name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); +out: + return result; +} + +int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct inode *old_dir, const char *old_name, + struct inode *new_dir, const char *new_name) +{ + int result; + __le16 old_type = cpu_to_le16(0x06); + +/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */ + result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, + new_dir, new_name); + if (result == 0xFF) /* File Not Found, try directory */ + { + old_type = cpu_to_le16(0x16); + result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, + new_dir, new_name); + } + if (result != 0x92) return result; /* All except NO_FILES_RENAMED */ + result = ncp_del_file_or_subdir(server, new_dir, new_name); + if (result != 0) return -EACCES; + result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, + new_dir, new_name); + return result; +} + + +/* We have to transfer to/from user space */ +int +ncp_read_kernel(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, char *target, int *bytes_read) +{ + const char *source; + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be16(server, to_read); + + if ((result = ncp_request(server, 72)) != 0) { + goto out; + } + *bytes_read = ncp_reply_be16(server, 0); + source = ncp_reply_data(server, 2 + (offset & 1)); + + memcpy(target, source, *bytes_read); +out: + ncp_unlock_server(server); + return result; +} + +/* There is a problem... egrep and some other silly tools do: + x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, <ncpfs fd>, 32768); + read(<ncpfs fd>, x, 32768); + Now copying read result by copy_to_user causes pagefault. This pagefault + could not be handled because of server was locked due to read. So we have + to use temporary buffer. So ncp_unlock_server must be done before + copy_to_user (and for write, copy_from_user must be done before + ncp_init_request... same applies for send raw packet ioctl). Because of + file is normally read in bigger chunks, caller provides kmalloced + (vmalloced) chunk of memory with size >= to_read... + */ +int +ncp_read_bounce(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, struct iov_iter *to, + int *bytes_read, void *bounce, __u32 bufsize) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be16(server, to_read); + result = ncp_request2(server, 72, bounce, bufsize); + ncp_unlock_server(server); + if (!result) { + int len = get_unaligned_be16((char *)bounce + + sizeof(struct ncp_reply_header)); + result = -EIO; + if (len <= to_read) { + char* source; + + source = (char*)bounce + + sizeof(struct ncp_reply_header) + 2 + + (offset & 1); + *bytes_read = len; + result = 0; + if (copy_to_iter(source, len, to) != len) + result = -EFAULT; + } + } + return result; +} + +int +ncp_write_kernel(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be16(server, to_write); + ncp_add_mem(server, source, to_write); + + if ((result = ncp_request(server, 73)) == 0) + *bytes_written = to_write; + ncp_unlock_server(server); + return result; +} + +#ifdef CONFIG_NCPFS_IOCTL_LOCKING +int +ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id, + __u8 locktype, __u32 offset, __u32 length, __u16 timeout) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, locktype); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be32(server, length); + ncp_add_be16(server, timeout); + + if ((result = ncp_request(server, 0x1A)) != 0) + { + ncp_unlock_server(server); + return result; + } + ncp_unlock_server(server); + return 0; +} + +int +ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id, + __u32 offset, __u32 length) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); /* who knows... lanalyzer says that */ + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be32(server, length); + + if ((result = ncp_request(server, 0x1E)) != 0) + { + ncp_unlock_server(server); + return result; + } + ncp_unlock_server(server); + return 0; +} +#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + +#ifdef CONFIG_NCPFS_NLS +/* This are the NLS conversion routines with inspirations and code parts + * from the vfat file system and hints from Petr Vandrovec. + */ + +int +ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen, + const unsigned char *iname, unsigned int ilen, int cc) +{ + struct nls_table *in = server->nls_io; + struct nls_table *out = server->nls_vol; + unsigned char *vname_start; + unsigned char *vname_end; + const unsigned char *iname_end; + + iname_end = iname + ilen; + vname_start = vname; + vname_end = vname + *vlen - 1; + + while (iname < iname_end) { + int chl; + wchar_t ec; + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { + int k; + unicode_t u; + + k = utf8_to_utf32(iname, iname_end - iname, &u); + if (k < 0 || u > MAX_WCHAR_T) + return -EINVAL; + iname += k; + ec = u; + } else { + if (*iname == NCP_ESC) { + int k; + + if (iname_end - iname < 5) + goto nospec; + + ec = 0; + for (k = 1; k < 5; k++) { + unsigned char nc; + + nc = iname[k] - '0'; + if (nc >= 10) { + nc -= 'A' - '0' - 10; + if ((nc < 10) || (nc > 15)) { + goto nospec; + } + } + ec = (ec << 4) | nc; + } + iname += 5; + } else { +nospec:; + if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0) + return chl; + iname += chl; + } + } + + /* unitoupper should be here! */ + + chl = out->uni2char(ec, vname, vname_end - vname); + if (chl < 0) + return chl; + + /* this is wrong... */ + if (cc) { + int chi; + + for (chi = 0; chi < chl; chi++){ + vname[chi] = ncp_toupper(out, vname[chi]); + } + } + vname += chl; + } + + *vname = 0; + *vlen = vname - vname_start; + return 0; +} + +int +ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen, + const unsigned char *vname, unsigned int vlen, int cc) +{ + struct nls_table *in = server->nls_vol; + struct nls_table *out = server->nls_io; + const unsigned char *vname_end; + unsigned char *iname_start; + unsigned char *iname_end; + unsigned char *vname_cc; + int err; + + vname_cc = NULL; + + if (cc) { + int i; + + /* this is wrong! */ + vname_cc = kmalloc(vlen, GFP_KERNEL); + if (!vname_cc) + return -ENOMEM; + for (i = 0; i < vlen; i++) + vname_cc[i] = ncp_tolower(in, vname[i]); + vname = vname_cc; + } + + iname_start = iname; + iname_end = iname + *ilen - 1; + vname_end = vname + vlen; + + while (vname < vname_end) { + wchar_t ec; + int chl; + + if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) { + err = chl; + goto quit; + } + vname += chl; + + /* unitolower should be here! */ + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { + int k; + + k = utf32_to_utf8(ec, iname, iname_end - iname); + if (k < 0) { + err = -ENAMETOOLONG; + goto quit; + } + iname += k; + } else { + if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) { + iname += chl; + } else { + int k; + + if (iname_end - iname < 5) { + err = -ENAMETOOLONG; + goto quit; + } + *iname = NCP_ESC; + for (k = 4; k > 0; k--) { + unsigned char v; + + v = (ec & 0xF) + '0'; + if (v > '9') { + v += 'A' - '9' - 1; + } + iname[k] = v; + ec >>= 4; + } + iname += 5; + } + } + } + + *iname = 0; + *ilen = iname - iname_start; + err = 0; +quit:; + if (cc) + kfree(vname_cc); + return err; +} + +#else + +int +ncp__io2vol(unsigned char *vname, unsigned int *vlen, + const unsigned char *iname, unsigned int ilen, int cc) +{ + int i; + + if (*vlen <= ilen) + return -ENAMETOOLONG; + + if (cc) + for (i = 0; i < ilen; i++) { + *vname = toupper(*iname); + vname++; + iname++; + } + else { + memmove(vname, iname, ilen); + vname += ilen; + } + + *vlen = ilen; + *vname = 0; + return 0; +} + +int +ncp__vol2io(unsigned char *iname, unsigned int *ilen, + const unsigned char *vname, unsigned int vlen, int cc) +{ + int i; + + if (*ilen <= vlen) + return -ENAMETOOLONG; + + if (cc) + for (i = 0; i < vlen; i++) { + *iname = tolower(*vname); + iname++; + vname++; + } + else { + memmove(iname, vname, vlen); + iname += vlen; + } + + *ilen = vlen; + *iname = 0; + return 0; +} + +#endif diff --git a/drivers/staging/ncpfs/ncplib_kernel.h b/drivers/staging/ncpfs/ncplib_kernel.h new file mode 100644 index 000000000000..aaae8aa9bf7d --- /dev/null +++ b/drivers/staging/ncpfs/ncplib_kernel.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncplib_kernel.h + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998, 1999 Wolfram Pienkoss for NLS + * Modified 1999 Wolfram Pienkoss for directory caching + * + */ + +#ifndef _NCPLIB_H +#define _NCPLIB_H + + +#include <linux/fs.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/fcntl.h> +#include <linux/pagemap.h> + +#include <linux/uaccess.h> +#include <asm/byteorder.h> +#include <asm/unaligned.h> +#include <asm/string.h> + +#ifdef CONFIG_NCPFS_NLS +#include <linux/nls.h> +#else +#include <linux/ctype.h> +#endif /* CONFIG_NCPFS_NLS */ + +#define NCP_MIN_SYMLINK_SIZE 8 +#define NCP_MAX_SYMLINK_SIZE 512 + +#define NCP_BLOCK_SHIFT 9 +#define NCP_BLOCK_SIZE (1 << (NCP_BLOCK_SHIFT)) + +int ncp_negotiate_buffersize(struct ncp_server *, int, int *); +int ncp_negotiate_size_and_options(struct ncp_server *server, int size, + int options, int *ret_size, int *ret_options); + +int ncp_get_volume_info_with_number(struct ncp_server* server, int n, + struct ncp_volume_info *target); + +int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle, + struct ncp_volume_info* target); + +int ncp_close_file(struct ncp_server *, const char *); +static inline int ncp_read_bounce_size(__u32 size) { + return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8; +}; +int ncp_read_bounce(struct ncp_server *, const char *, __u32, __u16, + struct iov_iter *, int *, void *bounce, __u32 bouncelen); +int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, + char *, int *); +int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16, + const char *, int *); + +static inline void ncp_inode_close(struct inode *inode) { + atomic_dec(&NCP_FINFO(inode)->opened); +} + +void ncp_extract_file_info(const void* src, struct nw_info_struct* target); +int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *, + struct nw_info_struct *target); +int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target); +int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns); +int ncp_get_volume_root(struct ncp_server *server, const char *volname, + __u32 *volume, __le32 *dirent, __le32 *dosdirent); +int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *); +int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *, + __le32, const struct nw_modify_dos_info *info); +int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *, + const char* path, __le32, const struct nw_modify_dos_info *info); +int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent, + __u32 mode, __u32 rdev); + +int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); +int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *); +int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *, + int, __le32, __le16, struct ncp_entry_info *); + +int ncp_initialize_search(struct ncp_server *, struct inode *, + struct nw_search_sequence *target); +int ncp_search_for_fileset(struct ncp_server *server, + struct nw_search_sequence *seq, + int* more, int* cnt, + char* buffer, size_t bufsize, + char** rbuf, size_t* rsize); + +int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct inode *, const char *, struct inode *, const char *); + + +int +ncp_LogPhysicalRecord(struct ncp_server *server, + const char *file_id, __u8 locktype, + __u32 offset, __u32 length, __u16 timeout); + +#ifdef CONFIG_NCPFS_IOCTL_LOCKING +int +ncp_ClearPhysicalRecord(struct ncp_server *server, + const char *file_id, + __u32 offset, __u32 length); +#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + +int +ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32, + __u32* volume, __le32* dirent, __le32* dosdirent); +int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle); +int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle); + +int ncp_create_new(struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t rdev, __le32 attributes); + +static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) { +#ifdef CONFIG_NCPFS_NFS_NS + return (server->m.flags & NCP_MOUNT_NFS_EXTRAS) && + (server->name_space[volnum] == NW_NS_NFS); +#else + return 0; +#endif +} + +#ifdef CONFIG_NCPFS_NLS + +int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); +int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); + +#define NCP_ESC ':' +#define NCP_IO_TABLE(sb) (NCP_SBP(sb)->nls_io) +#define ncp_tolower(t, c) nls_tolower(t, c) +#define ncp_toupper(t, c) nls_toupper(t, c) +#define ncp_strnicmp(t, s1, s2, len) \ + nls_strnicmp(t, s1, s2, len) +#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(S,m,i,n,k,U) +#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(S,m,i,n,k,U) + +#else + +int ncp__io2vol(unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); +int ncp__vol2io(unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); + +#define NCP_IO_TABLE(sb) NULL +#define ncp_tolower(t, c) tolower(c) +#define ncp_toupper(t, c) toupper(c) +#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U) +#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U) + + +static inline int ncp_strnicmp(const struct nls_table *t, + const unsigned char *s1, const unsigned char *s2, int len) +{ + while (len--) { + if (tolower(*s1++) != tolower(*s2++)) + return 1; + } + + return 0; +} + +#endif /* CONFIG_NCPFS_NLS */ + +#define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) +#define NCP_MAX_AGE(server) atomic_read(&(server)->dentry_ttl) +#define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) + +static inline void +ncp_age_dentry(struct ncp_server* server, struct dentry* dentry) +{ + dentry->d_time = jiffies - NCP_MAX_AGE(server); +} + +static inline void +ncp_new_dentry(struct dentry* dentry) +{ + dentry->d_time = jiffies; +} + +struct ncp_cache_head { + time_t mtime; + unsigned long time; /* cache age */ + unsigned long end; /* last valid fpos in cache */ + int eof; +}; + +#define NCP_DIRCACHE_SIZE ((int)(PAGE_SIZE/sizeof(struct dentry *))) +union ncp_dir_cache { + struct ncp_cache_head head; + struct dentry *dentry[NCP_DIRCACHE_SIZE]; +}; + +#define NCP_FIRSTCACHE_SIZE ((int)((NCP_DIRCACHE_SIZE * \ + sizeof(struct dentry *) - sizeof(struct ncp_cache_head)) / \ + sizeof(struct dentry *))) + +#define NCP_DIRCACHE_START (NCP_DIRCACHE_SIZE - NCP_FIRSTCACHE_SIZE) + +struct ncp_cache_control { + struct ncp_cache_head head; + struct page *page; + union ncp_dir_cache *cache; + unsigned long fpos, ofs; + int filled, valid, idx; +}; + +#endif /* _NCPLIB_H */ diff --git a/drivers/staging/ncpfs/ncpsign_kernel.c b/drivers/staging/ncpfs/ncpsign_kernel.c new file mode 100644 index 000000000000..8085b1a3ba47 --- /dev/null +++ b/drivers/staging/ncpfs/ncpsign_kernel.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ncpsign_kernel.c + * + * Arne de Bruijn (arne@knoware.nl), 1997 + * + */ + + +#ifdef CONFIG_NCPFS_PACKET_SIGNING + +#include <linux/string.h> +#include <linux/ncp.h> +#include <linux/bitops.h> +#include "ncp_fs.h" +#include "ncpsign_kernel.h" + +/* i386: 32-bit, little endian, handles mis-alignment */ +#ifdef __i386__ +#define GET_LE32(p) (*(const int *)(p)) +#define PUT_LE32(p,v) { *(int *)(p)=v; } +#else +/* from include/ncplib.h */ +#define BVAL(buf,pos) (((const __u8 *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) +#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val)) + +static inline __u16 +WVAL_LH(const __u8 * buf, int pos) +{ + return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; +} +static inline __u32 +DVAL_LH(const __u8 * buf, int pos) +{ + return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; +} +static inline void +WSET_LH(__u8 * buf, int pos, __u16 val) +{ + BSET(buf, pos, val & 0xff); + BSET(buf, pos + 1, val >> 8); +} +static inline void +DSET_LH(__u8 * buf, int pos, __u32 val) +{ + WSET_LH(buf, pos, val & 0xffff); + WSET_LH(buf, pos + 2, val >> 16); +} + +#define GET_LE32(p) DVAL_LH(p,0) +#define PUT_LE32(p,v) DSET_LH(p,0,v) +#endif + +static void nwsign(char *r_data1, char *r_data2, char *outdata) { + int i; + unsigned int w0,w1,w2,w3; + static int rbit[4]={0, 2, 1, 3}; +#ifdef __i386__ + unsigned int *data2=(unsigned int *)r_data2; +#else + unsigned int data2[16]; + for (i=0;i<16;i++) + data2[i]=GET_LE32(r_data2+(i<<2)); +#endif + w0=GET_LE32(r_data1); + w1=GET_LE32(r_data1+4); + w2=GET_LE32(r_data1+8); + w3=GET_LE32(r_data1+12); + for (i=0;i<16;i+=4) { + w0=rol32(w0 + ((w1 & w2) | ((~w1) & w3)) + data2[i+0],3); + w3=rol32(w3 + ((w0 & w1) | ((~w0) & w2)) + data2[i+1],7); + w2=rol32(w2 + ((w3 & w0) | ((~w3) & w1)) + data2[i+2],11); + w1=rol32(w1 + ((w2 & w3) | ((~w2) & w0)) + data2[i+3],19); + } + for (i=0;i<4;i++) { + w0=rol32(w0 + (((w2 | w3) & w1) | (w2 & w3)) + 0x5a827999 + data2[i+0],3); + w3=rol32(w3 + (((w1 | w2) & w0) | (w1 & w2)) + 0x5a827999 + data2[i+4],5); + w2=rol32(w2 + (((w0 | w1) & w3) | (w0 & w1)) + 0x5a827999 + data2[i+8],9); + w1=rol32(w1 + (((w3 | w0) & w2) | (w3 & w0)) + 0x5a827999 + data2[i+12],13); + } + for (i=0;i<4;i++) { + w0=rol32(w0 + ((w1 ^ w2) ^ w3) + 0x6ed9eba1 + data2[rbit[i]+0],3); + w3=rol32(w3 + ((w0 ^ w1) ^ w2) + 0x6ed9eba1 + data2[rbit[i]+8],9); + w2=rol32(w2 + ((w3 ^ w0) ^ w1) + 0x6ed9eba1 + data2[rbit[i]+4],11); + w1=rol32(w1 + ((w2 ^ w3) ^ w0) + 0x6ed9eba1 + data2[rbit[i]+12],15); + } + PUT_LE32(outdata,(w0+GET_LE32(r_data1)) & 0xffffffff); + PUT_LE32(outdata+4,(w1+GET_LE32(r_data1+4)) & 0xffffffff); + PUT_LE32(outdata+8,(w2+GET_LE32(r_data1+8)) & 0xffffffff); + PUT_LE32(outdata+12,(w3+GET_LE32(r_data1+12)) & 0xffffffff); +} + +/* Make a signature for the current packet and add it at the end of the */ +/* packet. */ +void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) { + unsigned char data[64]; + + memcpy(data, server->sign_root, 8); + *(__u32*)(data + 8) = totalsize; + if (size < 52) { + memcpy(data + 12, packet, size); + memset(data + 12 + size, 0, 52 - size); + } else { + memcpy(data + 12, packet, 52); + } + nwsign(server->sign_last, data, server->sign_last); + memcpy(sign_buff, server->sign_last, 8); +} + +int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) { + unsigned char data[64]; + unsigned char hash[16]; + + memcpy(data, server->sign_root, 8); + *(__u32*)(data + 8) = totalsize; + if (size < 52) { + memcpy(data + 12, packet, size); + memset(data + 12 + size, 0, 52 - size); + } else { + memcpy(data + 12, packet, 52); + } + nwsign(server->sign_last, data, hash); + return memcmp(sign_buff, hash, 8); +} + +#endif /* CONFIG_NCPFS_PACKET_SIGNING */ + diff --git a/drivers/staging/ncpfs/ncpsign_kernel.h b/drivers/staging/ncpfs/ncpsign_kernel.h new file mode 100644 index 000000000000..57ff0a0650b8 --- /dev/null +++ b/drivers/staging/ncpfs/ncpsign_kernel.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncpsign_kernel.h + * + * Arne de Bruijn (arne@knoware.nl), 1997 + * + */ + +#ifndef _NCPSIGN_KERNEL_H +#define _NCPSIGN_KERNEL_H + +#ifdef CONFIG_NCPFS_PACKET_SIGNING +void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff); +int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff); +#endif + +static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) { +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active) { + __sign_packet(server, data, size, totalsize, sign_buff); + return 8; + } +#endif + return 0; +} + +#endif diff --git a/drivers/staging/ncpfs/sock.c b/drivers/staging/ncpfs/sock.c new file mode 100644 index 000000000000..efb176b1751a --- /dev/null +++ b/drivers/staging/ncpfs/sock.c @@ -0,0 +1,854 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/fs/ncpfs/sock.c + * + * Copyright (C) 1992, 1993 Rick Sladkey + * + * Modified 1995, 1996 by Volker Lendecke to be usable for ncp + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/time.h> +#include <linux/errno.h> +#include <linux/socket.h> +#include <linux/fcntl.h> +#include <linux/stat.h> +#include <linux/string.h> +#include <linux/sched/signal.h> +#include <linux/uaccess.h> +#include <linux/in.h> +#include <linux/net.h> +#include <linux/mm.h> +#include <linux/netdevice.h> +#include <linux/signal.h> +#include <linux/slab.h> +#include <net/scm.h> +#include <net/sock.h> +#include <linux/ipx.h> +#include <linux/poll.h> +#include <linux/file.h> + +#include "ncp_fs.h" + +#include "ncpsign_kernel.h" + +static int _recv(struct socket *sock, void *buf, int size, unsigned flags) +{ + struct msghdr msg = {NULL, }; + struct kvec iov = {buf, size}; + return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); +} + +static int _send(struct socket *sock, const void *buff, int len) +{ + struct msghdr msg = { .msg_flags = 0 }; + struct kvec vec = {.iov_base = (void *)buff, .iov_len = len}; + iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len); + return sock_sendmsg(sock, &msg); +} + +struct ncp_request_reply { + struct list_head req; + wait_queue_head_t wq; + atomic_t refs; + unsigned char* reply_buf; + size_t datalen; + int result; + enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; + struct iov_iter from; + struct kvec tx_iov[3]; + u_int16_t tx_type; + u_int32_t sign[6]; +}; + +static inline struct ncp_request_reply* ncp_alloc_req(void) +{ + struct ncp_request_reply *req; + + req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL); + if (!req) + return NULL; + + init_waitqueue_head(&req->wq); + atomic_set(&req->refs, (1)); + req->status = RQ_IDLE; + + return req; +} + +static void ncp_req_get(struct ncp_request_reply *req) +{ + atomic_inc(&req->refs); +} + +static void ncp_req_put(struct ncp_request_reply *req) +{ + if (atomic_dec_and_test(&req->refs)) + kfree(req); +} + +void ncp_tcp_data_ready(struct sock *sk) +{ + struct ncp_server *server = sk->sk_user_data; + + server->data_ready(sk); + schedule_work(&server->rcv.tq); +} + +void ncp_tcp_error_report(struct sock *sk) +{ + struct ncp_server *server = sk->sk_user_data; + + server->error_report(sk); + schedule_work(&server->rcv.tq); +} + +void ncp_tcp_write_space(struct sock *sk) +{ + struct ncp_server *server = sk->sk_user_data; + + /* We do not need any locking: we first set tx.creq, and then we do sendmsg, + not vice versa... */ + server->write_space(sk); + if (server->tx.creq) + schedule_work(&server->tx.tq); +} + +void ncpdgram_timeout_call(struct timer_list *t) +{ + struct ncp_server *server = from_timer(server, t, timeout_tm); + + schedule_work(&server->timeout_tq); +} + +static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result) +{ + req->result = result; + if (req->status != RQ_ABANDONED) + memcpy(req->reply_buf, server->rxbuf, req->datalen); + req->status = RQ_DONE; + wake_up_all(&req->wq); + ncp_req_put(req); +} + +static void __abort_ncp_connection(struct ncp_server *server) +{ + struct ncp_request_reply *req; + + ncp_invalidate_conn(server); + del_timer(&server->timeout_tm); + while (!list_empty(&server->tx.requests)) { + req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); + + list_del_init(&req->req); + ncp_finish_request(server, req, -EIO); + } + req = server->rcv.creq; + if (req) { + server->rcv.creq = NULL; + ncp_finish_request(server, req, -EIO); + server->rcv.ptr = NULL; + server->rcv.state = 0; + } + req = server->tx.creq; + if (req) { + server->tx.creq = NULL; + ncp_finish_request(server, req, -EIO); + } +} + +static inline int get_conn_number(struct ncp_reply_header *rp) +{ + return rp->conn_low | (rp->conn_high << 8); +} + +static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) +{ + /* If req is done, we got signal, but we also received answer... */ + switch (req->status) { + case RQ_IDLE: + case RQ_DONE: + break; + case RQ_QUEUED: + list_del_init(&req->req); + ncp_finish_request(server, req, err); + break; + case RQ_INPROGRESS: + req->status = RQ_ABANDONED; + break; + case RQ_ABANDONED: + break; + } +} + +static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) +{ + mutex_lock(&server->rcv.creq_mutex); + __ncp_abort_request(server, req, err); + mutex_unlock(&server->rcv.creq_mutex); +} + +static inline void __ncptcp_abort(struct ncp_server *server) +{ + __abort_ncp_connection(server); +} + +static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) +{ + struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT }; + return sock_sendmsg(sock, &msg); +} + +static void __ncptcp_try_send(struct ncp_server *server) +{ + struct ncp_request_reply *rq; + struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT }; + int result; + + rq = server->tx.creq; + if (!rq) + return; + + msg.msg_iter = rq->from; + result = sock_sendmsg(server->ncp_sock, &msg); + + if (result == -EAGAIN) + return; + + if (result < 0) { + pr_err("tcp: Send failed: %d\n", result); + __ncp_abort_request(server, rq, result); + return; + } + if (!msg_data_left(&msg)) { + server->rcv.creq = rq; + server->tx.creq = NULL; + return; + } + rq->from = msg.msg_iter; +} + +static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) +{ + req->status = RQ_INPROGRESS; + h->conn_low = server->connection; + h->conn_high = server->connection >> 8; + h->sequence = ++server->sequence; +} + +static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + size_t signlen, len = req->tx_iov[1].iov_len; + struct ncp_request_header *h = req->tx_iov[1].iov_base; + + ncp_init_header(server, req, h); + signlen = sign_packet(server, + req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, + len - sizeof(struct ncp_request_header) + 1, + cpu_to_le32(len), req->sign); + if (signlen) { + /* NCP over UDP appends signature */ + req->tx_iov[2].iov_base = req->sign; + req->tx_iov[2].iov_len = signlen; + } + iov_iter_kvec(&req->from, WRITE | ITER_KVEC, + req->tx_iov + 1, signlen ? 2 : 1, len + signlen); + server->rcv.creq = req; + server->timeout_last = server->m.time_out; + server->timeout_retries = server->m.retry_count; + ncpdgram_send(server->ncp_sock, req); + mod_timer(&server->timeout_tm, jiffies + server->m.time_out); +} + +#define NCP_TCP_XMIT_MAGIC (0x446D6454) +#define NCP_TCP_XMIT_VERSION (1) +#define NCP_TCP_RCVD_MAGIC (0x744E6350) + +static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + size_t signlen, len = req->tx_iov[1].iov_len; + struct ncp_request_header *h = req->tx_iov[1].iov_base; + + ncp_init_header(server, req, h); + signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, + len - sizeof(struct ncp_request_header) + 1, + cpu_to_be32(len + 24), req->sign + 4) + 16; + + req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); + req->sign[1] = htonl(len + signlen); + req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); + req->sign[3] = htonl(req->datalen + 8); + /* NCP over TCP prepends signature */ + req->tx_iov[0].iov_base = req->sign; + req->tx_iov[0].iov_len = signlen; + iov_iter_kvec(&req->from, WRITE | ITER_KVEC, + req->tx_iov, 2, len + signlen); + + server->tx.creq = req; + __ncptcp_try_send(server); +} + +static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + /* we copy the data so that we do not depend on the caller + staying alive */ + memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len); + req->tx_iov[1].iov_base = server->txbuf; + + if (server->ncp_sock->type == SOCK_STREAM) + ncptcp_start_request(server, req); + else + ncpdgram_start_request(server, req); +} + +static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + mutex_lock(&server->rcv.creq_mutex); + if (!ncp_conn_valid(server)) { + mutex_unlock(&server->rcv.creq_mutex); + pr_err("tcp: Server died\n"); + return -EIO; + } + ncp_req_get(req); + if (server->tx.creq || server->rcv.creq) { + req->status = RQ_QUEUED; + list_add_tail(&req->req, &server->tx.requests); + mutex_unlock(&server->rcv.creq_mutex); + return 0; + } + __ncp_start_request(server, req); + mutex_unlock(&server->rcv.creq_mutex); + return 0; +} + +static void __ncp_next_request(struct ncp_server *server) +{ + struct ncp_request_reply *req; + + server->rcv.creq = NULL; + if (list_empty(&server->tx.requests)) { + return; + } + req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); + list_del_init(&req->req); + __ncp_start_request(server, req); +} + +static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) +{ + if (server->info_sock) { + struct msghdr msg = { .msg_flags = MSG_NOSIGNAL }; + __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)}; + struct kvec iov[2] = { + {.iov_base = hdr, .iov_len = 8}, + {.iov_base = (void *)data, .iov_len = len}, + }; + + iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE, + iov, 2, len + 8); + + sock_sendmsg(server->info_sock, &msg); + } +} + +void ncpdgram_rcv_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); + struct socket* sock; + + sock = server->ncp_sock; + + while (1) { + struct ncp_reply_header reply; + int result; + + result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); + if (result < 0) { + break; + } + if (result >= sizeof(reply)) { + struct ncp_request_reply *req; + + if (reply.type == NCP_WATCHDOG) { + unsigned char buf[10]; + + if (server->connection != get_conn_number(&reply)) { + goto drop; + } + result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); + if (result < 0) { + ncp_dbg(1, "recv failed with %d\n", result); + continue; + } + if (result < 10) { + ncp_dbg(1, "too short (%u) watchdog packet\n", result); + continue; + } + if (buf[9] != '?') { + ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]); + continue; + } + buf[9] = 'Y'; + _send(sock, buf, sizeof(buf)); + continue; + } + if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) { + result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT); + if (result < 0) { + continue; + } + info_server(server, 0, server->unexpected_packet.data, result); + continue; + } + mutex_lock(&server->rcv.creq_mutex); + req = server->rcv.creq; + if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && + server->connection == get_conn_number(&reply)))) { + if (reply.type == NCP_POSITIVE_ACK) { + server->timeout_retries = server->m.retry_count; + server->timeout_last = NCP_MAX_RPC_TIMEOUT; + mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); + } else if (reply.type == NCP_REPLY) { + result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT); +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { + if (result < 8 + 8) { + result = -EIO; + } else { + unsigned int hdrl; + + result -= 8; + hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; + if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) { + pr_info("Signature violation\n"); + result = -EIO; + } + } + } +#endif + del_timer(&server->timeout_tm); + server->rcv.creq = NULL; + ncp_finish_request(server, req, result); + __ncp_next_request(server); + mutex_unlock(&server->rcv.creq_mutex); + continue; + } + } + mutex_unlock(&server->rcv.creq_mutex); + } +drop:; + _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT); + } +} + +static void __ncpdgram_timeout_proc(struct ncp_server *server) +{ + /* If timer is pending, we are processing another request... */ + if (!timer_pending(&server->timeout_tm)) { + struct ncp_request_reply* req; + + req = server->rcv.creq; + if (req) { + int timeout; + + if (server->m.flags & NCP_MOUNT_SOFT) { + if (server->timeout_retries-- == 0) { + __ncp_abort_request(server, req, -ETIMEDOUT); + return; + } + } + /* Ignore errors */ + ncpdgram_send(server->ncp_sock, req); + timeout = server->timeout_last << 1; + if (timeout > NCP_MAX_RPC_TIMEOUT) { + timeout = NCP_MAX_RPC_TIMEOUT; + } + server->timeout_last = timeout; + mod_timer(&server->timeout_tm, jiffies + timeout); + } + } +} + +void ncpdgram_timeout_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, timeout_tq); + mutex_lock(&server->rcv.creq_mutex); + __ncpdgram_timeout_proc(server); + mutex_unlock(&server->rcv.creq_mutex); +} + +static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) +{ + int result; + + if (buffer) { + result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT); + } else { + static unsigned char dummy[1024]; + + if (len > sizeof(dummy)) { + len = sizeof(dummy); + } + result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT); + } + if (result < 0) { + return result; + } + if (result > len) { + pr_err("tcp: bug in recvmsg (%u > %zu)\n", result, len); + return -EIO; + } + return result; +} + +static int __ncptcp_rcv_proc(struct ncp_server *server) +{ + /* We have to check the result, so store the complete header */ + while (1) { + int result; + struct ncp_request_reply *req; + int datalen; + int type; + + while (server->rcv.len) { + result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len); + if (result == -EAGAIN) { + return 0; + } + if (result <= 0) { + req = server->rcv.creq; + if (req) { + __ncp_abort_request(server, req, -EIO); + } else { + __ncptcp_abort(server); + } + if (result < 0) { + pr_err("tcp: error in recvmsg: %d\n", result); + } else { + ncp_dbg(1, "tcp: EOF\n"); + } + return -EIO; + } + if (server->rcv.ptr) { + server->rcv.ptr += result; + } + server->rcv.len -= result; + } + switch (server->rcv.state) { + case 0: + if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) { + pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic)); + __ncptcp_abort(server); + return -EIO; + } + datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; + if (datalen < 10) { + pr_err("tcp: Unexpected reply len %d\n", datalen); + __ncptcp_abort(server); + return -EIO; + } +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active) { + if (datalen < 18) { + pr_err("tcp: Unexpected reply len %d\n", datalen); + __ncptcp_abort(server); + return -EIO; + } + server->rcv.buf.len = datalen - 8; + server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1; + server->rcv.len = 8; + server->rcv.state = 4; + break; + } +#endif + type = ntohs(server->rcv.buf.type); +#ifdef CONFIG_NCPFS_PACKET_SIGNING +cont:; +#endif + if (type != NCP_REPLY) { + if (datalen - 8 <= sizeof(server->unexpected_packet.data)) { + *(__u16*)(server->unexpected_packet.data) = htons(type); + server->unexpected_packet.len = datalen - 8; + + server->rcv.state = 5; + server->rcv.ptr = server->unexpected_packet.data + 2; + server->rcv.len = datalen - 10; + break; + } + ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type); +skipdata2:; + server->rcv.state = 2; +skipdata:; + server->rcv.ptr = NULL; + server->rcv.len = datalen - 10; + break; + } + req = server->rcv.creq; + if (!req) { + ncp_dbg(1, "Reply without appropriate request\n"); + goto skipdata2; + } + if (datalen > req->datalen + 8) { + pr_err("tcp: Unexpected reply len %d (expected at most %zd)\n", datalen, req->datalen + 8); + server->rcv.state = 3; + goto skipdata; + } + req->datalen = datalen - 8; + ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY; + server->rcv.ptr = server->rxbuf + 2; + server->rcv.len = datalen - 10; + server->rcv.state = 1; + break; +#ifdef CONFIG_NCPFS_PACKET_SIGNING + case 4: + datalen = server->rcv.buf.len; + type = ntohs(server->rcv.buf.type2); + goto cont; +#endif + case 1: + req = server->rcv.creq; + if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { + if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) { + pr_err("tcp: Bad sequence number\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) { + pr_err("tcp: Connection number mismatch\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + } +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { + if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { + pr_err("tcp: Signature violation\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + } +#endif + ncp_finish_request(server, req, req->datalen); + nextreq:; + __ncp_next_request(server); + case 2: + next:; + server->rcv.ptr = (unsigned char*)&server->rcv.buf; + server->rcv.len = 10; + server->rcv.state = 0; + break; + case 3: + ncp_finish_request(server, server->rcv.creq, -EIO); + goto nextreq; + case 5: + info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); + goto next; + } + } +} + +void ncp_tcp_rcv_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); + + mutex_lock(&server->rcv.creq_mutex); + __ncptcp_rcv_proc(server); + mutex_unlock(&server->rcv.creq_mutex); +} + +void ncp_tcp_tx_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, tx.tq); + + mutex_lock(&server->rcv.creq_mutex); + __ncptcp_try_send(server); + mutex_unlock(&server->rcv.creq_mutex); +} + +static int do_ncp_rpc_call(struct ncp_server *server, int size, + unsigned char* reply_buf, int max_reply_size) +{ + int result; + struct ncp_request_reply *req; + + req = ncp_alloc_req(); + if (!req) + return -ENOMEM; + + req->reply_buf = reply_buf; + req->datalen = max_reply_size; + req->tx_iov[1].iov_base = server->packet; + req->tx_iov[1].iov_len = size; + req->tx_type = *(u_int16_t*)server->packet; + + result = ncp_add_request(server, req); + if (result < 0) + goto out; + + if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) { + ncp_abort_request(server, req, -EINTR); + result = -EINTR; + goto out; + } + + result = req->result; + +out: + ncp_req_put(req); + + return result; +} + +/* + * We need the server to be locked here, so check! + */ + +static int ncp_do_request(struct ncp_server *server, int size, + void* reply, int max_reply_size) +{ + int result; + + if (server->lock == 0) { + pr_err("Server not locked!\n"); + return -EIO; + } + if (!ncp_conn_valid(server)) { + return -EIO; + } + { + sigset_t old_set; + unsigned long mask, flags; + + spin_lock_irqsave(¤t->sighand->siglock, flags); + old_set = current->blocked; + if (current->flags & PF_EXITING) + mask = 0; + else + mask = sigmask(SIGKILL); + if (server->m.flags & NCP_MOUNT_INTR) { + /* FIXME: This doesn't seem right at all. So, like, + we can't handle SIGINT and get whatever to stop? + What if we've blocked it ourselves? What about + alarms? Why, in fact, are we mucking with the + sigmask at all? -- r~ */ + if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL) + mask |= sigmask(SIGINT); + if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) + mask |= sigmask(SIGQUIT); + } + siginitsetinv(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + + result = do_ncp_rpc_call(server, size, reply, max_reply_size); + + spin_lock_irqsave(¤t->sighand->siglock, flags); + current->blocked = old_set; + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + } + + ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result); + + return result; +} + +/* ncp_do_request assures that at least a complete reply header is + * received. It assumes that server->current_size contains the ncp + * request size + */ +int ncp_request2(struct ncp_server *server, int function, + void* rpl, int size) +{ + struct ncp_request_header *h; + struct ncp_reply_header* reply = rpl; + int result; + + h = (struct ncp_request_header *) (server->packet); + if (server->has_subfunction != 0) { + *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2); + } + h->type = NCP_REQUEST; + /* + * The server shouldn't know or care what task is making a + * request, so we always use the same task number. + */ + h->task = 2; /* (current->pid) & 0xff; */ + h->function = function; + + result = ncp_do_request(server, server->current_size, reply, size); + if (result < 0) { + ncp_dbg(1, "ncp_request_error: %d\n", result); + goto out; + } + server->completion = reply->completion_code; + server->conn_status = reply->connection_state; + server->reply_size = result; + server->ncp_reply_size = result - sizeof(struct ncp_reply_header); + + result = reply->completion_code; + + if (result != 0) + ncp_vdbg("completion code=%x\n", result); +out: + return result; +} + +int ncp_connect(struct ncp_server *server) +{ + struct ncp_request_header *h; + int result; + + server->connection = 0xFFFF; + server->sequence = 255; + + h = (struct ncp_request_header *) (server->packet); + h->type = NCP_ALLOC_SLOT_REQUEST; + h->task = 2; /* see above */ + h->function = 0; + + result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); + if (result < 0) + goto out; + server->connection = h->conn_low + (h->conn_high * 256); + result = 0; +out: + return result; +} + +int ncp_disconnect(struct ncp_server *server) +{ + struct ncp_request_header *h; + + h = (struct ncp_request_header *) (server->packet); + h->type = NCP_DEALLOC_SLOT_REQUEST; + h->task = 2; /* see above */ + h->function = 0; + + return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); +} + +void ncp_lock_server(struct ncp_server *server) +{ + mutex_lock(&server->mutex); + if (server->lock) + pr_warn("%s: was locked!\n", __func__); + server->lock = 1; +} + +void ncp_unlock_server(struct ncp_server *server) +{ + if (!server->lock) { + pr_warn("%s: was not locked!\n", __func__); + return; + } + server->lock = 0; + mutex_unlock(&server->mutex); +} diff --git a/drivers/staging/ncpfs/symlink.c b/drivers/staging/ncpfs/symlink.c new file mode 100644 index 000000000000..b6e16da4837a --- /dev/null +++ b/drivers/staging/ncpfs/symlink.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/fs/ncpfs/symlink.c + * + * Code for allowing symbolic links on NCPFS (i.e. NetWare) + * Symbolic links are not supported on native NetWare, so we use an + * infrequently-used flag (Sh) and store a two-word magic header in + * the file to make sure we don't accidentally use a non-link file + * as a link. + * + * When using the NFS namespace, we set the mode to indicate a symlink and + * don't bother with the magic numbers. + * + * from linux/fs/ext2/symlink.c + * + * Copyright (C) 1998-99, Frank A. Vorstenbosch + * + * ncpfs symlink handling code + * NLS support (c) 1999 Petr Vandrovec + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + + +#include <linux/uaccess.h> + +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/time.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/stat.h> +#include "ncp_fs.h" + +/* these magic numbers must appear in the symlink file -- this makes it a bit + more resilient against the magic attributes being set on random files. */ + +#define NCP_SYMLINK_MAGIC0 cpu_to_le32(0x6c6d7973) /* "symlnk->" */ +#define NCP_SYMLINK_MAGIC1 cpu_to_le32(0x3e2d6b6e) + +/* ----- read a symbolic link ------------------------------------------ */ + +static int ncp_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int error, length, len; + char *link, *rawlink; + char *buf = kmap(page); + + error = -ENOMEM; + rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); + if (!rawlink) + goto fail; + + if (ncp_make_open(inode,O_RDONLY)) + goto failEIO; + + error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, + 0,NCP_MAX_SYMLINK_SIZE,rawlink,&length); + + ncp_inode_close(inode); + /* Close file handle if no other users... */ + ncp_make_closed(inode); + if (error) + goto failEIO; + + if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) { + if (length<NCP_MIN_SYMLINK_SIZE || + ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 || + ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1) + goto failEIO; + link = rawlink + 8; + length -= 8; + } else { + link = rawlink; + } + + len = NCP_MAX_SYMLINK_SIZE; + error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0); + kfree(rawlink); + if (error) + goto fail; + SetPageUptodate(page); + kunmap(page); + unlock_page(page); + return 0; + +failEIO: + error = -EIO; + kfree(rawlink); +fail: + SetPageError(page); + kunmap(page); + unlock_page(page); + return error; +} + +/* + * symlinks can't do much... + */ +const struct address_space_operations ncp_symlink_aops = { + .readpage = ncp_symlink_readpage, +}; + +/* ----- create a new symbolic link -------------------------------------- */ + +int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { + struct inode *inode; + char *rawlink; + int length, err, i, outlen; + int kludge; + umode_t mode; + __le32 attr; + unsigned int hdr; + + ncp_dbg(1, "dir=%p, dentry=%p, symname=%s\n", dir, dentry, symname); + + if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) + kludge = 0; + else +#ifdef CONFIG_NCPFS_EXTRAS + if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS) + kludge = 1; + else +#endif + /* EPERM is returned by VFS if symlink procedure does not exist */ + return -EPERM; + + rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); + if (!rawlink) + return -ENOMEM; + + if (kludge) { + mode = 0; + attr = aSHARED | aHIDDEN; + ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0; + ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1; + hdr = 8; + } else { + mode = S_IFLNK | S_IRWXUGO; + attr = 0; + hdr = 0; + } + + length = strlen(symname); + /* map to/from server charset, do not touch upper/lower case as + symlink can point out of ncp filesystem */ + outlen = NCP_MAX_SYMLINK_SIZE - hdr; + err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0); + if (err) + goto failfree; + + outlen += hdr; + + err = -EIO; + if (ncp_create_new(dir,dentry,mode,0,attr)) { + goto failfree; + } + + inode=d_inode(dentry); + + if (ncp_make_open(inode, O_WRONLY)) + goto failfree; + + if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + 0, outlen, rawlink, &i) || i!=outlen) { + goto fail; + } + + ncp_inode_close(inode); + ncp_make_closed(inode); + kfree(rawlink); + return 0; +fail:; + ncp_inode_close(inode); + ncp_make_closed(inode); +failfree:; + kfree(rawlink); + return err; +} + +/* ----- EOF ----- */ diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 82bffd911435..2744c9f0920e 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -393,7 +393,8 @@ static void dcon_set_source_sync(struct dcon_priv *dcon, int arg) } static ssize_t dcon_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct dcon_priv *dcon = dev_get_drvdata(dev); @@ -401,7 +402,8 @@ static ssize_t dcon_mode_show(struct device *dev, } static ssize_t dcon_sleep_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct dcon_priv *dcon = dev_get_drvdata(dev); @@ -409,7 +411,8 @@ static ssize_t dcon_sleep_show(struct device *dev, } static ssize_t dcon_freeze_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct dcon_priv *dcon = dev_get_drvdata(dev); @@ -417,7 +420,8 @@ static ssize_t dcon_freeze_show(struct device *dev, } static ssize_t dcon_mono_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct dcon_priv *dcon = dev_get_drvdata(dev); @@ -425,13 +429,15 @@ static ssize_t dcon_mono_show(struct device *dev, } static ssize_t dcon_resumeline_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", resumeline); } static ssize_t dcon_mono_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { unsigned long enable_mono; int rc; @@ -446,7 +452,8 @@ static ssize_t dcon_mono_store(struct device *dev, } static ssize_t dcon_freeze_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { struct dcon_priv *dcon = dev_get_drvdata(dev); unsigned long output; @@ -474,7 +481,8 @@ static ssize_t dcon_freeze_store(struct device *dev, } static ssize_t dcon_resumeline_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { unsigned short rl; int rc; @@ -490,7 +498,8 @@ static ssize_t dcon_resumeline_store(struct device *dev, } static ssize_t dcon_sleep_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { unsigned long output; int ret; @@ -641,7 +650,8 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Add the backlight device for the DCON */ dcon_bl_props.brightness = dcon->bl_val; dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev, - dcon, &dcon_bl_ops, &dcon_bl_props); + dcon, &dcon_bl_ops, + &dcon_bl_props); if (IS_ERR(dcon->bl_dev)) { dev_err(&client->dev, "cannot register backlight dev (%ld)\n", PTR_ERR(dcon->bl_dev)); diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h index 8fbde5d3b4a6..fa89bb97c7b0 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ b/drivers/staging/olpc_dcon/olpc_dcon.h @@ -10,18 +10,18 @@ #define DCON_REG_ID 0 #define DCON_REG_MODE 1 -#define MODE_PASSTHRU (1<<0) -#define MODE_SLEEP (1<<1) -#define MODE_SLEEP_AUTO (1<<2) -#define MODE_BL_ENABLE (1<<3) -#define MODE_BLANK (1<<4) -#define MODE_CSWIZZLE (1<<5) -#define MODE_COL_AA (1<<6) -#define MODE_MONO_LUMA (1<<7) -#define MODE_SCAN_INT (1<<8) -#define MODE_CLOCKDIV (1<<9) -#define MODE_DEBUG (1<<14) -#define MODE_SELFTEST (1<<15) +#define MODE_PASSTHRU BIT(0) +#define MODE_SLEEP BIT(1) +#define MODE_SLEEP_AUTO BIT(2) +#define MODE_BL_ENABLE BIT(3) +#define MODE_BLANK BIT(4) +#define MODE_CSWIZZLE BIT(5) +#define MODE_COL_AA BIT(6) +#define MODE_MONO_LUMA BIT(7) +#define MODE_SCAN_INT BIT(8) +#define MODE_CLOCKDIV BIT(9) +#define MODE_DEBUG BIT(14) +#define MODE_SELFTEST BIT(15) #define DCON_REG_HRES 0x2 #define DCON_REG_HTOTAL 0x3 @@ -36,11 +36,11 @@ #define DCON_REG_MEM_OPT_B 0x42 /* Load Delay Locked Loop (DLL) settings for clock delay */ -#define MEM_DLL_CLOCK_DELAY (1<<0) +#define MEM_DLL_CLOCK_DELAY BIT(0) /* Memory controller power down function */ -#define MEM_POWER_DOWN (1<<8) +#define MEM_POWER_DOWN BIT(8) /* Memory controller software reset */ -#define MEM_SOFT_RESET (1<<0) +#define MEM_SOFT_RESET BIT(0) /* Status values */ diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c index 0c5a10c69401..633c58ce24ee 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c @@ -69,7 +69,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon) gpio_direction_input(OLPC_GPIO_DCON_IRQ); gpio_direction_input(OLPC_GPIO_DCON_BLANK); gpio_direction_output(OLPC_GPIO_DCON_LOAD, - dcon->curr_src == DCON_SOURCE_CPU); + dcon->curr_src == DCON_SOURCE_CPU); /* Set up the interrupt mappings */ diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 2a205c6173dc..3404cb9722c9 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -716,7 +716,8 @@ pi433_write(struct file *filp, const char __user *buf, { struct pi433_instance *instance; struct pi433_device *device; - int copied, retval; + int retval; + unsigned int copied; instance = filp->private_data; device = instance->device; @@ -927,8 +928,7 @@ static int setup_GPIOs(struct pi433_device *device) { retval = PTR_ERR(device->gpiod[i]); /* release already allocated gpios */ - for (i--; i>=0; i--) - { + for (i--; i >= 0; i--) { free_irq(device->irq_num[i], device); gpiod_put(device->gpiod[i]); } @@ -967,7 +967,7 @@ static void free_GPIOs(struct pi433_device *device) { int i; - for (i=0; i<NUM_DIO; i++) + for (i = 0; i < NUM_DIO; i++) { /* check if gpiod is valid */ if ( IS_ERR(device->gpiod[i]) ) @@ -989,7 +989,7 @@ static int pi433_get_minor(struct pi433_device *device) device->minor = retval; retval = 0; } else if (retval == -ENOSPC) { - dev_err(device->dev, "too many pi433 devices\n"); + dev_err(&device->spi->dev, "too many pi433 devices\n"); retval = -EINVAL; } mutex_unlock(&minor_lock); @@ -1097,19 +1097,10 @@ static int pi433_probe(struct spi_device *spi) SET_CHECKED(rf69_set_output_power_level (spi, 13)); SET_CHECKED(rf69_set_antenna_impedance (spi, fiftyOhm)); - /* start tx thread */ - device->tx_task_struct = kthread_run(pi433_tx_thread, - device, - "pi433_tx_task"); - if (IS_ERR(device->tx_task_struct)) { - dev_dbg(device->dev, "start of send thread failed"); - goto send_thread_failed; - } - /* determ minor number */ retval = pi433_get_minor(device); if (retval) { - dev_dbg(device->dev, "get of minor number failed"); + dev_dbg(&spi->dev, "get of minor number failed"); goto minor_failed; } @@ -1119,7 +1110,8 @@ static int pi433_probe(struct spi_device *spi) &spi->dev, device->devt, device, - "pi433"); + "pi433.%d", + device->minor); if (IS_ERR(device->dev)) { pr_err("pi433: device register failed\n"); retval = PTR_ERR(device->dev); @@ -1132,6 +1124,16 @@ static int pi433_probe(struct spi_device *spi) device->minor); } + /* start tx thread */ + device->tx_task_struct = kthread_run(pi433_tx_thread, + device, + "pi433.%d_tx_task", + device->minor); + if (IS_ERR(device->tx_task_struct)) { + dev_dbg(device->dev, "start of send thread failed"); + goto send_thread_failed; + } + /* create cdev */ device->cdev = cdev_alloc(); device->cdev->owner = THIS_MODULE; @@ -1148,12 +1150,12 @@ static int pi433_probe(struct spi_device *spi) return 0; cdev_failed: + kthread_stop(device->tx_task_struct); +send_thread_failed: device_destroy(pi433_class, device->devt); device_create_failed: pi433_free_minor(device); minor_failed: - kthread_stop(device->tx_task_struct); -send_thread_failed: free_GPIOs(device); GPIO_failed: kfree(device); @@ -1230,14 +1232,16 @@ static int __init pi433_init(void) pi433_class = class_create(THIS_MODULE, "pi433"); if (IS_ERR(pi433_class)) { - unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); + unregister_chrdev(MAJOR(pi433_dev), + pi433_spi_driver.driver.name); return PTR_ERR(pi433_class); } status = spi_register_driver(&pi433_spi_driver); if (status < 0) { class_destroy(pi433_class); - unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); + unregister_chrdev(MAJOR(pi433_dev), + pi433_spi_driver.driver.name); } return status; diff --git a/drivers/staging/pi433/pi433_if.h b/drivers/staging/pi433/pi433_if.h index e6ed3cd9b2e2..fc842c48c33e 100644 --- a/drivers/staging/pi433/pi433_if.h +++ b/drivers/staging/pi433/pi433_if.h @@ -58,8 +58,7 @@ * NOTE: struct layout is the same in 64bit and 32bit userspace. */ #define PI433_TX_CFG_IOCTL_NR 0 -struct pi433_tx_cfg -{ +struct pi433_tx_cfg { __u32 frequency; __u16 bit_rate; __u32 dev_frequency; diff --git a/drivers/staging/pi433/rf69_enum.h b/drivers/staging/pi433/rf69_enum.h index fbfb59bd3f3d..86429aa66ad1 100644 --- a/drivers/staging/pi433/rf69_enum.h +++ b/drivers/staging/pi433/rf69_enum.h @@ -18,14 +18,12 @@ #ifndef RF69_ENUM_H #define RF69_ENUM_H -enum optionOnOff -{ +enum optionOnOff { optionOff, optionOn }; -enum mode -{ +enum mode { mode_sleep, standby, synthesizer, @@ -33,21 +31,18 @@ enum mode receive }; -enum dataMode -{ +enum dataMode { packet, continuous, continuousNoSync }; -enum modulation -{ +enum modulation { OOK, FSK }; -enum modShaping -{ +enum modShaping { shapingOff, shaping1_0, shaping0_5, @@ -56,8 +51,7 @@ enum modShaping shaping2BR }; -enum paRamp -{ +enum paRamp { ramp3400, ramp2000, ramp1000, @@ -76,14 +70,12 @@ enum paRamp ramp10 }; -enum antennaImpedance -{ +enum antennaImpedance { fiftyOhm, twohundretOhm }; -enum lnaGain -{ +enum lnaGain { automatic, max, maxMinus6, @@ -94,8 +86,7 @@ enum lnaGain undefined }; -enum dccPercent -{ +enum dccPercent { dcc16Percent, dcc8Percent, dcc4Percent, @@ -106,22 +97,19 @@ enum dccPercent dcc0_125Percent }; -enum mantisse -{ +enum mantisse { mantisse16, mantisse20, mantisse24 }; -enum thresholdType -{ +enum thresholdType { fixed, peak, average }; -enum thresholdStep -{ +enum thresholdStep { step_0_5db, step_1_0db, step_1_5db, @@ -132,8 +120,7 @@ enum thresholdStep step_6_0db }; -enum thresholdDecrement -{ +enum thresholdDecrement { dec_every8th, dec_every4th, dec_every2nd, @@ -144,8 +131,7 @@ enum thresholdDecrement dec_16times }; -enum flag -{ +enum flag { modeSwitchCompleted, readyToReceive, readyToSend, @@ -165,33 +151,28 @@ enum flag batteryLow }; -enum fifoFillCondition -{ +enum fifoFillCondition { afterSyncInterrupt, always }; -enum packetFormat -{ +enum packetFormat { packetLengthFix, packetLengthVar }; -enum txStartCondition -{ +enum txStartCondition { fifoLevel, fifoNotEmpty }; -enum addressFiltering -{ +enum addressFiltering { filteringOff, nodeAddress, nodeOrBroadcastAddress }; -enum dagc -{ +enum dagc { normalMode, improve, improve4LowModulationIndex diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index de832b0b5eec..2a3f0746ee2c 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -336,7 +336,6 @@ uint rtl8712_hal_init(struct _adapter *padapter) r8712_read32(padapter, RCR)); val32 = r8712_read32(padapter, RCR); r8712_write32(padapter, RCR, (val32 | BIT(25))); /* Append PHY status */ - val32 = 0; val32 = r8712_read32(padapter, 0x10250040); r8712_write32(padapter, 0x10250040, (val32 & 0x00FFFFFF)); /* for usb rx aggregation */ diff --git a/drivers/staging/rtlwifi/cam.c b/drivers/staging/rtlwifi/cam.c index 9c8c907cb48e..ca1c9e36d976 100644 --- a/drivers/staging/rtlwifi/cam.c +++ b/drivers/staging/rtlwifi/cam.c @@ -181,7 +181,7 @@ void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) u32 ul_command; u32 ul_content; - u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + u32 ul_enc_algo; switch (rtlpriv->sec.pairwise_enc_algorithm) { case WEP40_ENCRYPTION: @@ -221,7 +221,7 @@ void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) u32 ul_command; u32 ul_content; - u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + u32 ul_encalgo; u8 entry_i; switch (rtlpriv->sec.pairwise_enc_algorithm) { diff --git a/drivers/staging/rtlwifi/core.c b/drivers/staging/rtlwifi/core.c index b00e51df984f..a43d37452e8b 100644 --- a/drivers/staging/rtlwifi/core.c +++ b/drivers/staging/rtlwifi/core.c @@ -509,15 +509,13 @@ static int rtl_op_suspend(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct timeval ts; RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); if (WARN_ON(!wow)) return -EINVAL; /* to resolve s4 can not wake up*/ - do_gettimeofday(&ts); - rtlhal->last_suspend_sec = ts.tv_sec; + rtlhal->last_suspend_sec = ktime_get_real_seconds(); if ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) && wow->n_patterns) _rtl_add_wowlan_patterns(hw, wow); @@ -536,7 +534,6 @@ static int rtl_op_resume(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct timeval ts; RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); rtlhal->driver_is_goingto_unload = false; @@ -544,8 +541,7 @@ static int rtl_op_resume(struct ieee80211_hw *hw) rtlhal->wake_from_pnp_sleep = true; /* to resovle s4 can not wake up*/ - do_gettimeofday(&ts); - if (ts.tv_sec - rtlhal->last_suspend_sec < 5) + if (ktime_get_real_seconds() - rtlhal->last_suspend_sec < 5) return -1; rtl_op_start(hw); diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c index f45487122517..483ea85943c3 100644 --- a/drivers/staging/rtlwifi/rtl8822be/fw.c +++ b/drivers/staging/rtlwifi/rtl8822be/fw.c @@ -464,6 +464,8 @@ bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf, int count; skb = dev_alloc_skb(size); + if (!skb) + return false; memcpy((u8 *)skb_put(skb, size), buf, size); if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE)) diff --git a/drivers/staging/rtlwifi/wifi.h b/drivers/staging/rtlwifi/wifi.h index eb91c130b245..ca0243fa2e66 100644 --- a/drivers/staging/rtlwifi/wifi.h +++ b/drivers/staging/rtlwifi/wifi.h @@ -1670,7 +1670,7 @@ struct rtl_hal { bool enter_pnp_sleep; bool wake_from_pnp_sleep; bool wow_enabled; - __kernel_time_t last_suspend_sec; + time64_t last_suspend_sec; u32 wowlan_fwsize; u8 *wowlan_firmware; diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 89e2cfe7d1cc..70e0b8623110 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -275,23 +275,6 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev) return 0; } -int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val) -{ - struct pci_dev *pdev; - u8 data; - u8 devfn = (dev << 3) | func; - - pdev = pci_get_bus_and_slot(bus, devfn); - if (!pdev) - return -1; - - pci_read_config_byte(pdev, offset, &data); - if (val) - *val = data; - - return 0; -} - #ifdef CONFIG_PM /* * power management diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 575e5734f2a5..62e467c5a6d7 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -174,8 +174,6 @@ static inline void get_current_time(u8 *timeval_buf, int buf_len) /* struct scsi_cmnd transfer buffer access utilities */ enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; -int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val); - #define _MSG_TRACE #include "trace.h" diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO index a3a877d90066..f710ab15abfe 100644 --- a/drivers/staging/sm750fb/TODO +++ b/drivers/staging/sm750fb/TODO @@ -6,8 +6,8 @@ TODO: - check on hardware effects of removal of USE_HW_I2C and USE_DVICHIP (these two are supposed to be sample code which is given here if someone wants to use those functionalities) -- move it to drivers/video/fbdev -- modify the code for drm framework +- must be ported to the atomic kms framework in the drm subsystem (which will + give you a basic fbdev driver for free) Please send any patches to Greg Kroah-Hartman <greg@kroah.com> diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index 66061b5c3427..0ed1fefee0e9 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -64,13 +64,8 @@ int speakup_set_selection(struct tty_struct *tty) ps = spk_ys * vc->vc_size_row + (spk_xs << 1); pe = spk_ye * vc->vc_size_row + (spk_xe << 1); - if (ps > pe) { - /* make sel_start <= sel_end */ - int tmp = ps; - - ps = pe; - pe = tmp; - } + if (ps > pe) /* make sel_start <= sel_end */ + swap(ps, pe); if (spk_sel_cons != vc_cons[fg_console].d) { speakup_clear_selection(); diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 5cd407ca2251..a3c87544bf96 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -1,17 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2016 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __IOCHANNEL_H__ diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 1a0986ba3d24..fb4d3f814568 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -1,17 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* diff --git a/drivers/staging/unisys/include/visorchannel.h b/drivers/staging/unisys/include/visorchannel.h index 33945749c8b6..0c45b63e973c 100644 --- a/drivers/staging/unisys/include/visorchannel.h +++ b/drivers/staging/unisys/include/visorchannel.h @@ -1,17 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __VISORCHANNEL_H__ diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 9ee9886a9aed..bcc7b8e3d8eb 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __CONTROLVMCHANNEL_H__ diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 981b180f3c4b..398b4b12e972 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __VBUSCHANNEL_H__ diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 6cb6eb0673c6..a16715525dc9 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright � 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #include <linux/ctype.h> diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 4a8b12d7cfaa..e48498fedc49 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __VISORBUS_PRIVATE_H__ diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index aae16073ba03..f3996a750c3b 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index fed554a43151..daff44d7a8c0 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #include <linux/acpi.h> @@ -590,7 +581,8 @@ static void *parser_name_get(struct parser_context *ctx) struct visor_controlvm_parameters_header *phdr; phdr = &ctx->data; - if (phdr->name_offset + phdr->name_length > ctx->param_bytes) + if ((unsigned long)phdr->name_offset + + (unsigned long)phdr->name_length > ctx->param_bytes) return NULL; ctx->curr = (char *)&phdr + phdr->name_offset; ctx->bytes_remaining = phdr->name_length; @@ -1317,13 +1309,13 @@ static void parser_done(struct parser_context *ctx) static struct parser_context *parser_init_stream(u64 addr, u32 bytes, bool *retry) { - int allocbytes; + unsigned long allocbytes; struct parser_context *ctx; void *mapping; *retry = false; /* alloc an extra byte to ensure payload is \0 terminated */ - allocbytes = bytes + 1 + (sizeof(struct parser_context) - + allocbytes = (unsigned long)bytes + 1 + (sizeof(struct parser_context) - sizeof(struct visor_controlvm_parameters_header)); if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 0bcd3acb7b0c..da650d64695a 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -1,17 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2012 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #include <linux/debugfs.h> diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index 53975a09535f..67dac430ce0c 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __SPAR_ULTRAINPUTREPORT_H__ diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 450f003743c0..dabc5b44208e 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2011 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 6d8239163ba5..112a76ec0628 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1,15 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* This driver lives in a spar partition, and registers to ethernet io diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index be936b8fe317..e26895dc052e 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -328,11 +328,9 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, pr_debug("Grab another frame"); vchiq_mmal_port_parameter_set( instance, - dev->capture. - camera_port, + dev->capture.camera_port, MMAL_PARAMETER_CAPTURE, - &dev->capture. - frame_count, + &dev->capture.frame_count, sizeof(dev->capture.frame_count)); } } else { @@ -343,37 +341,17 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, if (dev->capture.frame_count) { if (dev->capture.vc_start_timestamp != -1 && pts != 0) { - struct timeval timestamp; + ktime_t timestamp; s64 runtime_us = pts - dev->capture.vc_start_timestamp; - u32 div = 0; - u32 rem = 0; - - div = - div_u64_rem(runtime_us, USEC_PER_SEC, &rem); - timestamp.tv_sec = - dev->capture.kernel_start_ts.tv_sec + div; - timestamp.tv_usec = - dev->capture.kernel_start_ts.tv_usec + rem; - - if (timestamp.tv_usec >= - USEC_PER_SEC) { - timestamp.tv_sec++; - timestamp.tv_usec -= - USEC_PER_SEC; - } + timestamp = ktime_add_us(dev->capture.kernel_start_ts, + runtime_us); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Convert start time %d.%06d and %llu " - "with offset %llu to %d.%06d\n", - (int)dev->capture.kernel_start_ts. - tv_sec, - (int)dev->capture.kernel_start_ts. - tv_usec, + "Convert start time %llu and %llu with offset %llu to %llu\n", + ktime_to_ns(dev->capture.kernel_start_ts), dev->capture.vc_start_timestamp, pts, - (int)timestamp.tv_sec, - (int)timestamp.tv_usec); - buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL + - timestamp.tv_usec * 1000ULL; + ktime_to_ns(timestamp)); + buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp); } else { buf->vb.vb2_buf.timestamp = ktime_get_ns(); } @@ -387,11 +365,9 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, "Grab another frame as buffer has EOS"); vchiq_mmal_port_parameter_set( instance, - dev->capture. - camera_port, + dev->capture.camera_port, MMAL_PARAMETER_CAPTURE, - &dev->capture. - frame_count, + &dev->capture.frame_count, sizeof(dev->capture.frame_count)); } } else { @@ -547,7 +523,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) "Start time %lld size %d\n", dev->capture.vc_start_timestamp, parameter_size); - v4l2_get_timestamp(&dev->capture.kernel_start_ts); + dev->capture.kernel_start_ts = ktime_get(); /* enable the camera port */ dev->capture.port->cb_ctx = dev; @@ -555,8 +531,8 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb); if (ret) { v4l2_err(&dev->v4l2_dev, - "Failed to enable capture port - error %d. " - "Disabling camera port again\n", ret); + "Failed to enable capture port - error %d. Disabling camera port again\n", + ret); vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port); @@ -1213,8 +1189,8 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev, port->current_buffer.size = (f->fmt.pix.sizeimage < (100 << 10)) - ? (100 << 10) : f->fmt.pix. - sizeimage; + ? (100 << 10) + : f->fmt.pix.sizeimage; } v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h index 404037476bc5..83920683a448 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h @@ -92,7 +92,7 @@ struct bm2835_mmal_dev { /* VC start timestamp for streaming */ s64 vc_start_timestamp; /* Kernel start timestamp for streaming */ - struct timeval kernel_start_ts; + ktime_t kernel_start_ts; struct vchiq_mmal_port *port; /* port being used for capture */ /* camera port being used for capture */ diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c index 6ea7fb0ea50e..6c4d8b4c7cd9 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c @@ -618,8 +618,8 @@ static void buffer_to_host_cb(struct vchiq_mmal_instance *instance, struct mmal_msg_context *msg_context; u32 handle; - pr_debug("buffer_to_host_cb: instance:%p msg:%p msg_len:%d\n", - instance, msg, msg_len); + pr_debug("%s: instance:%p msg:%p msg_len:%d\n", + __func__, instance, msg, msg_len); if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) { handle = msg->u.buffer_from_host.drvbuf.client_context; @@ -1360,8 +1360,7 @@ static int port_action_handle(struct vchiq_mmal_instance *instance, ret = -rmsg->u.port_action_reply.status; - pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)" \ - " connect component:0x%x connect port:%d\n", + pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n", __func__, ret, port->component->handle, port->handle, port_action_type_names[action_type], diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 44dfa5421374..f0b163473426 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index feaf222574ee..b8ee33dcb352 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: baseband.h * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 14034e342aa6..ea0a4b57852c 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: card.c * Purpose: Provide functions to setup NIC operation mode * Functions: diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 1a04dbb57d42..487039a64587 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: card.h * * Purpose: Provide functions to setup NIC operation mode diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index ab89956511a0..dec6f0f23b88 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: channel.c * */ diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index 8fe70760e548..53f623a4af65 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -1,19 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: channel.h - * */ #ifndef _CHANNEL_H_ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 2fee6e759ad8..b4a0037b40c1 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: desc.h * * Purpose:The header file of descriptor diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 3ae40d846a09..2f9e9219e8c8 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: device.h * * Purpose: MAC Data structure diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h index 0298ea923f97..73f904b51b96 100644 --- a/drivers/staging/vt6655/device_cfg.h +++ b/drivers/staging/vt6655/device_cfg.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: device_cfg.h * * Purpose: Driver configuration header diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 1123b4f1e1d6..676a0882cdd4 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: device_main.c * * Purpose: driver entry for initial, open, close, tx and rx. diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 9b3fa779258a..088d2d9dbc21 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: dpc.c * * Purpose: handle dpc rx functions diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h index 6e75fa9c5618..93af4220605f 100644 --- a/drivers/staging/vt6655/dpc.h +++ b/drivers/staging/vt6655/dpc.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: dpc.h * * Purpose: diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index d891993b20cf..4d6b48fd119d 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: key.c * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index a5024611af60..0942d8703f98 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: key.h * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index f7550b215f72..4750863c1bb7 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: mac.c * * Purpose: MAC routines diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index db401e32ae23..b8ab09434773 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: mac.h * * Purpose: MAC routines diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 716d2a80f840..d6c581b31569 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: power.c * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index f360c5966523..2ec40045fddb 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: power.h * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index edf7db9d53b3..03b0d56dbe9e 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: rf.c * * Purpose: rf function code diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index ba222301d49d..bfce5a89657d 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: rf.h * * Purpose: diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 3efe19a1b13f..9aa4d5262aaa 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: rxtx.c * * Purpose: handle WMAC/802.3/802.11 rx & tx functions diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index 095258923ebd..08db848613f0 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: rxtx.h * * Purpose: diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index 635f271595f6..df57d120ed30 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: srom.c * * Purpose:Implement functions to access eeprom diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index 6e03ab6dfa9d..577f20dc4308 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: srom.h * * Purpose: Implement functions to access eeprom diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h index d6a0563ad55c..6795b5d74cfc 100644 --- a/drivers/staging/vt6655/tmacro.h +++ b/drivers/staging/vt6655/tmacro.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: tmacro.h * * Purpose: define basic common types and macros diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index 9806b5989014..61b3e568ff9a 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * * File: upc.h * * Purpose: Macros to access device diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 882fe54ce41d..b29ba237fa29 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index fe1c25c64cca..a907e3026012 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: baseband.h * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 4fd9cd64c6e8..501f482b41c4 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: card.c * Purpose: Provide functions to setup NIC operation mode * Functions: diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h index 7f08cda27e2c..0a91d9ba4688 100644 --- a/drivers/staging/vt6656/card.h +++ b/drivers/staging/vt6656/card.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: card.h * * Purpose: Provide functions to setup NIC operation mode diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index a4299f405d7f..5d57d34577f5 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: channel.c * * Purpose: Channel number mapping diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h index 62f18a959098..6d0d2825d992 100644 --- a/drivers/staging/vt6656/channel.h +++ b/drivers/staging/vt6656/channel.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: channel.h * * Purpose: Country Regulation Rules header file diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h index 59e3071021bd..ac45ebb71195 100644 --- a/drivers/staging/vt6656/desc.h +++ b/drivers/staging/vt6656/desc.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: desc.h * * Purpose:The header file of descriptor diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 74715c854856..a2feeb916836 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: device.h * * Purpose: MAC Data structure diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 655f0002f880..c3b5b1431048 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: dpc.c * * Purpose: handle dpc rx functions diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index 5d0454f3af0e..ddd0cb710512 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: dpc.h * * Purpose: diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index 093a6048bd22..38521c338917 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6656/firmware.h b/drivers/staging/vt6656/firmware.h index f753019c94c9..f30ae90cbb1f 100644 --- a/drivers/staging/vt6656/firmware.h +++ b/drivers/staging/vt6656/firmware.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: firmware.h * * Purpose: Version and Release Information diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index c6ffbe0e2728..504424b19fcf 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: int.c * * Purpose: Handle USB interrupt endpoint diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index b5f1b4b02ce4..1e6ff925701a 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: int.h * * Purpose: diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index cc18cb141bff..91dede54cc1f 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: key.c * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h index cfc6c2131536..1306ff441b87 100644 --- a/drivers/staging/vt6656/key.h +++ b/drivers/staging/vt6656/key.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: key.h * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c index 417fdad1f9ae..0b543854ea97 100644 --- a/drivers/staging/vt6656/mac.c +++ b/drivers/staging/vt6656/mac.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: mac.c * * Purpose: MAC routines diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h index 29f37a0ff156..94e700fcd0b6 100644 --- a/drivers/staging/vt6656/mac.h +++ b/drivers/staging/vt6656/mac.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: mac.h * * Purpose: MAC routines diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index cc6d8778fe5b..1b51b835dd6f 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: main_usb.c * * Purpose: driver entry for initial, open, close, tx and rx. diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index c466e0614bc4..7a086c72d5a8 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: power.c * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h index 859e75fc77ac..d5a3198206da 100644 --- a/drivers/staging/vt6656/power.h +++ b/drivers/staging/vt6656/power.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: power.h * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 3a9d19a0b842..18f75dcc65d2 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: rf.c * * Purpose: rf function code diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h index c907a18047d2..f77866a9c177 100644 --- a/drivers/staging/vt6656/rf.h +++ b/drivers/staging/vt6656/rf.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: rf.h * * Purpose: diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index a44abcce6fb4..26ca3fa29301 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: rxtx.c * * Purpose: handle WMAC/802.3/802.11 rx & tx functions diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h index 1ba8647bea86..44698f41a234 100644 --- a/drivers/staging/vt6656/rxtx.h +++ b/drivers/staging/vt6656/rxtx.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: rxtx.h * * Purpose: diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 23eaef458556..273176386a51 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: usbpipe.c * * Purpose: Handle USB control endpoint diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h index 9fc5ac0ef6c1..5d7708fcf557 100644 --- a/drivers/staging/vt6656/usbpipe.h +++ b/drivers/staging/vt6656/usbpipe.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: usbpipe.h * * Purpose: diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index b2fc17f1381b..3eb2f11a5de1 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: wcmd.c * * Purpose: Handles the management command interface functions diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h index 727ec14380c4..4a96f4de980d 100644 --- a/drivers/staging/vt6656/wcmd.h +++ b/drivers/staging/vt6656/wcmd.h @@ -1,18 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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. - * - * * File: wcmd.h * * Purpose: Handles the management command interface functions diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 119f3459b5bb..da1fe4390707 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include "wilc_wfi_cfgoperations.h" #include "wilc_wlan_if.h" #include "wilc_wlan.h" diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index ce54864569c7..0deb61a21b27 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * NewportMedia WiFi chipset driver test tools - wilc-debug * Copyright (c) 2012 NewportMedia Inc. diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 0189e3edbbbe..bd2b29b8b356 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) Atmel Corporation. All rights reserved. * diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 5ef84410e0f2..ff2ba1057cdf 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) Atmel Corporation. All rights reserved. * diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index f49dfa82f1b8..999fd09ad1cd 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include <linux/completion.h> #include "wilc_wlan_if.h" #include "wilc_wlan.h" diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f5a3a1ce21ce..85c3af00abd2 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* hfa384x.h * * Defines the constants and data structures for the hfa384x diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 197f5a914e8f..84f3657e26a2 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/hfa384x_usb.c * * Functions that talk to the USB variantof the Intersil hfa384x MAC diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index c1b6d426bcad..855b424f6423 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211conv.c * * Ether/802.11 conversions and packet buffer routines diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h index 66332b1fb6d5..28459dcea4b1 100644 --- a/drivers/staging/wlan-ng/p80211conv.h +++ b/drivers/staging/wlan-ng/p80211conv.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211conv.h * * Ether/802.11 conversions and packet buffer routines diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h index 2c44c613a586..133d70c08ecf 100644 --- a/drivers/staging/wlan-ng/p80211hdr.h +++ b/drivers/staging/wlan-ng/p80211hdr.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211hdr.h * * Macros, types, and functions for handling 802.11 MAC headers diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h index ab6067e65050..d8cde1d8870b 100644 --- a/drivers/staging/wlan-ng/p80211ioctl.h +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211ioctl.h * * Declares constants and types for the p80211 ioctls diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index ea3d9ce222b9..4ac2f08a520a 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. * -------------------------------------------------------------------- * diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index 850d897fc163..15b7c08e210d 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. * -------------------------------------------------------------------- * diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h index 653950fd9843..3c12929858cb 100644 --- a/drivers/staging/wlan-ng/p80211mgmt.h +++ b/drivers/staging/wlan-ng/p80211mgmt.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211mgmt.h * * Macros, types, and functions to handle 802.11 mgmt frames diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h index 40c5cf5997c7..ae119ecd74b0 100644 --- a/drivers/staging/wlan-ng/p80211msg.h +++ b/drivers/staging/wlan-ng/p80211msg.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211msg.h * * Macros, constants, types, and funcs for req and ind messages diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 0f503652740f..0b5aecd6d233 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211knetdev.c * * Linux Kernel net device interface diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 8e0d08298c8b..cebbe746a52f 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211netdev.h * * WLAN net device structure and functions diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index afe847722cf7..c36d01469afc 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211req.c * * Request/Indication/MacMgmt interface handling functions diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index 6c72f59993e0..20be2c3af4c1 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211req.h * * Request handling functions diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 263ef2ddb197..94420562c418 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* * p80211types.h * diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 6492ffe59085..8bd92bba0ac1 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211wep.c * * WEP encode/decode for P80211. diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 344bec8cc31b..5860d0d65841 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* from src/prism2/download/prism2dl.c * * utility for downloading prism2 images moved into kernelspace diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 72070593394a..78934e435fcf 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/prism2mgmt.c * * Management request handler functions. diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index c062418f1202..564c3f4a3e03 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* prism2mgmt.h * * Declares the mgmt command handler functions diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index e41207d97309..edad299ff5ad 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/prism2mib.c * * Management request for mibset/mibget diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 99316b9a4e49..fed0b8ceca6f 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/prism2sta.c * * Implements the station functionality for prism2 diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index a3af1cbbf8ee..e19a8291cb2a 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -18,19 +18,6 @@ static const struct pci_device_id xgifb_pci_table[] = { MODULE_DEVICE_TABLE(pci, xgifb_pci_table); -/* To be included in fb.h */ -#define XGISR (xgifb_info->dev_info.P3c4) -#define XGICR (xgifb_info->dev_info.P3d4) -#define XGIDACA (xgifb_info->dev_info.P3c8) -#define XGIDACD (xgifb_info->dev_info.P3c9) -#define XGIPART1 (xgifb_info->dev_info.Part1Port) -#define XGIPART2 (xgifb_info->dev_info.Part2Port) -#define XGIPART3 (xgifb_info->dev_info.Part3Port) -#define XGIPART4 (xgifb_info->dev_info.Part4Port) -#define XGIPART5 (xgifb_info->dev_info.Part5Port) -#define XGIDAC2A XGIPART5 -#define XGIDAC2D (XGIPART5 + 1) - #define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */ #define IND_XGI_SCRATCH_REG_CR31 0x31 #define IND_XGI_SCRATCH_REG_CR32 0x32 diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index b813f1d460ce..10107de0119a 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * XG20, XG21, XG40, XG42 frame buffer device * for Linux kernels 2.5.x, 2.6.x @@ -31,18 +32,19 @@ static unsigned int refresh_rate; #ifdef DEBUG static void dumpVGAReg(struct xgifb_video_info *xgifb_info) { + struct vb_device_info *vb = &xgifb_info->dev_info; u8 i, reg; - xgifb_reg_set(XGISR, 0x05, 0x86); + xgifb_reg_set(vb->P3c4, 0x05, 0x86); for (i = 0; i < 0x4f; i++) { - reg = xgifb_reg_get(XGISR, i); + reg = xgifb_reg_get(vb->P3c4, i); pr_debug("o 3c4 %x\n", i); pr_debug("i 3c5 => %x\n", reg); } for (i = 0; i < 0xF0; i++) { - reg = xgifb_reg_get(XGICR, i); + reg = xgifb_reg_get(vb->P3d4, i); pr_debug("o 3d4 %x\n", i); pr_debug("i 3d5 => %x\n", reg); } @@ -644,9 +646,10 @@ static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info, static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info) { + struct vb_device_info *vb = &xgifb_info->dev_info; u8 cr30 = 0, cr31 = 0; - cr31 = xgifb_reg_get(XGICR, 0x31); + cr31 = xgifb_reg_get(vb->P3d4, 0x31); cr31 &= ~0x60; switch (xgifb_info->display2) { @@ -683,14 +686,15 @@ static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info) cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE); } - xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30); - xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31); - xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, + xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR30, cr30); + xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR31, cr31); + xgifb_reg_set(vb->P3d4, IND_XGI_SCRATCH_REG_CR33, (xgifb_info->rate_idx & 0x0F)); } static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) { + struct vb_device_info *vb = &xgifb_info->dev_info; u8 reg; unsigned char doit = 1; @@ -713,7 +717,7 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) /* We can't switch off CRT1 if bridge is in slave mode */ if (xgifb_info->hasVB != HASVB_NONE) { - reg = xgifb_reg_get(XGIPART1, 0x00); + reg = xgifb_reg_get(vb->Part1Port, 0x00); if ((reg & 0x50) == 0x10) doit = 0; @@ -722,18 +726,18 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) XGIfb_crt1off = 0; } - reg = xgifb_reg_get(XGICR, 0x17); + reg = xgifb_reg_get(vb->P3d4, 0x17); if ((XGIfb_crt1off) && (doit)) reg &= ~0x80; else reg |= 0x80; - xgifb_reg_set(XGICR, 0x17, reg); + xgifb_reg_set(vb->P3d4, 0x17, reg); - xgifb_reg_and(XGISR, IND_SIS_RAMDAC_CONTROL, ~0x04); + xgifb_reg_and(vb->P3c4, IND_SIS_RAMDAC_CONTROL, ~0x04); if (xgifb_info->display2 == XGIFB_DISP_TV && xgifb_info->hasVB == HASVB_301) { - reg = xgifb_reg_get(XGIPART4, 0x01); + reg = xgifb_reg_get(vb->Part4Port, 0x01); if (reg < 0xB0) { /* Set filter for XGI301 */ int filter_tb; @@ -760,60 +764,58 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) filter = -1; break; } - xgifb_reg_or(XGIPART1, - SIS_CRT2_WENABLE_315, - 0x01); + xgifb_reg_or(vb->Part1Port, SIS_CRT2_WENABLE_315, 0x01); if (xgifb_info->TV_type == TVMODE_NTSC) { - xgifb_reg_and(XGIPART2, 0x3a, 0x1f); + xgifb_reg_and(vb->Part2Port, 0x3a, 0x1f); if (xgifb_info->TV_plug == TVPLUG_SVIDEO) { - xgifb_reg_and(XGIPART2, 0x30, 0xdf); + xgifb_reg_and(vb->Part2Port, 0x30, 0xdf); } else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE) { - xgifb_reg_or(XGIPART2, 0x30, 0x20); + xgifb_reg_or(vb->Part2Port, 0x30, 0x20); switch (xgifb_info->video_width) { case 640: - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x35, 0xEB); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x36, 0x04); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x37, 0x25); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x38, 0x18); break; case 720: - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x35, 0xEE); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x36, 0x0C); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x37, 0x22); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x38, 0x08); break; case 800: - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x35, 0xEB); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x36, 0x15); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x37, 0x25); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x38, 0xF6); break; @@ -821,55 +823,55 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) } } else if (xgifb_info->TV_type == TVMODE_PAL) { - xgifb_reg_and(XGIPART2, 0x3A, 0x1F); + xgifb_reg_and(vb->Part2Port, 0x3A, 0x1F); if (xgifb_info->TV_plug == TVPLUG_SVIDEO) { - xgifb_reg_and(XGIPART2, 0x30, 0xDF); + xgifb_reg_and(vb->Part2Port, 0x30, 0xDF); } else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE) { - xgifb_reg_or(XGIPART2, 0x30, 0x20); + xgifb_reg_or(vb->Part2Port, 0x30, 0x20); switch (xgifb_info->video_width) { case 640: - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x35, 0xF1); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x36, 0xF7); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x37, 0x1F); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x38, 0x32); break; case 720: - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x35, 0xF3); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x36, 0x00); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x37, 0x1D); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x38, 0x20); break; case 800: - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x35, 0xFC); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x36, 0xFB); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x37, 0x14); - xgifb_reg_set(XGIPART2, + xgifb_reg_set(vb->Part2Port, 0x38, 0x2A); break; @@ -882,10 +884,10 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) pr_debug("FilterTable[%d]-%d: %*ph\n", filter_tb, filter, 4, f); - xgifb_reg_set(XGIPART2, 0x35, f[0]); - xgifb_reg_set(XGIPART2, 0x36, f[1]); - xgifb_reg_set(XGIPART2, 0x37, f[2]); - xgifb_reg_set(XGIPART2, 0x38, f[3]); + xgifb_reg_set(vb->Part2Port, 0x35, f[0]); + xgifb_reg_set(vb->Part2Port, 0x36, f[1]); + xgifb_reg_set(vb->Part2Port, 0x37, f[2]); + xgifb_reg_set(vb->Part2Port, 0x38, f[3]); } } } @@ -895,6 +897,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info) { struct xgifb_video_info *xgifb_info = info->par; + struct vb_device_info *vb = &xgifb_info->dev_info; struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info; unsigned int htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; @@ -981,11 +984,10 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 6; - xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD); + xgifb_reg_set(vb->P3c4, IND_SIS_PASSWORD, SIS_PASSWORD); - xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff)); - xgifb_reg_set(XGISR, - 0x0E, + xgifb_reg_set(vb->P3d4, 0x13, (info->fix.line_length & 0x00ff)); + xgifb_reg_set(vb->P3c4, 0x0E, (info->fix.line_length & 0xff00) >> 8); XGIfb_post_setmode(xgifb_info); @@ -1013,16 +1015,16 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->XGI310_AccelDepth = 0x00000000; xgifb_info->video_cmap_len = 256; #if defined(__BIG_ENDIAN) - cr_data = xgifb_reg_get(XGICR, 0x4D); - xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0)); + cr_data = xgifb_reg_get(vb->P3d4, 0x4D); + xgifb_reg_set(vb->P3d4, 0x4D, (cr_data & 0xE0)); #endif break; case 16: xgifb_info->DstColor = 0x8000; xgifb_info->XGI310_AccelDepth = 0x00010000; #if defined(__BIG_ENDIAN) - cr_data = xgifb_reg_get(XGICR, 0x4D); - xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B)); + cr_data = xgifb_reg_get(vb->P3d4, 0x4D); + xgifb_reg_set(vb->P3d4, 0x4D, ((cr_data & 0xE0) | 0x0B)); #endif xgifb_info->video_cmap_len = 16; break; @@ -1031,8 +1033,8 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->XGI310_AccelDepth = 0x00020000; xgifb_info->video_cmap_len = 16; #if defined(__BIG_ENDIAN) - cr_data = xgifb_reg_get(XGICR, 0x4D); - xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15)); + cr_data = xgifb_reg_get(vb->P3d4, 0x4D); + xgifb_reg_set(vb->P3d4, 0x4D, ((cr_data & 0xE0) | 0x15)); #endif break; default: @@ -1051,6 +1053,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct xgifb_video_info *xgifb_info = info->par; + struct vb_device_info *vb = &xgifb_info->dev_info; unsigned int base; base = var->yoffset * info->var.xres_virtual + var->xoffset; @@ -1068,22 +1071,20 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) break; } - xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD); + xgifb_reg_set(vb->P3c4, IND_SIS_PASSWORD, SIS_PASSWORD); - xgifb_reg_set(XGICR, 0x0D, base & 0xFF); - xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF); - xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF); - xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03); - xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04); + xgifb_reg_set(vb->P3d4, 0x0D, base & 0xFF); + xgifb_reg_set(vb->P3d4, 0x0C, (base >> 8) & 0xFF); + xgifb_reg_set(vb->P3c4, 0x0D, (base >> 16) & 0xFF); + xgifb_reg_set(vb->P3c4, 0x37, (base >> 24) & 0x03); + xgifb_reg_and_or(vb->P3c4, 0x37, 0xDF, (base >> 21) & 0x04); if (xgifb_info->display2 != XGIFB_DISP_NONE) { - xgifb_reg_or(XGIPART1, SIS_CRT2_WENABLE_315, 0x01); - xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF)); - xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF)); - xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF)); - xgifb_reg_and_or(XGIPART1, - 0x02, - 0x7F, + xgifb_reg_or(vb->Part1Port, SIS_CRT2_WENABLE_315, 0x01); + xgifb_reg_set(vb->Part1Port, 0x06, (base & 0xFF)); + xgifb_reg_set(vb->Part1Port, 0x05, ((base >> 8) & 0xFF)); + xgifb_reg_set(vb->Part1Port, 0x04, ((base >> 16) & 0xFF)); + xgifb_reg_and_or(vb->Part1Port, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); } return 0; @@ -1110,21 +1111,22 @@ static int XGIfb_setcolreg(unsigned int regno, unsigned int red, unsigned int transp, struct fb_info *info) { struct xgifb_video_info *xgifb_info = info->par; + struct vb_device_info *vb = &xgifb_info->dev_info; if (regno >= XGIfb_get_cmap_len(&info->var)) return 1; switch (info->var.bits_per_pixel) { case 8: - outb(regno, XGIDACA); - outb((red >> 10), XGIDACD); - outb((green >> 10), XGIDACD); - outb((blue >> 10), XGIDACD); + outb(regno, vb->P3c8); + outb((red >> 10), vb->P3c9); + outb((green >> 10), vb->P3c9); + outb((blue >> 10), vb->P3c9); if (xgifb_info->display2 != XGIFB_DISP_NONE) { - outb(regno, XGIDAC2A); - outb((red >> 8), XGIDAC2D); - outb((green >> 8), XGIDAC2D); - outb((blue >> 8), XGIDAC2D); + outb(regno, vb->Part5Port); + outb((red >> 8), (vb->Part5Port + 1)); + outb((green >> 8), (vb->Part5Port + 1)); + outb((blue >> 8), (vb->Part5Port + 1)); } break; case 16: @@ -1344,18 +1346,19 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, static int XGIfb_blank(int blank, struct fb_info *info) { struct xgifb_video_info *xgifb_info = info->par; + struct vb_device_info *vb = &xgifb_info->dev_info; u8 reg; - reg = xgifb_reg_get(XGICR, 0x17); + reg = xgifb_reg_get(vb->P3d4, 0x17); if (blank > 0) reg &= 0x7f; else reg |= 0x80; - xgifb_reg_set(XGICR, 0x17, reg); - xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */ - xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */ + xgifb_reg_set(vb->P3d4, 0x17, reg); + xgifb_reg_set(vb->P3c4, 0x00, 0x01); /* Synchronous Reset */ + xgifb_reg_set(vb->P3c4, 0x00, 0x03); /* End Reset */ return 0; } @@ -1379,14 +1382,15 @@ static struct fb_ops XGIfb_ops = { static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info) { + struct vb_device_info *vb = &xgifb_info->dev_info; u8 ChannelNum, tmp; u8 reg = 0; /* xorg driver sets 32MB * 1 channel */ if (xgifb_info->chip == XG27) - xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51); + xgifb_reg_set(vb->P3c4, IND_SIS_DRAM_SIZE, 0x51); - reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE); + reg = xgifb_reg_get(vb->P3c4, IND_SIS_DRAM_SIZE); if (!reg) return -1; @@ -1457,12 +1461,13 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info) static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) { + struct vb_device_info *vb = &xgifb_info->dev_info; u8 cr32, temp = 0; xgifb_info->TV_plug = 0; xgifb_info->TV_type = 0; - cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32); + cr32 = xgifb_reg_get(vb->P3d4, IND_XGI_SCRATCH_REG_CR32); if ((cr32 & SIS_CRT1) && !XGIfb_crt1off) { XGIfb_crt1off = 0; @@ -1499,7 +1504,7 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) } if (xgifb_info->TV_type == 0) { - temp = xgifb_reg_get(XGICR, 0x38); + temp = xgifb_reg_get(vb->P3d4, 0x38); if (temp & 0x10) xgifb_info->TV_type = TVMODE_PAL; else @@ -1519,7 +1524,7 @@ static bool XGIfb_has_VB(struct xgifb_video_info *xgifb_info) { u8 vb_chipid; - vb_chipid = xgifb_reg_get(XGIPART4, 0x00); + vb_chipid = xgifb_reg_get(xgifb_info->dev_info.Part4Port, 0x00); switch (vb_chipid) { case 0x01: xgifb_info->hasVB = HASVB_301; @@ -1539,7 +1544,8 @@ static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info) u8 reg; if (!XGIfb_has_VB(xgifb_info)) { - reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37); + reg = xgifb_reg_get(xgifb_info->dev_info.P3d4, + IND_XGI_SCRATCH_REG_CR37); switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) { case SIS_EXTERNAL_CHIP_LVDS: xgifb_info->hasVB = HASVB_LVDS; @@ -1617,6 +1623,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int ret; struct fb_info *fb_info; struct xgifb_video_info *xgifb_info; + struct vb_device_info *vb; struct xgi_hw_device_info *hw_info; unsigned long video_size_max; @@ -1625,6 +1632,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENOMEM; xgifb_info = fb_info->par; + vb = &xgifb_info->dev_info; hw_info = &xgifb_info->hw_info; xgifb_info->fb_info = fb_info; xgifb_info->chip_id = pdev->device; @@ -1658,10 +1666,11 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) xgifb_info->display2_force = true; } - XGIRegInit(&xgifb_info->dev_info, xgifb_info->vga_base); + XGIRegInit(vb, xgifb_info->vga_base); - xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD); - reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD); + xgifb_reg_set(vb->P3c4, + IND_SIS_PASSWORD, SIS_PASSWORD); + reg1 = xgifb_reg_get(vb->P3c4, IND_SIS_PASSWORD); if (reg1 != 0xa1) { /* I/O error */ dev_err(&pdev->dev, "I/O error\n"); @@ -1671,8 +1680,10 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) switch (xgifb_info->chip_id) { case PCI_DEVICE_ID_XGI_20: - xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN); - CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1); + xgifb_reg_or(vb->P3d4, + Index_CR_GPIO_Reg3, GPIOG_EN); + CR48 = xgifb_reg_get(vb->P3d4, + Index_CR_GPIO_Reg1); if (CR48 & GPIOG_READ) xgifb_info->chip = XG21; else @@ -1703,11 +1714,12 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ - xgifb_reg_or(XGISR, + xgifb_reg_or(vb->P3c4, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); /* Enable 2D accelerator engine */ - xgifb_reg_or(XGISR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); + xgifb_reg_or(vb->P3c4, + IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); hw_info->ulVideoMemorySize = xgifb_info->video_size; @@ -1760,7 +1772,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (xgifb_info->chip == XG27)) { xgifb_info->hasVB = HASVB_NONE; } else if (xgifb_info->chip == XG21) { - CR38 = xgifb_reg_get(XGICR, 0x38); + CR38 = xgifb_reg_get(vb->P3d4, 0x38); if ((CR38 & 0xE0) == 0xC0) xgifb_info->display2 = XGIFB_DISP_LCD; else if ((CR38 & 0xE0) == 0x60) @@ -1777,7 +1789,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) switch (xgifb_info->hasVB) { case HASVB_301: - reg = xgifb_reg_get(XGIPART4, 0x01); + reg = xgifb_reg_get(vb->Part4Port, 0x01); if (reg >= 0xE0) { hw_info->ujVBChipID = VB_CHIP_302LV; dev_info(&pdev->dev, @@ -1794,7 +1806,7 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } break; case HASVB_302: - reg = xgifb_reg_get(XGIPART4, 0x01); + reg = xgifb_reg_get(vb->Part4Port, 0x01); if (reg >= 0xE0) { hw_info->ujVBChipID = VB_CHIP_302LV; dev_info(&pdev->dev, @@ -1806,7 +1818,8 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) "XGI302LV bridge detected (revision 0x%02x)\n", reg); } else if (reg >= 0xB0) { - reg1 = xgifb_reg_get(XGIPART4, 0x23); + reg1 = xgifb_reg_get(vb->Part4Port, + 0x23); hw_info->ujVBChipID = VB_CHIP_302B; @@ -1844,7 +1857,8 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (xgifb_info->display2 == XGIFB_DISP_LCD) { if (!enable_dstn) { - reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL); + reg = xgifb_reg_get(vb->P3d4, + IND_XGI_LCD_PANEL); reg &= 0x0f; hw_info->ulCRT2LCDType = XGI310paneltype[reg]; } @@ -1940,11 +1954,11 @@ static int xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) XGIfb_bpp_to_var(xgifb_info, &fb_info->var); fb_info->var.pixclock = (u32)(1000000000 / XGIfb_mode_rate_to_dclock - (&xgifb_info->dev_info, hw_info, + (vb, hw_info, XGIbios_mode[xgifb_info->mode_idx].mode_no)); - if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, - hw_info, XGIbios_mode[xgifb_info->mode_idx].mode_no, + if (XGIfb_mode_rate_to_ddata(vb, hw_info, + XGIbios_mode[xgifb_info->mode_idx].mode_no, &fb_info->var.left_margin, &fb_info->var.right_margin, &fb_info->var.upper_margin, |