#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_NETFILTER #include #include #endif #include #include #ifdef CONFIG_RTL_LAYERED_ASIC_DRIVER #include #include #include #else #include #include #endif struct sock *hw_qos_sk = NULL; struct qos_cmd_info_s{ int action; union{ struct{ char port[8]; unsigned int portmask; } port_based_priority, queue_num; struct{ char vlan[8]; unsigned int vlanmask; }vlan_based_priority; struct{ char dscp[64]; unsigned int dscpmask1; unsigned int dscpmask2; }dscp_based_priority; struct{ unsigned char queue[8][6]; unsigned int portmask; unsigned int queuemask; }queue_type; struct{ char priority[8]; unsigned int prioritymask; }sys_priority; struct{ char decision[5]; }pri_decision; struct{ char remark[8][8]; unsigned int portmask; unsigned int prioritymask; }vlan_remark, dscp_remark; struct{ unsigned short apr[8][6]; unsigned char burst[8][6]; unsigned char ppr[8][6]; unsigned int portmask; unsigned int queuemask; }queue_rate; } qos_data; }; #define PORT_BASED_PRIORITY_ASSIGN 1 #define VLAN_BASED_PRIORITY_ASSIGN 2 #define DSCP_BASED_PRIORITY_ASSIGN 3 #define QUEUE_NUMBER 4 #define QUEUE_TYPE_STRICT 5 #define QUEUE_TYPE_WEIGHTED 6 #define PRIORITY_TO_QID 7 #define PRIORITY_DECISION 8 #define VLAN_REMARK 9 #define DSCP_REMARK 10 #define PORT_BASED_PRIORITY_SHOW 11 #define VLAN_BASED_PRIORITY_SHOW 12 #define DSCP_BASED_PRIORITY_SHOW 13 #define QUEUE_NUMBER_SHOW 14 #define QUEUE_TYPE_STRICT_SHOW 15 #define QUEUE_TYPE_WEIGHTED_SHOW 16 #define PRIORITY_TO_QID_SHOW 17 #define PRIORITY_DECISION_SHOW 18 #define VLAN_REMARK_SHOW 19 #define DSCP_REMARK_SHOW 20 #define QUEUE_RATE 21 #define QUEUE_RATE_SHOW 22 #define FLOW_CONTROL_ENABLE 23 #define FLOW_CONTROL_DISABLE 24 #define FLOW_CONTROL_CONFIGURATION_SHOW 25 static inline void port_based_priority_show(void) { int i, ret; enum PRIORITYVALUE priority; printk("PORT_BASED_PRIORITY: \n"); for(i=0; i<9; i++){ ret = rtl8651_getAsicPortBasedPriority(i, &priority); if(ret == SUCCESS) printk(" Priority of port[%d] is %d\n", i, priority); } return; } static inline void vlan_based_priority_show(void) { int i, ret; enum PRIORITYVALUE priority; printk("VLAN_BASED_PRIORITY: \n"); for(i=0; i<9; i++){ ret = rtl8651_getAsicDot1qAbsolutelyPriority(i, &priority); if(ret == SUCCESS) printk(" Priority of vlan_pri[%d] is %d\n", i, priority); } return; } static inline void dscp_based_priority_show(void) { int i, ret; enum PRIORITYVALUE priority; printk("DSCP_BASED_PRIORITY: \n"); for(i=0; i<64; i++){ ret = rtl8651_getAsicDscpPriority(i, &priority); if(ret == SUCCESS) printk(" Priority of dscp[%d] is %d\n", i, priority); } return; } static inline void queue_number_show(void) { int i, ret; enum QUEUENUM qnum; printk("QUEUE_NUMBER: \n"); for(i=0; i<8; i++){ ret = rtl8651_getAsicOutputQueueNumber(i, &qnum); if(ret == SUCCESS) printk(" Queue number of port[%d] is %d\n", i, qnum); } return; } static inline void queue_type_strict_show(void) { int i, ret, j; enum QUEUETYPE queueType; printk("QUEUE_TYPE_STRICT: \n"); for(i=0; i<8; i++){ for(j=0; j<5; j++){ ret = rtl8651_getAsicQueueStrict(i, j, &queueType); if((ret == SUCCESS) && (queueType == 0)) printk(" Port[%d]'s Queue[%d] type is STRICT\n", i, j); } } return; } static inline void queue_type_weighted_show(void) { int i, ret, j, weight; enum QUEUETYPE queueType; printk("QUEUE_TYPE_WEIGHTED: \n"); for(i=0; i<8; i++){ for(j=0; j<5; j++){ ret = rtl8651_getAsicQueueWeight(i, j, &queueType, &weight); if((ret == SUCCESS) && (queueType == 1)) printk(" Port[%d]'s Queue[%d] type is WEIGHTED, and weight is %u\n", i, j, weight); } } return; } static inline void priority_to_qid_show(void) { int i, j, ret; enum QUEUEID qid; printk("PRIORITY_TO_QID: \n"); for(i=1; i<7; i++){ for(j=0; j<8; j++){ ret = rtl8651_getAsicPriorityToQIDMappingTable(i, j, &qid); if(ret == SUCCESS) printk(" For Queue number[%d], priority[%d] is mapping to qid[%d]\n", i, j, qid); } } return; } static inline void priority_decision_show(void) { unsigned int portpri, dot1qpri, dscppri, aclpri, natpri; int ret; printk("PRIORITY_DECISION: \n"); ret = rtl8651_getAsicPriorityDecision(&portpri, &dot1qpri, &dscppri, &aclpri, &natpri); if(ret == SUCCESS){ printk(" Port based decision priority is %d\n", portpri); printk(" Vlan based decision priority is %d\n", dot1qpri); printk(" Dscp based decision priority is %d\n", dscppri); printk(" Acl based decision priority is %d\n", aclpri); printk(" Nat based decision priority is %d\n", natpri); } return; } static inline void vlan_remark_show(void) { int i, j, ret, remark; printk("VLAN_REMARK: \n"); for(i=0; i<8; i++){ for(j=0; j<8; j++){ ret = rtl8651_getAsicVlanRemark(i, j, &remark); if(ret == SUCCESS) printk(" Port[%d]'s sys_pri[%d] is remarked as vlan_pri[%d]\n", i, j, remark); } } return; } static inline void dscp_remark_show(void) { int i, j, ret, remark; printk("DSCP_REMARK: \n"); for(i=0; i<8; i++){ for(j=0; j<8; j++){ ret = rtl8651_getAsicDscpRemark(i, j, &remark); if(ret == SUCCESS) printk(" Port[%d]'s sys_pri[%d] is remarked as dscp[%d]\n", i, j, remark); } } return; } static inline void queue_rate_show(void) { int i, j, ret; unsigned int ppr, apr, burst; printk("QUEUE_RATE: \n"); for(i=0; i<8; i++){ for(j=0; j<6; j++){ ret = rtl8651_getAsicQueueRate(i, j, &ppr, &burst, &apr); if(ret == SUCCESS) printk(" Port[%d] queue[%d]'s ppr is %d, burst is %d, apr is %d\n", i, j, ppr, burst, apr); } } return; } static inline void flow_control_config_show(void) { unsigned int flow_control_enable = 0; int ret; ret = rtl8651_getAsicQueueFlowControlConfigureRegister(0, 0, &flow_control_enable); if(ret == SUCCESS){ if(flow_control_enable == 1){ printk(" QOS Flow Control is enabled!\n"); }else{ printk(" QOS Flow Control is disabled!\n"); } } } void hw_qos_netlink_receive (struct sk_buff *__skb) { unsigned int i, j; enum QUEUENUM queue_num; int ret; int pid = 0; struct qos_cmd_info_s send_data,recv_data; pid=rtk_nlrecvmsg(__skb, sizeof(struct qos_cmd_info_s), &recv_data); if(pid<0) return; switch(recv_data.action) { case PORT_BASED_PRIORITY_ASSIGN: for(i=0; i<8; i++){ if((1<=32) && ((1<<(i-32)) & recv_data.qos_data.dscp_based_priority.dscpmask2))){ ret = rtl8651_setAsicDscpPriority(i, recv_data.qos_data.dscp_based_priority.dscp[i]); if(ret == FAILED){ printk("Dscp based priority set to DSCPCR register failed\n "); } } } send_data.action = DSCP_BASED_PRIORITY_ASSIGN; break; case QUEUE_NUMBER: for(i=0; i<8; i++){ if((1< 0) && (recv_data.qos_data.queue_type.queue[i][j] != 255)){ ret = rtl8651_setAsicQueueWeight(i, j, WFQ_PRIO, recv_data.qos_data.queue_type.queue[i][j]); if(ret == FAILED){ printk("Queue type WEIGHTED set to WFQWCR0P0 register failed\n "); } } } } } } send_data.action = QUEUE_TYPE_WEIGHTED; break; case PRIORITY_TO_QID: for(i=0; i<8; i++){ ret = rtl8651_getAsicOutputQueueNumber(i, &queue_num); if(ret == SUCCESS){ for(j=0; j<8; j++) { if((1<