Changeset 21941


Ignore:
Timestamp:
2010-06-26T21:54:22+02:00 (7 years ago)
Author:
juhosg
Message:

backfire: generic: rtl8366: update vlan handling code for rtl8366s (backport of r21922)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/backfire/target/linux/generic-2.6/files/drivers/net/phy/rtl8366s.c

    r21939 r21941  
    631631} 
    632632 
    633 static int rtl8366s_get_port_vlan_index(struct rtl8366_smi *smi, int port, 
    634                                        int *val) 
     633static int rtl8366s_get_mc_index(struct rtl8366_smi *smi, int port, int *val) 
    635634{ 
    636635        u32 data; 
     
    649648 
    650649        return 0; 
    651  
    652 } 
    653  
    654 static int rtl8366s_get_vlan_port_pvid(struct rtl8366_smi *smi, int port, 
    655                                        int *val) 
    656 { 
    657         struct rtl8366_vlan_mc vlanmc; 
    658         int err; 
    659         int index; 
    660  
    661         err = rtl8366s_get_port_vlan_index(smi, port, &index); 
    662         if (err) 
    663                 return err; 
    664  
    665         err = rtl8366s_get_vlan_mc(smi, index, &vlanmc); 
    666         if (err) 
    667                 return err; 
    668  
    669         *val = vlanmc.vid; 
    670         return 0; 
    671 } 
    672  
    673 static int rtl8366s_set_port_vlan_index(struct rtl8366_smi *smi, int port, 
    674                                         int index) 
     650} 
     651 
     652static int rtl8366s_set_mc_index(struct rtl8366_smi *smi, int port, int index) 
    675653{ 
    676654        if (port >= RTL8366_NUM_PORTS || index >= RTL8366_NUM_VLANS) 
     
    684662} 
    685663 
    686 static int rtl8366s_set_vlan_port_pvid(struct rtl8366_smi *smi, int port, int val) 
    687 { 
     664static int rtl8366s_set_vlan(struct rtl8366_smi *smi, int vid, u32 member, 
     665                             u32 untag, u32 fid) 
     666{ 
     667        struct rtl8366_vlan_4k vlan4k; 
     668        int err; 
    688669        int i; 
     670 
     671        /* Update the 4K table */ 
     672        err = rtl8366s_get_vlan_4k(smi, vid, &vlan4k); 
     673        if (err) 
     674                return err; 
     675 
     676        vlan4k.member = member; 
     677        vlan4k.untag = untag; 
     678        vlan4k.fid = fid; 
     679        err = rtl8366s_set_vlan_4k(smi, &vlan4k); 
     680        if (err) 
     681                return err; 
     682 
     683        /* Try to find an existing MC entry for this VID */ 
     684        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     685                struct rtl8366_vlan_mc vlanmc; 
     686 
     687                err = rtl8366s_get_vlan_mc(smi, i, &vlanmc); 
     688                if (err) 
     689                        return err; 
     690 
     691                if (vid == vlanmc.vid) { 
     692                        /* update the MC entry */ 
     693                        vlanmc.member = member; 
     694                        vlanmc.untag = untag; 
     695                        vlanmc.fid = fid; 
     696 
     697                        err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); 
     698                        break; 
     699                } 
     700        } 
     701 
     702        return err; 
     703} 
     704 
     705static int rtl8366s_get_pvid(struct rtl8366_smi *smi, int port, int *val) 
     706{ 
     707        struct rtl8366_vlan_mc vlanmc; 
     708        int err; 
     709        int index; 
     710 
     711        err = rtl8366s_get_mc_index(smi, port, &index); 
     712        if (err) 
     713                return err; 
     714 
     715        err = rtl8366s_get_vlan_mc(smi, index, &vlanmc); 
     716        if (err) 
     717                return err; 
     718 
     719        *val = vlanmc.vid; 
     720        return 0; 
     721} 
     722 
     723static int rtl8366s_mc_is_used(struct rtl8366_smi *smi, int mc_index, 
     724                               int *used) 
     725{ 
     726        int err; 
     727        int i; 
     728 
     729        *used = 0; 
     730        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
     731                int index = 0; 
     732 
     733                err = rtl8366s_get_mc_index(smi, i, &index); 
     734                if (err) 
     735                        return err; 
     736 
     737                if (mc_index == index) { 
     738                        *used = 1; 
     739                        break; 
     740                } 
     741        } 
     742 
     743        return 0; 
     744} 
     745 
     746static int rtl8366s_set_pvid(struct rtl8366_smi *smi, unsigned port, 
     747                             unsigned vid) 
     748{ 
    689749        struct rtl8366_vlan_mc vlanmc; 
    690750        struct rtl8366_vlan_4k vlan4k; 
    691  
    692         if (port >= RTL8366_NUM_PORTS || val >= RTL8366_NUM_VIDS) 
    693                 return -EINVAL; 
    694  
    695         /* Updating the 4K entry; lookup it and change the port member set */ 
    696         rtl8366s_get_vlan_4k(smi, val, &vlan4k); 
    697         vlan4k.member |= ((1 << port) | RTL8366_PORT_CPU); 
    698         vlan4k.untag = RTL8366_PORT_ALL_BUT_CPU; 
    699         rtl8366s_set_vlan_4k(smi, &vlan4k); 
    700  
    701         /* 
    702          * For the 16 entries more work needs to be done. First see if such 
    703          * VID is already there and change it 
    704          */ 
    705         for (i = 0; i < RTL8366_NUM_VLANS; ++i) { 
    706                 rtl8366s_get_vlan_mc(smi, i, &vlanmc); 
    707  
    708                 /* Try to find an existing vid and update port member set */ 
    709                 if (val == vlanmc.vid) { 
    710                         vlanmc.member |= ((1 << port) | RTL8366_PORT_CPU); 
    711                         rtl8366s_set_vlan_mc(smi, i, &vlanmc); 
    712  
    713                         /* Now update PVID register settings */ 
    714                         rtl8366s_set_port_vlan_index(smi, port, i); 
    715  
    716                         return 0; 
     751        int err; 
     752        int i; 
     753 
     754        /* Try to find an existing MC entry for this VID */ 
     755        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     756                err = rtl8366s_get_vlan_mc(smi, i, &vlanmc); 
     757                if (err) 
     758                        return err; 
     759 
     760                if (vid == vlanmc.vid) { 
     761                        err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); 
     762                        if (err) 
     763                                return err; 
     764 
     765                        err = rtl8366s_set_mc_index(smi, port, i); 
     766                        return err; 
    717767                } 
    718768        } 
    719769 
    720         /* 
    721          * PVID could not be found from vlan table. Replace unused (one that 
    722          * has no member ports) with new one 
    723          */ 
    724         for (i = 0; i < RTL8366_NUM_VLANS; ++i) { 
    725                 rtl8366s_get_vlan_mc(smi, i, &vlanmc); 
    726  
    727                 /* 
    728                  * See if this vlan member configuration is unused. It is 
    729                  * unused if member set contains no ports or CPU port only 
    730                  */ 
    731                 if (!vlanmc.member || vlanmc.member == RTL8366_PORT_CPU) { 
    732                         vlanmc.vid = val; 
    733                         vlanmc.priority = 0; 
    734                         vlanmc.untag = RTL8366_PORT_ALL_BUT_CPU; 
    735                         vlanmc.member = ((1 << port) | RTL8366_PORT_CPU); 
    736                         vlanmc.fid = 0; 
    737  
    738                         rtl8366s_set_vlan_mc(smi, i, &vlanmc); 
    739  
    740                         /* Now update PVID register settings */ 
    741                         rtl8366s_set_port_vlan_index(smi, port, i); 
    742  
    743                         return 0; 
     770        /* We have no MC entry for this VID, try to find an empty one */ 
     771        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     772                err = rtl8366s_get_vlan_mc(smi, i, &vlanmc); 
     773                if (err) 
     774                        return err; 
     775 
     776                if (vlanmc.vid == 0 && vlanmc.member == 0) { 
     777                        /* Update the entry from the 4K table */ 
     778                        err = rtl8366s_get_vlan_4k(smi, vid, &vlan4k); 
     779                        if (err) 
     780                                return err; 
     781 
     782                        vlanmc.vid = vid; 
     783                        vlanmc.member = vlan4k.member; 
     784                        vlanmc.untag = vlan4k.untag; 
     785                        vlanmc.fid = vlan4k.fid; 
     786                        err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); 
     787                        if (err) 
     788                                return err; 
     789 
     790                        err = rtl8366s_set_mc_index(smi, port, i); 
     791                        return err; 
    744792                } 
    745793        } 
    746794 
     795        /* MC table is full, try to find an unused entry and replace it */ 
     796        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     797                int used; 
     798 
     799                err = rtl8366s_mc_is_used(smi, i, &used); 
     800                if (err) 
     801                        return err; 
     802 
     803                if (!used) { 
     804                        /* Update the entry from the 4K table */ 
     805                        err = rtl8366s_get_vlan_4k(smi, vid, &vlan4k); 
     806                        if (err) 
     807                                return err; 
     808 
     809                        vlanmc.vid = vid; 
     810                        vlanmc.member = vlan4k.member; 
     811                        vlanmc.untag = vlan4k.untag; 
     812                        vlanmc.fid = vlan4k.fid; 
     813                        err = rtl8366s_set_vlan_mc(smi, i, &vlanmc); 
     814                        if (err) 
     815                                return err; 
     816 
     817                        err = rtl8366s_set_mc_index(smi, port, i); 
     818                        return err; 
     819                } 
     820        } 
     821 
    747822        dev_err(smi->parent, 
    748                 "All 16 vlan member configurations are in use\n"); 
    749  
    750         return -EINVAL; 
    751 } 
    752  
     823                "all VLAN member configurations are in use\n"); 
     824 
     825        return -ENOSPC; 
     826} 
    753827 
    754828static int rtl8366s_vlan_set_vlan(struct rtl8366_smi *smi, int enable) 
     
    767841static int rtl8366s_reset_vlan(struct rtl8366_smi *smi) 
    768842{ 
    769         struct rtl8366_vlan_4k vlan4k; 
    770843        struct rtl8366_vlan_mc vlanmc; 
    771844        int err; 
    772845        int i; 
    773846 
    774         /* clear 16 VLAN member configuration */ 
     847        /* clear VLAN member configurations */ 
    775848        vlanmc.vid = 0; 
    776849        vlanmc.priority = 0; 
     
    784857        } 
    785858 
    786         /* Set a default VLAN with vid 1 to 4K table for all ports */ 
    787         vlan4k.vid = 1; 
    788         vlan4k.member = RTL8366_PORT_ALL; 
    789         vlan4k.untag = RTL8366_PORT_ALL; 
    790         vlan4k.fid = 0; 
    791         err = rtl8366s_set_vlan_4k(smi, &vlan4k); 
    792         if (err) 
    793                 return err; 
    794  
    795         /* Set all ports PVID to default VLAN */ 
    796859        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
    797                 err = rtl8366s_set_vlan_port_pvid(smi, i, 0); 
     860                if (i == RTL8366_PORT_CPU) 
     861                        continue; 
     862 
     863                err = rtl8366s_set_vlan(smi, (i + 1), 
     864                                         (1 << i) | RTL8366_PORT_CPU, 
     865                                         (1 << i) | RTL8366_PORT_CPU, 
     866                                         0); 
     867                if (err) 
     868                        return err; 
     869 
     870                err = rtl8366s_set_pvid(smi, i, (i + 1)); 
    798871                if (err) 
    799872                        return err; 
     
    873946                for (j = 0; j < RTL8366_NUM_PORTS; ++j) { 
    874947                        int index = 0; 
    875                         if (!rtl8366s_get_port_vlan_index(smi, j, &index)) { 
     948                        if (!rtl8366s_get_mc_index(smi, j, &index)) { 
    876949                                if (index == i) 
    877950                                        len += snprintf(buf + len, 
     
    11681241        int i; 
    11691242        u32 len = 0; 
    1170         struct rtl8366_vlan_mc vlanmc; 
    11711243        struct rtl8366_vlan_4k vlan4k; 
    11721244        struct rtl8366s *rtl = sw_to_rtl8366s(dev); 
    11731245        struct rtl8366_smi *smi = &rtl->smi; 
    11741246        char *buf = rtl->buf; 
     1247        int err; 
    11751248 
    11761249        if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) 
     
    11791252        memset(buf, '\0', sizeof(rtl->buf)); 
    11801253 
    1181         rtl8366s_get_vlan_mc(smi, val->port_vlan, &vlanmc); 
    1182         rtl8366s_get_vlan_4k(smi, vlanmc.vid, &vlan4k); 
    1183  
    1184         len += snprintf(buf + len, sizeof(rtl->buf) - len, "VLAN %d: Ports: ", 
    1185                         val->port_vlan); 
    1186  
    1187         for (i = 0; i < RTL8366_NUM_PORTS; ++i) { 
    1188                 int index = 0; 
    1189                 if (!rtl8366s_get_port_vlan_index(smi, i, &index) && 
    1190                     index == val->port_vlan) 
    1191                         len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1192                                         "%d", i); 
    1193         } 
    1194         len += snprintf(buf + len, sizeof(rtl->buf) - len, "\n"); 
     1254        err = rtl8366s_get_vlan_4k(smi, val->port_vlan, &vlan4k); 
     1255        if (err) 
     1256                return err; 
    11951257 
    11961258        len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1197                         "\t\t vid \t prio \t member \t untag \t fid\n"); 
    1198         len += snprintf(buf + len, sizeof(rtl->buf) - len, "\tMC:\t"); 
     1259                        "VLAN %d: Ports: '", vlan4k.vid); 
     1260 
     1261        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
     1262                if (!(vlan4k.member & (1 << i))) 
     1263                        continue; 
     1264 
     1265                len += snprintf(buf + len, sizeof(rtl->buf) - len, "%d%s", i, 
     1266                                (vlan4k.untag & (1 << i)) ? "" : "t"); 
     1267        } 
     1268 
    11991269        len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1200                         "%d \t %d \t 0x%04x \t 0x%04x \t %d\n", 
    1201                         vlanmc.vid, vlanmc.priority, vlanmc.member, 
    1202                         vlanmc.untag, vlanmc.fid); 
    1203         len += snprintf(buf + len, sizeof(rtl->buf) - len, "\t4K:\t"); 
    1204         len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1205                         "%d \t  \t 0x%04x \t 0x%04x \t %d", 
    1206                         vlan4k.vid, vlan4k.member, vlan4k.untag, vlan4k.fid); 
     1270                        "', members=%04x, untag=%04x, fid=%u", 
     1271                        vlan4k.member, vlan4k.untag, vlan4k.fid); 
    12071272 
    12081273        val->value.s = buf; 
     
    13051370{ 
    13061371        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    1307         struct rtl8366_vlan_mc vlanmc; 
    13081372        struct switch_port *port; 
     1373        struct rtl8366_vlan_4k vlan4k; 
    13091374        int i; 
    13101375 
     
    13121377                return -EINVAL; 
    13131378 
    1314         rtl8366s_get_vlan_mc(smi, val->port_vlan, &vlanmc); 
     1379        rtl8366s_get_vlan_4k(smi, val->port_vlan, &vlan4k); 
    13151380 
    13161381        port = &val->value.ports[0]; 
    13171382        val->len = 0; 
    13181383        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
    1319                 if (!(vlanmc.member & BIT(i))) 
     1384                if (!(vlan4k.member & BIT(i))) 
    13201385                        continue; 
    13211386 
    13221387                port->id = i; 
    1323                 port->flags = (vlanmc.untag & BIT(i)) ? 
     1388                port->flags = (vlan4k.untag & BIT(i)) ? 
    13241389                                        0 : BIT(SWITCH_PORT_FLAG_TAGGED); 
    13251390                val->len++; 
     
    13331398{ 
    13341399        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    1335         struct rtl8366_vlan_mc vlanmc; 
    1336         struct rtl8366_vlan_4k vlan4k; 
    13371400        struct switch_port *port; 
     1401        u32 member = 0; 
     1402        u32 untag = 0; 
    13381403        int i; 
    13391404 
    13401405        if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) 
    13411406                return -EINVAL; 
    1342  
    1343         rtl8366s_get_vlan_mc(smi, val->port_vlan, &vlanmc); 
    1344         rtl8366s_get_vlan_4k(smi, vlanmc.vid, &vlan4k); 
    1345  
    1346         vlanmc.untag = 0; 
    1347         vlanmc.member = 0; 
    13481407 
    13491408        port = &val->value.ports[0]; 
    13501409        for (i = 0; i < val->len; i++, port++) { 
    1351                 vlanmc.member |= BIT(port->id); 
     1410                member |= BIT(port->id); 
    13521411 
    13531412                if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) 
    1354                         vlanmc.untag |= BIT(port->id); 
    1355         } 
    1356  
    1357         vlan4k.member = vlanmc.member; 
    1358         vlan4k.untag = vlanmc.untag; 
    1359  
    1360         rtl8366s_set_vlan_mc(smi, val->port_vlan, &vlanmc); 
    1361         rtl8366s_set_vlan_4k(smi, &vlan4k); 
    1362         return 0; 
     1413                        untag |= BIT(port->id); 
     1414        } 
     1415 
     1416        return rtl8366s_set_vlan(smi, val->port_vlan, member, untag, 0); 
    13631417} 
    13641418 
     
    13661420{ 
    13671421        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    1368         return rtl8366s_get_vlan_port_pvid(smi, port, val); 
     1422        return rtl8366s_get_pvid(smi, port, val); 
    13691423} 
    13701424 
     
    13721426{ 
    13731427        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    1374         return rtl8366s_set_vlan_port_pvid(smi, port, val); 
     1428        return rtl8366s_set_pvid(smi, port, val); 
    13751429} 
    13761430 
Note: See TracChangeset for help on using the changeset viewer.