diff options
| author | Cathy Zhou <Cathy.Zhou@Sun.COM> | 2009-03-17 20:14:50 -0700 |
|---|---|---|
| committer | Cathy Zhou <Cathy.Zhou@Sun.COM> | 2009-03-17 20:14:50 -0700 |
| commit | 5d460eafffba936e81c4dd5ebe0f59b238f09121 (patch) | |
| tree | ec942dd0b37946b807039b9f42e69a8f54c30b7d /usr/src/uts/common/sys | |
| parent | f91909144addd198e09d1842e5354bfa62d96691 (diff) | |
| download | illumos-gate-5d460eafffba936e81c4dd5ebe0f59b238f09121.tar.gz | |
PSARC/2008/242 Data Fast-Path for Softmac
6649224 fast-path needed to improve legacy network interface performance after UV
6649898 the smac_lock and smac_mutex fields in softmac_t should be given a more descriptive name
6799767 DLD capability is not correctly updated if it is renegotiated
Diffstat (limited to 'usr/src/uts/common/sys')
| -rw-r--r-- | usr/src/uts/common/sys/dld.h | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/dld_impl.h | 8 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/dlpi.h | 19 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/dls_impl.h | 2 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/mac.h | 18 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/mac_client_priv.h | 1 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/mac_impl.h | 5 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/mac_provider.h | 18 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/softmac_impl.h | 244 |
9 files changed, 267 insertions, 51 deletions
diff --git a/usr/src/uts/common/sys/dld.h b/usr/src/uts/common/sys/dld.h index 3094fa1a09..5fede27bb2 100644 --- a/usr/src/uts/common/sys/dld.h +++ b/usr/src/uts/common/sys/dld.h @@ -411,6 +411,9 @@ int dld_open(queue_t *, dev_t *, int, int, cred_t *); int dld_close(queue_t *); void dld_wput(queue_t *, mblk_t *); void dld_wsrv(queue_t *); +int dld_str_open(queue_t *, dev_t *, void *); +int dld_str_close(queue_t *); +void *dld_str_private(queue_t *); void dld_init_ops(struct dev_ops *, const char *); void dld_fini_ops(struct dev_ops *); int dld_autopush(dev_t *, struct dlautopush *); diff --git a/usr/src/uts/common/sys/dld_impl.h b/usr/src/uts/common/sys/dld_impl.h index 79aa82ba75..68caa4f459 100644 --- a/usr/src/uts/common/sys/dld_impl.h +++ b/usr/src/uts/common/sys/dld_impl.h @@ -207,13 +207,19 @@ struct dld_str_s { /* Protected by */ dls_multicst_addr_t *ds_dmap; /* ds_rw_lock */ dls_rx_t ds_rx; /* ds_lock */ void *ds_rx_arg; /* ds_lock */ - boolean_t ds_active; /* SL */ + uint_t ds_nactive; /* SL */ dld_str_t *ds_next; /* SL */ dls_head_t *ds_head; dls_dl_handle_t ds_ddh; list_node_t ds_tqlist; + + /* + * driver private data set by the driver when calling dld_str_open(). + */ + void *ds_private; }; + #define DLD_DATATHR_INC(dsp) { \ ASSERT(MUTEX_HELD(&(dsp)->ds_lock)); \ dsp->ds_datathr_cnt++; \ diff --git a/usr/src/uts/common/sys/dlpi.h b/usr/src/uts/common/sys/dlpi.h index e67f604630..11293ac6d3 100644 --- a/usr/src/uts/common/sys/dlpi.h +++ b/usr/src/uts/common/sys/dlpi.h @@ -104,6 +104,7 @@ typedef struct dl_ipnetinfo { #define DL_CONTROL_ACK 0x113 /* Device specific control ack */ #define DL_PASSIVE_REQ 0x114 /* Allow access to aggregated link */ #define DL_INTR_MODE_REQ 0x115 /* Request Rx processing in INTR mode */ +#define DL_NOTIFY_CONF 0x116 /* Notification from upstream */ /* * Primitives used for Connectionless Service @@ -385,7 +386,7 @@ typedef struct dl_ipnetinfo { #define DL_PROMISC_MULTI 0x03 /* promiscuous mode for multicast */ /* - * DLPI notification codes for DL_NOTIFY primitives. + * DLPI notification codes for DL_NOTIFY_REQ primitives. * Bit-wise distinct since DL_NOTIFY_REQ and DL_NOTIFY_ACK carry multiple * notification codes. */ @@ -400,6 +401,12 @@ typedef struct dl_ipnetinfo { #define DL_NOTE_SPEED 0x0100 /* Approximate link speed */ #define DL_NOTE_FASTPATH_FLUSH 0x0200 /* Fast Path info changes */ #define DL_NOTE_CAPAB_RENEG 0x0400 /* Initiate capability renegotiation */ +#define DL_NOTE_REPLUMB 0x0800 /* Inform the link to replumb */ + +/* + * DLPI notification codes for DL_NOTIFY_CONF primitives. + */ +#define DL_NOTE_REPLUMB_DONE 0x0001 /* Indicate replumb has done */ /* * DLPI Quality Of Service definition for use in QOS structure definitions. @@ -1017,6 +1024,14 @@ typedef struct { } dl_notify_ind_t; /* + * DL_NOTIFY_CONF, M_PROTO type + */ +typedef struct { + t_uscalar_t dl_primitive; /* set to DL_NOTIFY_CONF */ + uint32_t dl_notification; /* Which notification? */ +} dl_notify_conf_t; + +/* * DL_AGGR_REQ, M_PROTO type */ typedef struct { @@ -1507,6 +1522,7 @@ union DL_primitives { dl_notify_req_t notify_req; dl_notify_ack_t notify_ack; dl_notify_ind_t notify_ind; + dl_notify_conf_t notify_conf; dl_aggr_req_t aggr_req; dl_aggr_ind_t aggr_ind; dl_unaggr_req_t unaggr_req; @@ -1574,6 +1590,7 @@ union DL_primitives { #define DL_NOTIFY_REQ_SIZE sizeof (dl_notify_req_t) #define DL_NOTIFY_ACK_SIZE sizeof (dl_notify_ack_t) #define DL_NOTIFY_IND_SIZE sizeof (dl_notify_ind_t) +#define DL_NOTIFY_CONF_SIZE sizeof (dl_notify_conf_t) #define DL_AGGR_REQ_SIZE sizeof (dl_aggr_req_t) #define DL_AGGR_IND_SIZE sizeof (dl_aggr_ind_t) #define DL_UNAGGR_REQ_SIZE sizeof (dl_unaggr_req_t) diff --git a/usr/src/uts/common/sys/dls_impl.h b/usr/src/uts/common/sys/dls_impl.h index 33162a4d5c..dafd451954 100644 --- a/usr/src/uts/common/sys/dls_impl.h +++ b/usr/src/uts/common/sys/dls_impl.h @@ -119,7 +119,7 @@ extern void dls_rx_promisc(void *, mac_resource_handle_t, mblk_t *, extern void dls_rx_vlan_promisc(void *, mac_resource_handle_t, mblk_t *, boolean_t); extern int dls_active_set(dld_str_t *); -extern void dls_active_clear(dld_str_t *); +extern void dls_active_clear(dld_str_t *, boolean_t); extern void dls_mgmt_init(void); extern void dls_mgmt_fini(void); diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h index 1756644b6c..2cfe7443e5 100644 --- a/usr/src/uts/common/sys/mac.h +++ b/usr/src/uts/common/sys/mac.h @@ -260,20 +260,6 @@ typedef struct mac_info_s { } mac_info_t; /* - * Information for legacy devices. - */ -typedef struct mac_capab_legacy_s { - /* - * Notifications that the legacy device does not support. - */ - uint32_t ml_unsup_note; - /* - * dev_t of the legacy device; can be held to force attach. - */ - dev_t ml_dev; -} mac_capab_legacy_t; - -/* * When VNICs are created on top of the NIC, there are two levels * of MAC layer, a lower MAC, which is the MAC layer at the level of the * physical NIC, and an upper MAC, which is the MAC layer at the level @@ -569,13 +555,15 @@ extern void mac_margin_get(mac_handle_t, uint32_t *); extern int mac_margin_remove(mac_handle_t, uint32_t); extern int mac_margin_add(mac_handle_t, uint32_t *, boolean_t); +extern int mac_fastpath_disable(mac_handle_t); +extern void mac_fastpath_enable(mac_handle_t); extern mactype_register_t *mactype_alloc(uint_t); extern void mactype_free(mactype_register_t *); extern int mactype_register(mactype_register_t *); extern int mactype_unregister(const char *); -extern void mac_start_logusage(mac_logtype_t, uint_t); +extern int mac_start_logusage(mac_logtype_t, uint_t); extern void mac_stop_logusage(mac_logtype_t); extern mac_handle_t mac_get_lower_mac_handle(mac_handle_t); diff --git a/usr/src/uts/common/sys/mac_client_priv.h b/usr/src/uts/common/sys/mac_client_priv.h index c1b999bb31..20e3afa82a 100644 --- a/usr/src/uts/common/sys/mac_client_priv.h +++ b/usr/src/uts/common/sys/mac_client_priv.h @@ -63,6 +63,7 @@ extern void mac_ioctl(mac_handle_t, queue_t *, mblk_t *); extern link_state_t mac_link_get(mac_handle_t); extern void mac_resource_set(mac_client_handle_t, mac_resource_add_t, void *); extern dev_info_t *mac_devinfo_get(mac_handle_t); +extern void *mac_driver(mac_handle_t); extern boolean_t mac_capab_get(mac_handle_t, mac_capab_t, void *); extern boolean_t mac_sap_verify(mac_handle_t, uint32_t, uint32_t *); extern mblk_t *mac_header(mac_handle_t, const uint8_t *, uint32_t, mblk_t *, diff --git a/usr/src/uts/common/sys/mac_impl.h b/usr/src/uts/common/sys/mac_impl.h index ee5557b113..9a02c07b54 100644 --- a/usr/src/uts/common/sys/mac_impl.h +++ b/usr/src/uts/common/sys/mac_impl.h @@ -457,9 +457,10 @@ struct mac_impl_s { mac_resource_props_t mi_resource_props; /* SL */ minor_t mi_minor; /* WO */ - dev_t mi_phy_dev; /* WO */ uint32_t mi_oref; /* SL */ - uint32_t mi_unsup_note; /* WO */ + mac_capab_legacy_t mi_capab_legacy; /* WO */ + dev_t mi_phy_dev; /* WO */ + /* * List of margin value requests added by mac clients. This list is * sorted: the first one has the greatest value. diff --git a/usr/src/uts/common/sys/mac_provider.h b/usr/src/uts/common/sys/mac_provider.h index 5522a6c884..6713912b63 100644 --- a/usr/src/uts/common/sys/mac_provider.h +++ b/usr/src/uts/common/sys/mac_provider.h @@ -145,6 +145,24 @@ typedef struct mac_capab_multifactaddr_s { } mac_capab_multifactaddr_t; /* + * Info and callbacks of legacy devices. + */ +typedef struct mac_capab_legacy_s { + /* + * Notifications that the legacy device does not support. + */ + uint32_t ml_unsup_note; + /* + * dev_t of the legacy device; can be held to force attach. + */ + dev_t ml_dev; + boolean_t (*ml_active_set)(void *); + void (*ml_active_clear)(void *); + int (*ml_fastpath_disable)(void *); + void (*ml_fastpath_enable)(void *); +} mac_capab_legacy_t; + +/* * MAC driver entry point types. */ typedef int (*mac_getstat_t)(void *, uint_t, uint64_t *); diff --git a/usr/src/uts/common/sys/softmac_impl.h b/usr/src/uts/common/sys/softmac_impl.h index 9cdb49de31..83caa23c82 100644 --- a/usr/src/uts/common/sys/softmac_impl.h +++ b/usr/src/uts/common/sys/softmac_impl.h @@ -44,9 +44,20 @@ extern "C" { #endif +typedef void (*softmac_rx_t)(void *, mac_resource_handle_t, mblk_t *, + mac_header_info_t *); + +typedef struct softmac_lower_rxinfo_s { + softmac_rx_t slr_rx; + void *slr_arg; +} softmac_lower_rxinfo_t; + typedef struct softmac_lower_s { + ldi_handle_t sl_lh; struct softmac *sl_softmac; queue_t *sl_wq; + struct softmac_upper_s *sl_sup; + softmac_lower_rxinfo_t *sl_rxinfo; /* * sl_ctl_inprogress is used to serialize the control path. It will @@ -68,8 +79,6 @@ typedef struct softmac_lower_s { t_uscalar_t sl_pending_prim; boolean_t sl_pending_ioctl; mblk_t *sl_ack_mp; - - ldi_handle_t sl_lh; } softmac_lower_t; typedef enum { @@ -110,55 +119,53 @@ typedef struct softmac_dev_s { * node, the other minor node can still be used to register the mac. * (Specifically, an incorrect xxx_getinfo() implementation will cause style-2 * minor node mac registration to fail.) + * + * Locking description: + * WO: write once, valid the life time. */ typedef struct softmac { - /* - * The following fields will be set when the softmac is created and - * will not change. No lock is required. - */ - char smac_devname[MAXNAMELEN]; - major_t smac_umajor; - int smac_uppa; - uint32_t smac_cnt; /* # of minor nodes for this device */ + char smac_devname[MAXNAMELEN]; /* WO */ + major_t smac_umajor; /* WO */ + int smac_uppa; /* WO */ + uint32_t smac_cnt; /* WO, # of minor nodes */ + kmutex_t smac_mutex; + kcondvar_t smac_cv; + softmac_state_t smac_state; /* smac_mutex */ /* - * The following fields are protected by smac_mutex. - * * The smac_hold_cnt field increases when softmac_hold_device() is * called to force the dls_vlan_t of the device to be created. The * device pre-detach fails if this counter is not 0. */ - softmac_state_t smac_state; - uint32_t smac_hold_cnt; - kmutex_t smac_mutex; - kcondvar_t smac_cv; - uint32_t smac_flags; - int smac_attacherr; + uint32_t smac_hold_cnt; /* smac_mutex */ + uint32_t smac_flags; /* smac_mutex */ + int smac_attacherr; /* smac_mutex */ mac_handle_t smac_mh; - softmac_dev_t *smac_softmac[2]; + softmac_dev_t *smac_softmac[2]; /* smac_mutex */ + /* * Number of minor nodes whose post-attach routine has succeeded. * This should be the same as the numbers of softmac_dev_t. * Note that it does not imply SOFTMAC_ATTACH_DONE as the taskq might * be still ongoing. */ - uint32_t smac_attachok_cnt; + uint32_t smac_attachok_cnt; /* smac_mutex */ /* * Number of softmac_dev_t left when pre-detach fails. This is used * to indicate whether postattach is called because of a failed * pre-detach. */ - uint32_t smac_attached_left; + uint32_t smac_attached_left; /* smac_mutex */ /* * Thread handles the DL_NOTIFY_IND message from the lower stream. */ - kthread_t *smac_notify_thread; + kthread_t *smac_notify_thread; /* smac_mutex */ /* * Head and tail of the DL_NOTIFY_IND messsages. */ - mblk_t *smac_notify_head; - mblk_t *smac_notify_tail; + mblk_t *smac_notify_head; /* smac_mutex */ + mblk_t *smac_notify_tail; /* smac_mutex */ /* * The remaining fields are used to register the MAC for a legacy @@ -193,10 +200,34 @@ typedef struct softmac { dl_capab_mdt_t smac_mdt_capab; boolean_t smac_mdt; - /* Following fields protected by the mac perimeter */ - softmac_lower_state_t smac_lower_state; - /* Lower stream structure */ + /* + * Lower stream structure, accessed by the MAC provider API. The GLDv3 + * framework assures it's validity. + */ softmac_lower_t *smac_lower; + + kmutex_t smac_active_mutex; + /* + * Set by xxx_active_set() when aggregation is created. + */ + boolean_t smac_active; /* smac_active_mutex */ + /* + * Numbers of the bounded streams in the fast-path mode. + */ + uint32_t smac_nactive; /* smac_active_mutex */ + + kmutex_t smac_fp_mutex; + kcondvar_t smac_fp_cv; + /* + * numbers of clients that request to disable fastpath. + */ + uint32_t smac_fp_disable_clients; /* smac_fp_mutex */ + boolean_t smac_fastpath_admin_disabled; /* smac_fp_mutex */ + + /* + * stream list over this softmac. + */ + list_t smac_sup_list; /* smac_fp_mutex */ } softmac_t; typedef struct smac_ioc_start_s { @@ -206,20 +237,157 @@ typedef struct smac_ioc_start_s { #define SMAC_IOC ('S' << 24 | 'M' << 16 | 'C' << 8) #define SMAC_IOC_START (SMAC_IOC | 0x01) +/* + * The su_mode of a non-IP/ARP stream is UNKNOWN, and the su_mode of an IP/ARP + * stream is either SLOWPATH or FASTPATH. + */ +#define SOFTMAC_UNKNOWN 0x00 +#define SOFTMAC_SLOWPATH 0x01 +#define SOFTMAC_FASTPATH 0x02 + +typedef struct softmac_switch_req_s { + list_node_t ssq_req_list_node; + uint32_t ssq_expected_mode; +} softmac_switch_req_t; + +#define DATAPATH_MODE(softmac) \ + ((((softmac)->smac_fp_disable_clients != 0) || \ + (softmac)->smac_fastpath_admin_disabled) ? SOFTMAC_SLOWPATH : \ + SOFTMAC_FASTPATH) + + +/* + * Locking description: + * + * WO: Set once and valid for life; + * SL: Serialized by the control path (softmac_wput_nondata_task()) + */ +typedef struct softmac_upper_s { + softmac_t *su_softmac; /* WO */ + queue_t *su_rq; /* WO */ + queue_t *su_wq; /* WO */ + + /* + * List of upper streams that has pending DLPI messages to be processed. + */ + list_node_t su_taskq_list_node; /* softmac_taskq_lock */ + + /* + * non-NULL for IP/ARP streams in the fast-path mode + */ + softmac_lower_t *su_slp; /* SL & su_mutex */ + + /* + * List of all IP/ARP upperstreams on the same softmac (including + * the ones in both data-path modes). + */ + list_node_t su_list_node; /* smac_fp_mutex */ + + /* + * List of datapath switch requests. + */ + list_t su_req_list; /* smac_fp_mutex */ + + /* + * Place holder of RX callbacks used to handles data messages comes + * from the dedicated-lower-stream associated with the IP/ARP stream. + * Another RX callback is softmac_drop_rxinfo, which is a global + * variable. + */ + softmac_lower_rxinfo_t su_rxinfo; /* WO */ + softmac_lower_rxinfo_t su_direct_rxinfo; /* WO */ + + /* + * Used to serialize the DLPI operation and fastpath<->slowpath + * switching over operation. + */ + kmutex_t su_disp_mutex; + kcondvar_t su_disp_cv; + mblk_t *su_pending_head; /* su_disp_mutex */ + mblk_t *su_pending_tail; /* su_disp_mutex */ + boolean_t su_dlpi_pending; /* su_disp_mutex */ + boolean_t su_closing; /* su_disp_mutex */ + + uint32_t su_bound : 1, /* SL */ + su_active : 1, /* SL */ + su_direct : 1; /* SL */ + + /* + * Used for fastpath data path. + */ + kmutex_t su_mutex; + kcondvar_t su_cv; + mblk_t *su_tx_flow_mp; /* su_mutex */ + boolean_t su_tx_busy; /* su_mutex */ + /* + * Number of softmac_srv() operation in fastpath processing. + */ + uint32_t su_tx_inprocess; /* su_mutex */ + /* + * SOFTMAC_SLOWPATH or SOFTMAC_FASTPATH + */ + uint32_t su_mode; /* SL & su_mutex */ + + /* + * Whether this stream is already scheduled in softmac_taskq_list. + */ + boolean_t su_taskq_scheduled; /* softmac_taskq_lock */ +} softmac_upper_t; + +#define SOFTMAC_EQ_PENDING(sup, mp) { \ + if ((sup)->su_pending_head == NULL) { \ + (sup)->su_pending_head = (sup)->su_pending_tail = (mp); \ + } else { \ + (sup)->su_pending_tail->b_next = (mp); \ + (sup)->su_pending_tail = (mp); \ + } \ +} + +#define SOFTMAC_DQ_PENDING(sup, mpp) { \ + if ((sup)->su_pending_head == NULL) { \ + *(mpp) = NULL; \ + } else { \ + *(mpp) = (sup)->su_pending_head; \ + if (((sup)->su_pending_head = (*(mpp))->b_next) == NULL)\ + (sup)->su_pending_tail = NULL; \ + (*(mpp))->b_next = NULL; \ + } \ +} + +/* + * A macro to check whether the write-queue of the lower stream is full + * and packets need to be enqueued. + * + * Because softmac is pushed right above the underlying device and + * _I_INSERT/_I_REMOVE is not processed in the lower stream, it is + * safe to directly access the q_next pointer. + */ +#define SOFTMAC_CANPUTNEXT(q) \ + (!((q)->q_next->q_nfsrv->q_flag & QFULL) || canput((q)->q_next)) + + extern dev_info_t *softmac_dip; #define SOFTMAC_DEV_NAME "softmac" extern int softmac_send_bind_req(softmac_lower_t *, uint_t); +extern int softmac_send_unbind_req(softmac_lower_t *); extern int softmac_send_notify_req(softmac_lower_t *, uint32_t); extern int softmac_send_promisc_req(softmac_lower_t *, t_uscalar_t, boolean_t); -extern void softmac_init(void); -extern void softmac_fini(void); -extern boolean_t softmac_busy(void); +extern void softmac_init(); +extern void softmac_fini(); +extern void softmac_fp_init(); +extern void softmac_fp_fini(); +extern boolean_t softmac_busy(); extern int softmac_fill_capab(ldi_handle_t, softmac_t *); extern int softmac_capab_enable(softmac_lower_t *); -extern void softmac_rput_process_notdata(queue_t *, mblk_t *); +extern void softmac_rput_process_notdata(queue_t *, softmac_upper_t *, + mblk_t *); extern void softmac_rput_process_data(softmac_lower_t *, mblk_t *); +extern int softmac_output(softmac_lower_t *, mblk_t *, t_uscalar_t, + t_uscalar_t, mblk_t **); +extern int softmac_mexchange_error_ack(mblk_t **, t_uscalar_t, + t_uscalar_t, t_uscalar_t); extern int softmac_m_promisc(void *, boolean_t); extern int softmac_m_multicst(void *, boolean_t, const uint8_t *); @@ -231,6 +399,20 @@ extern int softmac_proto_tx(softmac_lower_t *, mblk_t *, mblk_t **); extern void softmac_ioctl_tx(softmac_lower_t *, mblk_t *, mblk_t **); extern void softmac_notify_thread(void *); +extern int softmac_hold(dev_t, softmac_t **); +extern void softmac_rele(softmac_t *); +extern int softmac_lower_setup(softmac_t *, softmac_upper_t *, + softmac_lower_t **); +extern boolean_t softmac_active_set(void *); +extern void softmac_active_clear(void *); +extern int softmac_fastpath_disable(void *); +extern void softmac_fastpath_enable(void *); +extern int softmac_datapath_switch(softmac_t *, boolean_t, boolean_t); + +extern void softmac_wput_data(softmac_upper_t *, mblk_t *); +extern void softmac_wput_nondata(softmac_upper_t *, mblk_t *); +extern void softmac_upperstream_close(softmac_upper_t *); + #ifdef __cplusplus } #endif |
