mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 22:54:05 +08:00
HSI fixes and ABI documentation for 3.4
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPlT/gAAoJEB6f1gasKaUuvF4P+QGdTDSKP0Y3dKbddqiA5Y0z iuDad2VBW+e08KnlH8gzu0/iXNYWL1/hD87i/e48586ZwrUKMskij+mAZAs7ThK+ p3yZ+c3isq301YkdAa4giYY8EyAbHC+2+Hn2kOt9H8KAhSCePzk2J31UxqSBgBb9 iqge6+t7MN+d38910xaXL/Eq/zcfczDUqgNECIvMjZglD6WEXEt64Z5OvLdz8HqO QT+CpvuZW/0WPy0dzT0sgp4a9bj6g25RKZeO+6IiuVuxNO4F+byAVojo9cpmvfHd fl6Fa8WmkNlUgdFlhFfZ+2dmGrfwsoHxcH1a2VMv5M8mTI0tUtCy5oYBR1I8yHK9 dYXVK7tpUJvsMYNxTJmqykuMuvwB7zG6mg1uNLLoYHMNAdNA1/QUG432Tox8hC6V rPHbL35Jg4M78SceMmN5JgXY71BY7rZFPHoDxAS2fv94+TTt+Lo+dFZ21riEqQDB 1tjoVVtLXNVoDApCnIuastyRh0irtGz52AGX/FfvMCJeked4+wxU++eBbpvOVbkm jRJLcJwiCFwW+3Zs8bv7f/rXYSU2zfSt0MIkJYpuMeASVr6yAlOUR6qzCpMLJ0Br kRl4+ljcMg1SJ7V0+/lwPWWYGaMapbd6kQtXrlSobBt/rwgo7KmMzZCtla2BYzks pdcd+efPh/LZdDKdFVem =S3mw -----END PGP SIGNATURE----- Merge tag 'hsi_fixes_for_3.4' of git://gitorious.org/kernel-hsi/kernel-hsi Pull HSI fixes and ABI documentation from Carlos Chinea * tag 'hsi_fixes_for_3.4' of git://gitorious.org/kernel-hsi/kernel-hsi: HSI: Add HSI ABI documentation HSI: hsi_char: Remove max_data_size from sysfs HSI: hsi: Rework hsi_event interface HSI: hsi: Remove controllers and ports from the bus HSI: hsi: Fix error path cleanup on client registration HSI: hsi: Rework hsi_controller release
This commit is contained in:
commit
423b40e194
19
Documentation/ABI/testing/sysfs-bus-hsi
Normal file
19
Documentation/ABI/testing/sysfs-bus-hsi
Normal file
@ -0,0 +1,19 @@
|
||||
What: /sys/bus/hsi
|
||||
Date: April 2012
|
||||
KernelVersion: 3.4
|
||||
Contact: Carlos Chinea <carlos.chinea@nokia.com>
|
||||
Description:
|
||||
High Speed Synchronous Serial Interface (HSI) is a
|
||||
serial interface mainly used for connecting application
|
||||
engines (APE) with cellular modem engines (CMT) in cellular
|
||||
handsets.
|
||||
The bus will be populated with devices (hsi_clients) representing
|
||||
the protocols available in the system. Bus drivers implement
|
||||
those protocols.
|
||||
|
||||
What: /sys/bus/hsi/devices/.../modalias
|
||||
Date: April 2012
|
||||
KernelVersion: 3.4
|
||||
Contact: Carlos Chinea <carlos.chinea@nokia.com>
|
||||
Description: Stores the same MODALIAS value emitted by uevent
|
||||
Format: hsi:<hsi_client device name>
|
@ -123,7 +123,7 @@ struct hsc_client_data {
|
||||
static unsigned int hsc_major;
|
||||
/* Maximum buffer size that hsi_char will accept from userspace */
|
||||
static unsigned int max_data_size = 0x1000;
|
||||
module_param(max_data_size, uint, S_IRUSR | S_IWUSR);
|
||||
module_param(max_data_size, uint, 0);
|
||||
MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)");
|
||||
|
||||
static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg,
|
||||
|
@ -21,26 +21,13 @@
|
||||
*/
|
||||
#include <linux/hsi/hsi.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/notifier.h>
|
||||
#include "hsi_core.h"
|
||||
|
||||
static struct device_type hsi_ctrl = {
|
||||
.name = "hsi_controller",
|
||||
};
|
||||
|
||||
static struct device_type hsi_cl = {
|
||||
.name = "hsi_client",
|
||||
};
|
||||
|
||||
static struct device_type hsi_port = {
|
||||
.name = "hsi_port",
|
||||
};
|
||||
|
||||
static ssize_t modalias_show(struct device *dev,
|
||||
struct device_attribute *a __maybe_unused, char *buf)
|
||||
{
|
||||
@ -54,8 +41,7 @@ static struct device_attribute hsi_bus_dev_attrs[] = {
|
||||
|
||||
static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
if (dev->type == &hsi_cl)
|
||||
add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
|
||||
add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -80,12 +66,10 @@ static void hsi_client_release(struct device *dev)
|
||||
static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
|
||||
{
|
||||
struct hsi_client *cl;
|
||||
unsigned long flags;
|
||||
|
||||
cl = kzalloc(sizeof(*cl), GFP_KERNEL);
|
||||
if (!cl)
|
||||
return;
|
||||
cl->device.type = &hsi_cl;
|
||||
cl->tx_cfg = info->tx_cfg;
|
||||
cl->rx_cfg = info->rx_cfg;
|
||||
cl->device.bus = &hsi_bus_type;
|
||||
@ -93,14 +77,11 @@ static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
|
||||
cl->device.release = hsi_client_release;
|
||||
dev_set_name(&cl->device, info->name);
|
||||
cl->device.platform_data = info->platform_data;
|
||||
spin_lock_irqsave(&port->clock, flags);
|
||||
list_add_tail(&cl->link, &port->clients);
|
||||
spin_unlock_irqrestore(&port->clock, flags);
|
||||
if (info->archdata)
|
||||
cl->device.archdata = *info->archdata;
|
||||
if (device_register(&cl->device) < 0) {
|
||||
pr_err("hsi: failed to register client: %s\n", info->name);
|
||||
kfree(cl);
|
||||
put_device(&cl->device);
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,13 +101,6 @@ static void hsi_scan_board_info(struct hsi_controller *hsi)
|
||||
|
||||
static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
|
||||
{
|
||||
struct hsi_client *cl = to_hsi_client(dev);
|
||||
struct hsi_port *port = to_hsi_port(dev->parent);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->clock, flags);
|
||||
list_del(&cl->link);
|
||||
spin_unlock_irqrestore(&port->clock, flags);
|
||||
device_unregister(dev);
|
||||
|
||||
return 0;
|
||||
@ -140,12 +114,17 @@ static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hsi_controller_release(struct device *dev __maybe_unused)
|
||||
static void hsi_controller_release(struct device *dev)
|
||||
{
|
||||
struct hsi_controller *hsi = to_hsi_controller(dev);
|
||||
|
||||
kfree(hsi->port);
|
||||
kfree(hsi);
|
||||
}
|
||||
|
||||
static void hsi_port_release(struct device *dev __maybe_unused)
|
||||
static void hsi_port_release(struct device *dev)
|
||||
{
|
||||
kfree(to_hsi_port(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,20 +149,12 @@ int hsi_register_controller(struct hsi_controller *hsi)
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
hsi->device.type = &hsi_ctrl;
|
||||
hsi->device.bus = &hsi_bus_type;
|
||||
hsi->device.release = hsi_controller_release;
|
||||
err = device_register(&hsi->device);
|
||||
err = device_add(&hsi->device);
|
||||
if (err < 0)
|
||||
return err;
|
||||
for (i = 0; i < hsi->num_ports; i++) {
|
||||
hsi->port[i].device.parent = &hsi->device;
|
||||
hsi->port[i].device.bus = &hsi_bus_type;
|
||||
hsi->port[i].device.release = hsi_port_release;
|
||||
hsi->port[i].device.type = &hsi_port;
|
||||
INIT_LIST_HEAD(&hsi->port[i].clients);
|
||||
spin_lock_init(&hsi->port[i].clock);
|
||||
err = device_register(&hsi->port[i].device);
|
||||
hsi->port[i]->device.parent = &hsi->device;
|
||||
err = device_add(&hsi->port[i]->device);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
@ -192,7 +163,9 @@ int hsi_register_controller(struct hsi_controller *hsi)
|
||||
|
||||
return 0;
|
||||
out:
|
||||
hsi_unregister_controller(hsi);
|
||||
while (i-- > 0)
|
||||
device_del(&hsi->port[i]->device);
|
||||
device_del(&hsi->device);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -222,6 +195,29 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hsi_put_controller - Free an HSI controller
|
||||
*
|
||||
* @hsi: Pointer to the HSI controller to freed
|
||||
*
|
||||
* HSI controller drivers should only use this function if they need
|
||||
* to free their allocated hsi_controller structures before a successful
|
||||
* call to hsi_register_controller. Other use is not allowed.
|
||||
*/
|
||||
void hsi_put_controller(struct hsi_controller *hsi)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!hsi)
|
||||
return;
|
||||
|
||||
for (i = 0; i < hsi->num_ports; i++)
|
||||
if (hsi->port && hsi->port[i])
|
||||
put_device(&hsi->port[i]->device);
|
||||
put_device(&hsi->device);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_put_controller);
|
||||
|
||||
/**
|
||||
* hsi_alloc_controller - Allocate an HSI controller and its ports
|
||||
* @n_ports: Number of ports on the HSI controller
|
||||
@ -232,54 +228,51 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
|
||||
struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
|
||||
{
|
||||
struct hsi_controller *hsi;
|
||||
struct hsi_port *port;
|
||||
struct hsi_port **port;
|
||||
unsigned int i;
|
||||
|
||||
if (!n_ports)
|
||||
return NULL;
|
||||
|
||||
port = kzalloc(sizeof(*port)*n_ports, flags);
|
||||
if (!port)
|
||||
return NULL;
|
||||
hsi = kzalloc(sizeof(*hsi), flags);
|
||||
if (!hsi)
|
||||
goto out;
|
||||
for (i = 0; i < n_ports; i++) {
|
||||
dev_set_name(&port[i].device, "port%d", i);
|
||||
port[i].num = i;
|
||||
port[i].async = hsi_dummy_msg;
|
||||
port[i].setup = hsi_dummy_cl;
|
||||
port[i].flush = hsi_dummy_cl;
|
||||
port[i].start_tx = hsi_dummy_cl;
|
||||
port[i].stop_tx = hsi_dummy_cl;
|
||||
port[i].release = hsi_dummy_cl;
|
||||
mutex_init(&port[i].lock);
|
||||
return NULL;
|
||||
port = kzalloc(sizeof(*port)*n_ports, flags);
|
||||
if (!port) {
|
||||
kfree(hsi);
|
||||
return NULL;
|
||||
}
|
||||
hsi->num_ports = n_ports;
|
||||
hsi->port = port;
|
||||
hsi->device.release = hsi_controller_release;
|
||||
device_initialize(&hsi->device);
|
||||
|
||||
for (i = 0; i < n_ports; i++) {
|
||||
port[i] = kzalloc(sizeof(**port), flags);
|
||||
if (port[i] == NULL)
|
||||
goto out;
|
||||
port[i]->num = i;
|
||||
port[i]->async = hsi_dummy_msg;
|
||||
port[i]->setup = hsi_dummy_cl;
|
||||
port[i]->flush = hsi_dummy_cl;
|
||||
port[i]->start_tx = hsi_dummy_cl;
|
||||
port[i]->stop_tx = hsi_dummy_cl;
|
||||
port[i]->release = hsi_dummy_cl;
|
||||
mutex_init(&port[i]->lock);
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head);
|
||||
dev_set_name(&port[i]->device, "port%d", i);
|
||||
hsi->port[i]->device.release = hsi_port_release;
|
||||
device_initialize(&hsi->port[i]->device);
|
||||
}
|
||||
|
||||
return hsi;
|
||||
out:
|
||||
kfree(port);
|
||||
hsi_put_controller(hsi);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_alloc_controller);
|
||||
|
||||
/**
|
||||
* hsi_free_controller - Free an HSI controller
|
||||
* @hsi: Pointer to HSI controller
|
||||
*/
|
||||
void hsi_free_controller(struct hsi_controller *hsi)
|
||||
{
|
||||
if (!hsi)
|
||||
return;
|
||||
|
||||
kfree(hsi->port);
|
||||
kfree(hsi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_free_controller);
|
||||
|
||||
/**
|
||||
* hsi_free_msg - Free an HSI message
|
||||
* @msg: Pointer to the HSI message
|
||||
@ -414,37 +407,67 @@ void hsi_release_port(struct hsi_client *cl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_release_port);
|
||||
|
||||
static int hsi_start_rx(struct hsi_client *cl, void *data __maybe_unused)
|
||||
static int hsi_event_notifier_call(struct notifier_block *nb,
|
||||
unsigned long event, void *data __maybe_unused)
|
||||
{
|
||||
if (cl->hsi_start_rx)
|
||||
(*cl->hsi_start_rx)(cl);
|
||||
struct hsi_client *cl = container_of(nb, struct hsi_client, nb);
|
||||
|
||||
(*cl->ehandler)(cl, event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hsi_stop_rx(struct hsi_client *cl, void *data __maybe_unused)
|
||||
/**
|
||||
* hsi_register_port_event - Register a client to receive port events
|
||||
* @cl: HSI client that wants to receive port events
|
||||
* @cb: Event handler callback
|
||||
*
|
||||
* Clients should register a callback to be able to receive
|
||||
* events from the ports. Registration should happen after
|
||||
* claiming the port.
|
||||
* The handler can be called in interrupt context.
|
||||
*
|
||||
* Returns -errno on error, or 0 on success.
|
||||
*/
|
||||
int hsi_register_port_event(struct hsi_client *cl,
|
||||
void (*handler)(struct hsi_client *, unsigned long))
|
||||
{
|
||||
if (cl->hsi_stop_rx)
|
||||
(*cl->hsi_stop_rx)(cl);
|
||||
struct hsi_port *port = hsi_get_port(cl);
|
||||
|
||||
return 0;
|
||||
if (!handler || cl->ehandler)
|
||||
return -EINVAL;
|
||||
if (!hsi_port_claimed(cl))
|
||||
return -EACCES;
|
||||
cl->ehandler = handler;
|
||||
cl->nb.notifier_call = hsi_event_notifier_call;
|
||||
|
||||
return atomic_notifier_chain_register(&port->n_head, &cl->nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_register_port_event);
|
||||
|
||||
static int hsi_port_for_each_client(struct hsi_port *port, void *data,
|
||||
int (*fn)(struct hsi_client *cl, void *data))
|
||||
/**
|
||||
* hsi_unregister_port_event - Stop receiving port events for a client
|
||||
* @cl: HSI client that wants to stop receiving port events
|
||||
*
|
||||
* Clients should call this function before releasing their associated
|
||||
* port.
|
||||
*
|
||||
* Returns -errno on error, or 0 on success.
|
||||
*/
|
||||
int hsi_unregister_port_event(struct hsi_client *cl)
|
||||
{
|
||||
struct hsi_client *cl;
|
||||
struct hsi_port *port = hsi_get_port(cl);
|
||||
int err;
|
||||
|
||||
spin_lock(&port->clock);
|
||||
list_for_each_entry(cl, &port->clients, link) {
|
||||
spin_unlock(&port->clock);
|
||||
(*fn)(cl, data);
|
||||
spin_lock(&port->clock);
|
||||
}
|
||||
spin_unlock(&port->clock);
|
||||
WARN_ON(!hsi_port_claimed(cl));
|
||||
|
||||
return 0;
|
||||
err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb);
|
||||
if (!err)
|
||||
cl->ehandler = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
|
||||
|
||||
/**
|
||||
* hsi_event -Notifies clients about port events
|
||||
@ -458,22 +481,12 @@ static int hsi_port_for_each_client(struct hsi_port *port, void *data,
|
||||
* Events:
|
||||
* HSI_EVENT_START_RX - Incoming wake line high
|
||||
* HSI_EVENT_STOP_RX - Incoming wake line down
|
||||
*
|
||||
* Returns -errno on error, or 0 on success.
|
||||
*/
|
||||
void hsi_event(struct hsi_port *port, unsigned int event)
|
||||
int hsi_event(struct hsi_port *port, unsigned long event)
|
||||
{
|
||||
int (*fn)(struct hsi_client *cl, void *data);
|
||||
|
||||
switch (event) {
|
||||
case HSI_EVENT_START_RX:
|
||||
fn = hsi_start_rx;
|
||||
break;
|
||||
case HSI_EVENT_STOP_RX:
|
||||
fn = hsi_stop_rx;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
hsi_port_for_each_client(port, NULL, fn);
|
||||
return atomic_notifier_call_chain(&port->n_head, event, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hsi_event);
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
/* HSI message ttype */
|
||||
#define HSI_MSG_READ 0
|
||||
@ -121,18 +121,18 @@ static inline int hsi_register_board_info(struct hsi_board_info const *info,
|
||||
* @device: Driver model representation of the device
|
||||
* @tx_cfg: HSI TX configuration
|
||||
* @rx_cfg: HSI RX configuration
|
||||
* @hsi_start_rx: Called after incoming wake line goes high
|
||||
* @hsi_stop_rx: Called after incoming wake line goes low
|
||||
* @e_handler: Callback for handling port events (RX Wake High/Low)
|
||||
* @pclaimed: Keeps tracks if the clients claimed its associated HSI port
|
||||
* @nb: Notifier block for port events
|
||||
*/
|
||||
struct hsi_client {
|
||||
struct device device;
|
||||
struct hsi_config tx_cfg;
|
||||
struct hsi_config rx_cfg;
|
||||
void (*hsi_start_rx)(struct hsi_client *cl);
|
||||
void (*hsi_stop_rx)(struct hsi_client *cl);
|
||||
/* private: */
|
||||
void (*ehandler)(struct hsi_client *, unsigned long);
|
||||
unsigned int pclaimed:1;
|
||||
struct list_head link;
|
||||
struct notifier_block nb;
|
||||
};
|
||||
|
||||
#define to_hsi_client(dev) container_of(dev, struct hsi_client, device)
|
||||
@ -147,6 +147,10 @@ static inline void *hsi_client_drvdata(struct hsi_client *cl)
|
||||
return dev_get_drvdata(&cl->device);
|
||||
}
|
||||
|
||||
int hsi_register_port_event(struct hsi_client *cl,
|
||||
void (*handler)(struct hsi_client *, unsigned long));
|
||||
int hsi_unregister_port_event(struct hsi_client *cl);
|
||||
|
||||
/**
|
||||
* struct hsi_client_driver - Driver associated to an HSI client
|
||||
* @driver: Driver model representation of the driver
|
||||
@ -214,8 +218,7 @@ void hsi_free_msg(struct hsi_msg *msg);
|
||||
* @start_tx: Callback to inform that a client wants to TX data
|
||||
* @stop_tx: Callback to inform that a client no longer wishes to TX data
|
||||
* @release: Callback to inform that a client no longer uses the port
|
||||
* @clients: List of hsi_clients using the port.
|
||||
* @clock: Lock to serialize access to the clients list.
|
||||
* @n_head: Notifier chain for signaling port events to the clients.
|
||||
*/
|
||||
struct hsi_port {
|
||||
struct device device;
|
||||
@ -231,14 +234,14 @@ struct hsi_port {
|
||||
int (*start_tx)(struct hsi_client *cl);
|
||||
int (*stop_tx)(struct hsi_client *cl);
|
||||
int (*release)(struct hsi_client *cl);
|
||||
struct list_head clients;
|
||||
spinlock_t clock;
|
||||
/* private */
|
||||
struct atomic_notifier_head n_head;
|
||||
};
|
||||
|
||||
#define to_hsi_port(dev) container_of(dev, struct hsi_port, device)
|
||||
#define hsi_get_port(cl) to_hsi_port((cl)->device.parent)
|
||||
|
||||
void hsi_event(struct hsi_port *port, unsigned int event);
|
||||
int hsi_event(struct hsi_port *port, unsigned long event);
|
||||
int hsi_claim_port(struct hsi_client *cl, unsigned int share);
|
||||
void hsi_release_port(struct hsi_client *cl);
|
||||
|
||||
@ -270,13 +273,13 @@ struct hsi_controller {
|
||||
struct module *owner;
|
||||
unsigned int id;
|
||||
unsigned int num_ports;
|
||||
struct hsi_port *port;
|
||||
struct hsi_port **port;
|
||||
};
|
||||
|
||||
#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device)
|
||||
|
||||
struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags);
|
||||
void hsi_free_controller(struct hsi_controller *hsi);
|
||||
void hsi_put_controller(struct hsi_controller *hsi);
|
||||
int hsi_register_controller(struct hsi_controller *hsi);
|
||||
void hsi_unregister_controller(struct hsi_controller *hsi);
|
||||
|
||||
@ -294,7 +297,7 @@ static inline void *hsi_controller_drvdata(struct hsi_controller *hsi)
|
||||
static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
|
||||
unsigned int num)
|
||||
{
|
||||
return (num < hsi->num_ports) ? &hsi->port[num] : NULL;
|
||||
return (num < hsi->num_ports) ? hsi->port[num] : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user