Loading drivers/hsi/clients/hsi_char.c +6 −6 Original line number Diff line number Diff line Loading @@ -367,7 +367,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc) return -EINVAL; tmp = cl->rx_cfg; cl->rx_cfg.mode = rxc->mode; cl->rx_cfg.channels = rxc->channels; cl->rx_cfg.num_hw_channels = rxc->channels; cl->rx_cfg.flow = rxc->flow; ret = hsi_setup(cl); if (ret < 0) { Loading @@ -383,7 +383,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc) static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc) { rxc->mode = cl->rx_cfg.mode; rxc->channels = cl->rx_cfg.channels; rxc->channels = cl->rx_cfg.num_hw_channels; rxc->flow = cl->rx_cfg.flow; } Loading @@ -402,7 +402,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc) return -EINVAL; tmp = cl->tx_cfg; cl->tx_cfg.mode = txc->mode; cl->tx_cfg.channels = txc->channels; cl->tx_cfg.num_hw_channels = txc->channels; cl->tx_cfg.speed = txc->speed; cl->tx_cfg.arb_mode = txc->arb_mode; ret = hsi_setup(cl); Loading @@ -417,7 +417,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc) static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc) { txc->mode = cl->tx_cfg.mode; txc->channels = cl->tx_cfg.channels; txc->channels = cl->tx_cfg.num_hw_channels; txc->speed = cl->tx_cfg.speed; txc->arb_mode = cl->tx_cfg.arb_mode; } Loading @@ -435,7 +435,7 @@ static ssize_t hsc_read(struct file *file, char __user *buf, size_t len, return -EINVAL; if (len > max_data_size) len = max_data_size; if (channel->ch >= channel->cl->rx_cfg.channels) if (channel->ch >= channel->cl->rx_cfg.num_hw_channels) return -ECHRNG; if (test_and_set_bit(HSC_CH_READ, &channel->flags)) return -EBUSY; Loading Loading @@ -492,7 +492,7 @@ static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len, return -EINVAL; if (len > max_data_size) len = max_data_size; if (channel->ch >= channel->cl->tx_cfg.channels) if (channel->ch >= channel->cl->tx_cfg.num_hw_channels) return -ECHRNG; if (test_and_set_bit(HSC_CH_WRITE, &channel->flags)) return -EBUSY; Loading drivers/hsi/hsi.c +45 −1 Original line number Diff line number Diff line Loading @@ -62,18 +62,36 @@ static struct bus_type hsi_bus_type = { static void hsi_client_release(struct device *dev) { kfree(to_hsi_client(dev)); struct hsi_client *cl = to_hsi_client(dev); kfree(cl->tx_cfg.channels); kfree(cl->rx_cfg.channels); kfree(cl); } static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) { struct hsi_client *cl; size_t size; cl = kzalloc(sizeof(*cl), GFP_KERNEL); if (!cl) return; cl->tx_cfg = info->tx_cfg; if (cl->tx_cfg.channels) { size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels); cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL); memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size); } cl->rx_cfg = info->rx_cfg; if (cl->rx_cfg.channels) { size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels); cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL); memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size); } cl->device.bus = &hsi_bus_type; cl->device.parent = &port->device; cl->device.release = hsi_client_release; Loading Loading @@ -502,6 +520,32 @@ int hsi_event(struct hsi_port *port, unsigned long event) } EXPORT_SYMBOL_GPL(hsi_event); /** * hsi_get_channel_id_by_name - acquire channel id by channel name * @cl: HSI client, which uses the channel * @name: name the channel is known under * * Clients can call this function to get the hsi channel ids similar to * requesting IRQs or GPIOs by name. This function assumes the same * channel configuration is used for RX and TX. * * Returns -errno on error or channel id on success. */ int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name) { int i; if (!cl->rx_cfg.channels) return -ENOENT; for (i = 0; i < cl->rx_cfg.num_channels; i++) if (!strcmp(cl->rx_cfg.channels[i].name, name)) return cl->rx_cfg.channels[i].id; return -ENXIO; } EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name); static int __init hsi_init(void) { return bus_register(&hsi_bus_type); Loading include/linux/hsi/hsi.h +20 −4 Original line number Diff line number Diff line Loading @@ -67,17 +67,31 @@ enum { HSI_EVENT_STOP_RX, }; /** * struct hsi_channel - channel resource used by the hsi clients * @id: Channel number * @name: Channel name */ struct hsi_channel { unsigned int id; const char *name; }; /** * struct hsi_config - Configuration for RX/TX HSI modules * @mode: Bit transmission mode (STREAM or FRAME) * @channels: Number of channels to use [1..16] * @channels: Channel resources used by the client * @num_channels: Number of channel resources * @num_hw_channels: Number of channels the transceiver is configured for [1..16] * @speed: Max bit transmission speed (Kbit/s) * @flow: RX flow type (SYNCHRONIZED or PIPELINE) * @arb_mode: Arbitration mode for TX frame (Round robin, priority) */ struct hsi_config { unsigned int mode; unsigned int channels; struct hsi_channel *channels; unsigned int num_channels; unsigned int num_hw_channels; unsigned int speed; union { unsigned int flow; /* RX only */ Loading Loading @@ -306,6 +320,8 @@ static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, */ int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name); /** * hsi_id - Get HSI controller ID associated to a client * @cl: Pointer to a HSI client Loading Loading
drivers/hsi/clients/hsi_char.c +6 −6 Original line number Diff line number Diff line Loading @@ -367,7 +367,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc) return -EINVAL; tmp = cl->rx_cfg; cl->rx_cfg.mode = rxc->mode; cl->rx_cfg.channels = rxc->channels; cl->rx_cfg.num_hw_channels = rxc->channels; cl->rx_cfg.flow = rxc->flow; ret = hsi_setup(cl); if (ret < 0) { Loading @@ -383,7 +383,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc) static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc) { rxc->mode = cl->rx_cfg.mode; rxc->channels = cl->rx_cfg.channels; rxc->channels = cl->rx_cfg.num_hw_channels; rxc->flow = cl->rx_cfg.flow; } Loading @@ -402,7 +402,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc) return -EINVAL; tmp = cl->tx_cfg; cl->tx_cfg.mode = txc->mode; cl->tx_cfg.channels = txc->channels; cl->tx_cfg.num_hw_channels = txc->channels; cl->tx_cfg.speed = txc->speed; cl->tx_cfg.arb_mode = txc->arb_mode; ret = hsi_setup(cl); Loading @@ -417,7 +417,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc) static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc) { txc->mode = cl->tx_cfg.mode; txc->channels = cl->tx_cfg.channels; txc->channels = cl->tx_cfg.num_hw_channels; txc->speed = cl->tx_cfg.speed; txc->arb_mode = cl->tx_cfg.arb_mode; } Loading @@ -435,7 +435,7 @@ static ssize_t hsc_read(struct file *file, char __user *buf, size_t len, return -EINVAL; if (len > max_data_size) len = max_data_size; if (channel->ch >= channel->cl->rx_cfg.channels) if (channel->ch >= channel->cl->rx_cfg.num_hw_channels) return -ECHRNG; if (test_and_set_bit(HSC_CH_READ, &channel->flags)) return -EBUSY; Loading Loading @@ -492,7 +492,7 @@ static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len, return -EINVAL; if (len > max_data_size) len = max_data_size; if (channel->ch >= channel->cl->tx_cfg.channels) if (channel->ch >= channel->cl->tx_cfg.num_hw_channels) return -ECHRNG; if (test_and_set_bit(HSC_CH_WRITE, &channel->flags)) return -EBUSY; Loading
drivers/hsi/hsi.c +45 −1 Original line number Diff line number Diff line Loading @@ -62,18 +62,36 @@ static struct bus_type hsi_bus_type = { static void hsi_client_release(struct device *dev) { kfree(to_hsi_client(dev)); struct hsi_client *cl = to_hsi_client(dev); kfree(cl->tx_cfg.channels); kfree(cl->rx_cfg.channels); kfree(cl); } static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) { struct hsi_client *cl; size_t size; cl = kzalloc(sizeof(*cl), GFP_KERNEL); if (!cl) return; cl->tx_cfg = info->tx_cfg; if (cl->tx_cfg.channels) { size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels); cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL); memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size); } cl->rx_cfg = info->rx_cfg; if (cl->rx_cfg.channels) { size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels); cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL); memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size); } cl->device.bus = &hsi_bus_type; cl->device.parent = &port->device; cl->device.release = hsi_client_release; Loading Loading @@ -502,6 +520,32 @@ int hsi_event(struct hsi_port *port, unsigned long event) } EXPORT_SYMBOL_GPL(hsi_event); /** * hsi_get_channel_id_by_name - acquire channel id by channel name * @cl: HSI client, which uses the channel * @name: name the channel is known under * * Clients can call this function to get the hsi channel ids similar to * requesting IRQs or GPIOs by name. This function assumes the same * channel configuration is used for RX and TX. * * Returns -errno on error or channel id on success. */ int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name) { int i; if (!cl->rx_cfg.channels) return -ENOENT; for (i = 0; i < cl->rx_cfg.num_channels; i++) if (!strcmp(cl->rx_cfg.channels[i].name, name)) return cl->rx_cfg.channels[i].id; return -ENXIO; } EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name); static int __init hsi_init(void) { return bus_register(&hsi_bus_type); Loading
include/linux/hsi/hsi.h +20 −4 Original line number Diff line number Diff line Loading @@ -67,17 +67,31 @@ enum { HSI_EVENT_STOP_RX, }; /** * struct hsi_channel - channel resource used by the hsi clients * @id: Channel number * @name: Channel name */ struct hsi_channel { unsigned int id; const char *name; }; /** * struct hsi_config - Configuration for RX/TX HSI modules * @mode: Bit transmission mode (STREAM or FRAME) * @channels: Number of channels to use [1..16] * @channels: Channel resources used by the client * @num_channels: Number of channel resources * @num_hw_channels: Number of channels the transceiver is configured for [1..16] * @speed: Max bit transmission speed (Kbit/s) * @flow: RX flow type (SYNCHRONIZED or PIPELINE) * @arb_mode: Arbitration mode for TX frame (Round robin, priority) */ struct hsi_config { unsigned int mode; unsigned int channels; struct hsi_channel *channels; unsigned int num_channels; unsigned int num_hw_channels; unsigned int speed; union { unsigned int flow; /* RX only */ Loading Loading @@ -306,6 +320,8 @@ static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, */ int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name); /** * hsi_id - Get HSI controller ID associated to a client * @cl: Pointer to a HSI client Loading