MC_GETPROP(9E) | Driver Entry Points | MC_GETPROP(9E) |
mc_getprop
—
#include <sys/mac_provider.h>
int
prefix_m_getprop
(void *driver,
const char *pr_name, mac_prop_id_t
pr_num, uint_t pr_valsize, void
*pr_val);
mc_getprop
() entry point is used to obtain the value
of a given device's property and place it into pr_val.
When the mc_getprop
() entry point is
called, the driver needs to first identify the property. The set of possible
properties and their meaning is listed in the
PROPERTIES section of
mac(9E). It should identify the property based on the
value of pr_num. Most drivers will use a
switch statement and for any property that it supports it
should then check if the value in pr_valsize is
sufficient for the property, comparing it to the minimum size listed for the
property in mac(9E). If it is not, then it should return
an error. Otherwise, it should copy the property's value into
pr_val. When an unknown or unsupported property is
encountered, generally the default case of the switch
statement, the device driver should return an error.
The special property MAC_PROP_PRIVATE indicates that this is a device driver specific private property. The device driver must then look at the value of the pr_name argument and use strcmp(9F) on it, comparing it to each of its private (bounded-size) properties to identify which one it is.
At this time, private properties are limited to being string based properties. If other types of property values are used, they will not be rendered correctly by dladm(1M).
The device driver can access its device soft state by casting the device pointer to the appropriate structure. As this may be called while other operations are ongoing, the device driver should employ the appropriate locking while reading the properties.
mc_getprop
() function is generally called from
kernel context.
mc_getprop
() entry point.
#include <sys/mac_provider.h> /* * Note, this example merely shows the structure of this function. * Different devices will manage their state in different ways. Like other * examples, this assumes that the device has state in a structure called * example_t and that there is a lock which keeps track of that state. */ static char *example_priv_props[] = { "_rx_intr_throttle", "_tx_intr_throttle", NULL }; static int example_m_getprop_private(example_t *ep, const char *pr_name, uint_t pr_valsize, void *pr_val) { uint32_t val; ASSERT(MUTEX_HELD(&ep->ep_lock)); if (strcmp(pr_name, example_priv_props[0] == 0) { val = ep->ep_rx_itr; } else if (strcmp(pr_name, example_priv_props[1] == 0) { val = ep->ep_tx_itr; } else { return (ENOTSUP); } /* * Due to issues in the GLDv3, these must be returned as string * properties. */ if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize) return (EOVERFLOW); return (0); } static int example_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, uint_t pr_valsize, void *pr_val) { int ret = 0; uint64_t speed; example_t *ep = arg; mutex_enter(&ep->ep_lock); /* * This only handles a subset of the properties that exist on the * system. A proper driver will need to handle more. See mac(9E) for a * full property list. */ switch (pr_num) { case MAC_PROP_DUPLEX: if (pr_valsize < sizeof (link_duplex_t)) { ret = EOVERFLOW; break; } bcopy(ep->ep_link_duplex, pr_val, sizeof (link_duplex_t)); case MAC_PROP_SPEED: if (pr_valsize < sizeof (uint64_t)) { ret = EOVERFLOW; break; } /* * The link speed is stored in Mbits/s in this driver and is * expected in bits/s. */ speed = ep->ep_link_speed * 1000000ULL; bcopy(&speed, pr_val, sizeof (speed)); break; case MAC_PROP_MTU: if (pr_valsize < sizeof (uint32_t)) { ret = EOVERFLOW; break; } bcopy(&ep->ep_mtu, pr_val, sizeof (speed)); break; case MAC_PROP_PRIVATE: ret = example_m_getprop_private(ep, pr_name, pr_valsize, pr_val); break; default: ret = ENOTSUP; break; } mutex_exit(&ep->ep_lock); return (ret); }
February 15, 2020 | illumos |