aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ieee802154/at86rf230.c433
-rw-r--r--include/linux/nl802154.h12
-rw-r--r--include/net/mac802154.h35
-rw-r--r--include/net/wpan-phy.h19
-rw-r--r--net/ieee802154/ieee802154.h1
-rw-r--r--net/ieee802154/netlink.c1
-rw-r--r--net/ieee802154/nl-phy.c198
-rw-r--r--net/ieee802154/nl_policy.c10
-rw-r--r--net/ieee802154/wpan-class.c10
-rw-r--r--net/mac802154/ieee802154_dev.c67
10 files changed, 668 insertions, 118 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index ab31544bc254..34bf011584fb 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -37,7 +37,6 @@
37 37
38struct at86rf230_local { 38struct at86rf230_local {
39 struct spi_device *spi; 39 struct spi_device *spi;
40 int rstn, slp_tr, dig2;
41 40
42 u8 part; 41 u8 part;
43 u8 vers; 42 u8 vers;
@@ -53,8 +52,16 @@ struct at86rf230_local {
53 spinlock_t lock; 52 spinlock_t lock;
54 bool irq_busy; 53 bool irq_busy;
55 bool is_tx; 54 bool is_tx;
55 bool tx_aret;
56
57 int rssi_base_val;
56}; 58};
57 59
60static inline int is_rf212(struct at86rf230_local *local)
61{
62 return local->part == 7;
63}
64
58#define RG_TRX_STATUS (0x01) 65#define RG_TRX_STATUS (0x01)
59#define SR_TRX_STATUS 0x01, 0x1f, 0 66#define SR_TRX_STATUS 0x01, 0x1f, 0
60#define SR_RESERVED_01_3 0x01, 0x20, 5 67#define SR_RESERVED_01_3 0x01, 0x20, 5
@@ -100,7 +107,10 @@ struct at86rf230_local {
100#define SR_SFD_VALUE 0x0b, 0xff, 0 107#define SR_SFD_VALUE 0x0b, 0xff, 0
101#define RG_TRX_CTRL_2 (0x0c) 108#define RG_TRX_CTRL_2 (0x0c)
102#define SR_OQPSK_DATA_RATE 0x0c, 0x03, 0 109#define SR_OQPSK_DATA_RATE 0x0c, 0x03, 0
103#define SR_RESERVED_0c_2 0x0c, 0x7c, 2 110#define SR_SUB_MODE 0x0c, 0x04, 2
111#define SR_BPSK_QPSK 0x0c, 0x08, 3
112#define SR_OQPSK_SUB1_RC_EN 0x0c, 0x10, 4
113#define SR_RESERVED_0c_5 0x0c, 0x60, 5
104#define SR_RX_SAFE_MODE 0x0c, 0x80, 7 114#define SR_RX_SAFE_MODE 0x0c, 0x80, 7
105#define RG_ANT_DIV (0x0d) 115#define RG_ANT_DIV (0x0d)
106#define SR_ANT_CTRL 0x0d, 0x03, 0 116#define SR_ANT_CTRL 0x0d, 0x03, 0
@@ -145,7 +155,7 @@ struct at86rf230_local {
145#define SR_RESERVED_17_5 0x17, 0x08, 3 155#define SR_RESERVED_17_5 0x17, 0x08, 3
146#define SR_AACK_UPLD_RES_FT 0x17, 0x10, 4 156#define SR_AACK_UPLD_RES_FT 0x17, 0x10, 4
147#define SR_AACK_FLTR_RES_FT 0x17, 0x20, 5 157#define SR_AACK_FLTR_RES_FT 0x17, 0x20, 5
148#define SR_RESERVED_17_2 0x17, 0x40, 6 158#define SR_CSMA_LBT_MODE 0x17, 0x40, 6
149#define SR_RESERVED_17_1 0x17, 0x80, 7 159#define SR_RESERVED_17_1 0x17, 0x80, 7
150#define RG_FTN_CTRL (0x18) 160#define RG_FTN_CTRL (0x18)
151#define SR_RESERVED_18_2 0x18, 0x7f, 0 161#define SR_RESERVED_18_2 0x18, 0x7f, 0
@@ -244,6 +254,57 @@ struct at86rf230_local {
244#define STATE_TRANSITION_IN_PROGRESS 0x1F 254#define STATE_TRANSITION_IN_PROGRESS 0x1F
245 255
246static int 256static int
257__at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
258 u8 *version)
259{
260 u8 data[4];
261 u8 *buf = kmalloc(2, GFP_KERNEL);
262 int status;
263 struct spi_message msg;
264 struct spi_transfer xfer = {
265 .len = 2,
266 .tx_buf = buf,
267 .rx_buf = buf,
268 };
269 u8 reg;
270
271 if (!buf)
272 return -ENOMEM;
273
274 for (reg = RG_PART_NUM; reg <= RG_MAN_ID_1; reg++) {
275 buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
276 buf[1] = 0xff;
277 dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
278 spi_message_init(&msg);
279 spi_message_add_tail(&xfer, &msg);
280
281 status = spi_sync(spi, &msg);
282 dev_vdbg(&spi->dev, "status = %d\n", status);
283 if (msg.status)
284 status = msg.status;
285
286 dev_vdbg(&spi->dev, "status = %d\n", status);
287 dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
288 dev_vdbg(&spi->dev, "buf[1] = %02x\n", buf[1]);
289
290 if (status == 0)
291 data[reg - RG_PART_NUM] = buf[1];
292 else
293 break;
294 }
295
296 if (status == 0) {
297 *part = data[0];
298 *version = data[1];
299 *man_id = (data[3] << 8) | data[2];
300 }
301
302 kfree(buf);
303
304 return status;
305}
306
307static int
247__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data) 308__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
248{ 309{
249 u8 *buf = lp->buf; 310 u8 *buf = lp->buf;
@@ -489,7 +550,9 @@ at86rf230_state(struct ieee802154_dev *dev, int state)
489 } while (val == STATE_TRANSITION_IN_PROGRESS); 550 } while (val == STATE_TRANSITION_IN_PROGRESS);
490 551
491 552
492 if (val == desired_status) 553 if (val == desired_status ||
554 (desired_status == STATE_RX_ON && val == STATE_BUSY_RX) ||
555 (desired_status == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK))
493 return 0; 556 return 0;
494 557
495 pr_err("unexpected state change: %d, asked for %d\n", val, state); 558 pr_err("unexpected state change: %d, asked for %d\n", val, state);
@@ -510,7 +573,11 @@ at86rf230_start(struct ieee802154_dev *dev)
510 if (rc) 573 if (rc)
511 return rc; 574 return rc;
512 575
513 return at86rf230_state(dev, STATE_RX_ON); 576 rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
577 if (rc)
578 return rc;
579
580 return at86rf230_state(dev, STATE_RX_AACK_ON);
514} 581}
515 582
516static void 583static void
@@ -520,6 +587,39 @@ at86rf230_stop(struct ieee802154_dev *dev)
520} 587}
521 588
522static int 589static int
590at86rf230_set_channel(struct at86rf230_local *lp, int page, int channel)
591{
592 lp->rssi_base_val = -91;
593
594 return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
595}
596
597static int
598at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
599{
600 int rc;
601
602 if (channel == 0)
603 rc = at86rf230_write_subreg(lp, SR_SUB_MODE, 0);
604 else
605 rc = at86rf230_write_subreg(lp, SR_SUB_MODE, 1);
606 if (rc < 0)
607 return rc;
608
609 if (page == 0) {
610 rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 0);
611 lp->rssi_base_val = -100;
612 } else {
613 rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 1);
614 lp->rssi_base_val = -98;
615 }
616 if (rc < 0)
617 return rc;
618
619 return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
620}
621
622static int
523at86rf230_channel(struct ieee802154_dev *dev, int page, int channel) 623at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
524{ 624{
525 struct at86rf230_local *lp = dev->priv; 625 struct at86rf230_local *lp = dev->priv;
@@ -527,14 +627,22 @@ at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
527 627
528 might_sleep(); 628 might_sleep();
529 629
530 if (page != 0 || channel < 11 || channel > 26) { 630 if (page < 0 || page > 31 ||
631 !(lp->dev->phy->channels_supported[page] & BIT(channel))) {
531 WARN_ON(1); 632 WARN_ON(1);
532 return -EINVAL; 633 return -EINVAL;
533 } 634 }
534 635
535 rc = at86rf230_write_subreg(lp, SR_CHANNEL, channel); 636 if (is_rf212(lp))
637 rc = at86rf212_set_channel(lp, page, channel);
638 else
639 rc = at86rf230_set_channel(lp, page, channel);
640 if (rc < 0)
641 return rc;
642
536 msleep(1); /* Wait for PLL */ 643 msleep(1); /* Wait for PLL */
537 dev->phy->current_channel = channel; 644 dev->phy->current_channel = channel;
645 dev->phy->current_page = page;
538 646
539 return 0; 647 return 0;
540} 648}
@@ -568,6 +676,12 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
568 if (rc) 676 if (rc)
569 goto err_rx; 677 goto err_rx;
570 678
679 if (lp->tx_aret) {
680 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON);
681 if (rc)
682 goto err_rx;
683 }
684
571 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX); 685 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
572 if (rc) 686 if (rc)
573 goto err_rx; 687 goto err_rx;
@@ -668,6 +782,98 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
668 return 0; 782 return 0;
669} 783}
670 784
785static int
786at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
787{
788 struct at86rf230_local *lp = dev->priv;
789 int rc;
790
791 /* typical maximum output is 5dBm with RG_PHY_TX_PWR 0x60, lower five
792 * bits decrease power in 1dB steps. 0x60 represents extra PA gain of
793 * 0dB.
794 * thus, supported values for db range from -26 to 5, for 31dB of
795 * reduction to 0dB of reduction.
796 */
797 if (db > 5 || db < -26)
798 return -EINVAL;
799
800 db = -(db - 5);
801
802 rc = __at86rf230_write(lp, RG_PHY_TX_PWR, 0x60 | db);
803 if (rc)
804 return rc;
805
806 return 0;
807}
808
809static int
810at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
811{
812 struct at86rf230_local *lp = dev->priv;
813
814 return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on);
815}
816
817static int
818at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
819{
820 struct at86rf230_local *lp = dev->priv;
821
822 return at86rf230_write_subreg(lp, SR_CCA_MODE, mode);
823}
824
825static int
826at86rf212_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
827{
828 struct at86rf230_local *lp = dev->priv;
829 int desens_steps;
830
831 if (level < lp->rssi_base_val || level > 30)
832 return -EINVAL;
833
834 desens_steps = (level - lp->rssi_base_val) * 100 / 207;
835
836 return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, desens_steps);
837}
838
839static int
840at86rf212_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
841 u8 retries)
842{
843 struct at86rf230_local *lp = dev->priv;
844 int rc;
845
846 if (min_be > max_be || max_be > 8 || retries > 5)
847 return -EINVAL;
848
849 rc = at86rf230_write_subreg(lp, SR_MIN_BE, min_be);
850 if (rc)
851 return rc;
852
853 rc = at86rf230_write_subreg(lp, SR_MAX_BE, max_be);
854 if (rc)
855 return rc;
856
857 return at86rf230_write_subreg(lp, SR_MAX_CSMA_RETRIES, max_be);
858}
859
860static int
861at86rf212_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
862{
863 struct at86rf230_local *lp = dev->priv;
864 int rc = 0;
865
866 if (retries < -1 || retries > 15)
867 return -EINVAL;
868
869 lp->tx_aret = retries >= 0;
870
871 if (retries >= 0)
872 rc = at86rf230_write_subreg(lp, SR_MAX_FRAME_RETRIES, retries);
873
874 return rc;
875}
876
671static struct ieee802154_ops at86rf230_ops = { 877static struct ieee802154_ops at86rf230_ops = {
672 .owner = THIS_MODULE, 878 .owner = THIS_MODULE,
673 .xmit = at86rf230_xmit, 879 .xmit = at86rf230_xmit,
@@ -678,6 +884,22 @@ static struct ieee802154_ops at86rf230_ops = {
678 .set_hw_addr_filt = at86rf230_set_hw_addr_filt, 884 .set_hw_addr_filt = at86rf230_set_hw_addr_filt,
679}; 885};
680 886
887static struct ieee802154_ops at86rf212_ops = {
888 .owner = THIS_MODULE,
889 .xmit = at86rf230_xmit,
890 .ed = at86rf230_ed,
891 .set_channel = at86rf230_channel,
892 .start = at86rf230_start,
893 .stop = at86rf230_stop,
894 .set_hw_addr_filt = at86rf230_set_hw_addr_filt,
895 .set_txpower = at86rf212_set_txpower,
896 .set_lbt = at86rf212_set_lbt,
897 .set_cca_mode = at86rf212_set_cca_mode,
898 .set_cca_ed_level = at86rf212_set_cca_ed_level,
899 .set_csma_params = at86rf212_set_csma_params,
900 .set_frame_retries = at86rf212_set_frame_retries,
901};
902
681static void at86rf230_irqwork(struct work_struct *work) 903static void at86rf230_irqwork(struct work_struct *work)
682{ 904{
683 struct at86rf230_local *lp = 905 struct at86rf230_local *lp =
@@ -752,22 +974,15 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
752 struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data; 974 struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data;
753 int rc, irq_pol; 975 int rc, irq_pol;
754 u8 status; 976 u8 status;
977 u8 csma_seed[2];
755 978
756 rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status); 979 rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
757 if (rc) 980 if (rc)
758 return rc; 981 return rc;
759 982
760 dev_info(&lp->spi->dev, "Status: %02x\n", status); 983 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
761 if (status == STATE_P_ON) { 984 if (rc)
762 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TRX_OFF); 985 return rc;
763 if (rc)
764 return rc;
765 msleep(1);
766 rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
767 if (rc)
768 return rc;
769 dev_info(&lp->spi->dev, "Status: %02x\n", status);
770 }
771 986
772 /* configure irq polarity, defaults to high active */ 987 /* configure irq polarity, defaults to high active */
773 if (pdata->irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) 988 if (pdata->irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
@@ -783,6 +998,14 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
783 if (rc) 998 if (rc)
784 return rc; 999 return rc;
785 1000
1001 get_random_bytes(csma_seed, ARRAY_SIZE(csma_seed));
1002 rc = at86rf230_write_subreg(lp, SR_CSMA_SEED_0, csma_seed[0]);
1003 if (rc)
1004 return rc;
1005 rc = at86rf230_write_subreg(lp, SR_CSMA_SEED_1, csma_seed[1]);
1006 if (rc)
1007 return rc;
1008
786 /* CLKM changes are applied immediately */ 1009 /* CLKM changes are applied immediately */
787 rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00); 1010 rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00);
788 if (rc) 1011 if (rc)
@@ -795,16 +1018,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
795 /* Wait the next SLEEP cycle */ 1018 /* Wait the next SLEEP cycle */
796 msleep(100); 1019 msleep(100);
797 1020
798 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
799 if (rc)
800 return rc;
801 msleep(1);
802
803 rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
804 if (rc)
805 return rc;
806 dev_info(&lp->spi->dev, "Status: %02x\n", status);
807
808 rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status); 1021 rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
809 if (rc) 1022 if (rc)
810 return rc; 1023 return rc;
@@ -824,26 +1037,18 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
824 return 0; 1037 return 0;
825} 1038}
826 1039
827static void at86rf230_fill_data(struct spi_device *spi)
828{
829 struct at86rf230_local *lp = spi_get_drvdata(spi);
830 struct at86rf230_platform_data *pdata = spi->dev.platform_data;
831
832 lp->rstn = pdata->rstn;
833 lp->slp_tr = pdata->slp_tr;
834 lp->dig2 = pdata->dig2;
835}
836
837static int at86rf230_probe(struct spi_device *spi) 1040static int at86rf230_probe(struct spi_device *spi)
838{ 1041{
839 struct at86rf230_platform_data *pdata; 1042 struct at86rf230_platform_data *pdata;
840 struct ieee802154_dev *dev; 1043 struct ieee802154_dev *dev;
841 struct at86rf230_local *lp; 1044 struct at86rf230_local *lp;
842 u8 man_id_0, man_id_1, status; 1045 u16 man_id = 0;
1046 u8 part = 0, version = 0, status;
843 irq_handler_t irq_handler; 1047 irq_handler_t irq_handler;
844 work_func_t irq_worker; 1048 work_func_t irq_worker;
845 int rc, supported = 0; 1049 int rc;
846 const char *chip; 1050 const char *chip;
1051 struct ieee802154_ops *ops = NULL;
847 1052
848 if (!spi->irq) { 1053 if (!spi->irq) {
849 dev_err(&spi->dev, "no IRQ specified\n"); 1054 dev_err(&spi->dev, "no IRQ specified\n");
@@ -856,116 +1061,117 @@ static int at86rf230_probe(struct spi_device *spi)
856 return -EINVAL; 1061 return -EINVAL;
857 } 1062 }
858 1063
859 dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops); 1064 rc = gpio_request(pdata->rstn, "rstn");
860 if (!dev)
861 return -ENOMEM;
862
863 lp = dev->priv;
864 lp->dev = dev;
865
866 lp->spi = spi;
867
868 dev->parent = &spi->dev;
869 dev->extra_tx_headroom = 0;
870 /* We do support only 2.4 Ghz */
871 dev->phy->channels_supported[0] = 0x7FFF800;
872 dev->flags = IEEE802154_HW_OMIT_CKSUM;
873
874 if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
875 irq_worker = at86rf230_irqwork;
876 irq_handler = at86rf230_isr;
877 } else {
878 irq_worker = at86rf230_irqwork_level;
879 irq_handler = at86rf230_isr_level;
880 }
881
882 mutex_init(&lp->bmux);
883 INIT_WORK(&lp->irqwork, irq_worker);
884 spin_lock_init(&lp->lock);
885 init_completion(&lp->tx_complete);
886
887 spi_set_drvdata(spi, lp);
888
889 at86rf230_fill_data(spi);
890
891 rc = gpio_request(lp->rstn, "rstn");
892 if (rc) 1065 if (rc)
893 goto err_rstn; 1066 return rc;
894 1067
895 if (gpio_is_valid(lp->slp_tr)) { 1068 if (gpio_is_valid(pdata->slp_tr)) {
896 rc = gpio_request(lp->slp_tr, "slp_tr"); 1069 rc = gpio_request(pdata->slp_tr, "slp_tr");
897 if (rc) 1070 if (rc)
898 goto err_slp_tr; 1071 goto err_slp_tr;
899 } 1072 }
900 1073
901 rc = gpio_direction_output(lp->rstn, 1); 1074 rc = gpio_direction_output(pdata->rstn, 1);
902 if (rc) 1075 if (rc)
903 goto err_gpio_dir; 1076 goto err_gpio_dir;
904 1077
905 if (gpio_is_valid(lp->slp_tr)) { 1078 if (gpio_is_valid(pdata->slp_tr)) {
906 rc = gpio_direction_output(lp->slp_tr, 0); 1079 rc = gpio_direction_output(pdata->slp_tr, 0);
907 if (rc) 1080 if (rc)
908 goto err_gpio_dir; 1081 goto err_gpio_dir;
909 } 1082 }
910 1083
911 /* Reset */ 1084 /* Reset */
912 msleep(1); 1085 msleep(1);
913 gpio_set_value(lp->rstn, 0); 1086 gpio_set_value(pdata->rstn, 0);
914 msleep(1); 1087 msleep(1);
915 gpio_set_value(lp->rstn, 1); 1088 gpio_set_value(pdata->rstn, 1);
916 msleep(1); 1089 msleep(1);
917 1090
918 rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0); 1091 rc = __at86rf230_detect_device(spi, &man_id, &part, &version);
919 if (rc) 1092 if (rc < 0)
920 goto err_gpio_dir;
921 rc = at86rf230_read_subreg(lp, SR_MAN_ID_1, &man_id_1);
922 if (rc)
923 goto err_gpio_dir; 1093 goto err_gpio_dir;
924 1094
925 if (man_id_1 != 0x00 || man_id_0 != 0x1f) { 1095 if (man_id != 0x001f) {
926 dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n", 1096 dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
927 man_id_1, man_id_0); 1097 man_id >> 8, man_id & 0xFF);
928 rc = -EINVAL; 1098 rc = -EINVAL;
929 goto err_gpio_dir; 1099 goto err_gpio_dir;
930 } 1100 }
931 1101
932 rc = at86rf230_read_subreg(lp, SR_PART_NUM, &lp->part); 1102 switch (part) {
933 if (rc)
934 goto err_gpio_dir;
935
936 rc = at86rf230_read_subreg(lp, SR_VERSION_NUM, &lp->vers);
937 if (rc)
938 goto err_gpio_dir;
939
940 switch (lp->part) {
941 case 2: 1103 case 2:
942 chip = "at86rf230"; 1104 chip = "at86rf230";
943 /* supported = 1; FIXME: should be easy to support; */ 1105 /* FIXME: should be easy to support; */
944 break; 1106 break;
945 case 3: 1107 case 3:
946 chip = "at86rf231"; 1108 chip = "at86rf231";
947 supported = 1; 1109 ops = &at86rf230_ops;
1110 break;
1111 case 7:
1112 chip = "at86rf212";
1113 if (version == 1)
1114 ops = &at86rf212_ops;
948 break; 1115 break;
949 default: 1116 default:
950 chip = "UNKNOWN"; 1117 chip = "UNKNOWN";
951 break; 1118 break;
952 } 1119 }
953 1120
954 dev_info(&spi->dev, "Detected %s chip version %d\n", chip, lp->vers); 1121 dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version);
955 if (!supported) { 1122 if (!ops) {
956 rc = -ENOTSUPP; 1123 rc = -ENOTSUPP;
957 goto err_gpio_dir; 1124 goto err_gpio_dir;
958 } 1125 }
959 1126
1127 dev = ieee802154_alloc_device(sizeof(*lp), ops);
1128 if (!dev) {
1129 rc = -ENOMEM;
1130 goto err_gpio_dir;
1131 }
1132
1133 lp = dev->priv;
1134 lp->dev = dev;
1135 lp->part = part;
1136 lp->vers = version;
1137
1138 lp->spi = spi;
1139
1140 dev->parent = &spi->dev;
1141 dev->extra_tx_headroom = 0;
1142 dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
1143
1144 if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
1145 irq_worker = at86rf230_irqwork;
1146 irq_handler = at86rf230_isr;
1147 } else {
1148 irq_worker = at86rf230_irqwork_level;
1149 irq_handler = at86rf230_isr_level;
1150 }
1151
1152 mutex_init(&lp->bmux);
1153 INIT_WORK(&lp->irqwork, irq_worker);
1154 spin_lock_init(&lp->lock);
1155 init_completion(&lp->tx_complete);
1156
1157 spi_set_drvdata(spi, lp);
1158
1159 if (is_rf212(lp)) {
1160 dev->phy->channels_supported[0] = 0x00007FF;
1161 dev->phy->channels_supported[2] = 0x00007FF;
1162 } else {
1163 dev->phy->channels_supported[0] = 0x7FFF800;
1164 }
1165
960 rc = at86rf230_hw_init(lp); 1166 rc = at86rf230_hw_init(lp);
961 if (rc) 1167 if (rc)
962 goto err_gpio_dir; 1168 goto err_hw_init;
963 1169
964 rc = request_irq(spi->irq, irq_handler, 1170 rc = request_irq(spi->irq, irq_handler,
965 IRQF_SHARED | pdata->irq_type, 1171 IRQF_SHARED | pdata->irq_type,
966 dev_name(&spi->dev), lp); 1172 dev_name(&spi->dev), lp);
967 if (rc) 1173 if (rc)
968 goto err_gpio_dir; 1174 goto err_hw_init;
969 1175
970 /* Read irq status register to reset irq line */ 1176 /* Read irq status register to reset irq line */
971 rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status); 1177 rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
@@ -980,30 +1186,33 @@ static int at86rf230_probe(struct spi_device *spi)
980 1186
981err_irq: 1187err_irq:
982 free_irq(spi->irq, lp); 1188 free_irq(spi->irq, lp);
1189err_hw_init:
983 flush_work(&lp->irqwork); 1190 flush_work(&lp->irqwork);
984err_gpio_dir: 1191 spi_set_drvdata(spi, NULL);
985 if (gpio_is_valid(lp->slp_tr))
986 gpio_free(lp->slp_tr);
987err_slp_tr:
988 gpio_free(lp->rstn);
989err_rstn:
990 mutex_destroy(&lp->bmux); 1192 mutex_destroy(&lp->bmux);
991 ieee802154_free_device(lp->dev); 1193 ieee802154_free_device(lp->dev);
1194
1195err_gpio_dir:
1196 if (gpio_is_valid(pdata->slp_tr))
1197 gpio_free(pdata->slp_tr);
1198err_slp_tr:
1199 gpio_free(pdata->rstn);
992 return rc; 1200 return rc;
993} 1201}
994 1202
995static int at86rf230_remove(struct spi_device *spi) 1203static int at86rf230_remove(struct spi_device *spi)
996{ 1204{
997 struct at86rf230_local *lp = spi_get_drvdata(spi); 1205 struct at86rf230_local *lp = spi_get_drvdata(spi);
1206 struct at86rf230_platform_data *pdata = spi->dev.platform_data;
998 1207
999 ieee802154_unregister_device(lp->dev); 1208 ieee802154_unregister_device(lp->dev);
1000 1209
1001 free_irq(spi->irq, lp); 1210 free_irq(spi->irq, lp);
1002 flush_work(&lp->irqwork); 1211 flush_work(&lp->irqwork);
1003 1212
1004 if (gpio_is_valid(lp->slp_tr)) 1213 if (gpio_is_valid(pdata->slp_tr))
1005 gpio_free(lp->slp_tr); 1214 gpio_free(pdata->slp_tr);
1006 gpio_free(lp->rstn); 1215 gpio_free(pdata->rstn);
1007 1216
1008 mutex_destroy(&lp->bmux); 1217 mutex_destroy(&lp->bmux);
1009 ieee802154_free_device(lp->dev); 1218 ieee802154_free_device(lp->dev);
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index fd4f2d1cdf6c..e110b8c266f5 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -70,6 +70,16 @@ enum {
70 IEEE802154_ATTR_PHY_NAME, 70 IEEE802154_ATTR_PHY_NAME,
71 IEEE802154_ATTR_DEV_TYPE, 71 IEEE802154_ATTR_DEV_TYPE,
72 72
73 IEEE802154_ATTR_TXPOWER,
74 IEEE802154_ATTR_LBT_ENABLED,
75 IEEE802154_ATTR_CCA_MODE,
76 IEEE802154_ATTR_CCA_ED_LEVEL,
77 IEEE802154_ATTR_CSMA_RETRIES,
78 IEEE802154_ATTR_CSMA_MIN_BE,
79 IEEE802154_ATTR_CSMA_MAX_BE,
80
81 IEEE802154_ATTR_FRAME_RETRIES,
82
73 __IEEE802154_ATTR_MAX, 83 __IEEE802154_ATTR_MAX,
74}; 84};
75 85
@@ -122,6 +132,8 @@ enum {
122 IEEE802154_ADD_IFACE, 132 IEEE802154_ADD_IFACE,
123 IEEE802154_DEL_IFACE, 133 IEEE802154_DEL_IFACE,
124 134
135 IEEE802154_SET_PHYPARAMS,
136
125 __IEEE802154_CMD_MAX, 137 __IEEE802154_CMD_MAX,
126}; 138};
127 139
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 807d6b7a943f..8ca3d04e7558 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -113,6 +113,32 @@ struct ieee802154_dev {
113 * Set radio for listening on specific address. 113 * Set radio for listening on specific address.
114 * Set the device for listening on specified address. 114 * Set the device for listening on specified address.
115 * Returns either zero, or negative errno. 115 * Returns either zero, or negative errno.
116 *
117 * set_txpower:
118 * Set radio transmit power in dB. Called with pib_lock held.
119 * Returns either zero, or negative errno.
120 *
121 * set_lbt
122 * Enables or disables listen before talk on the device. Called with
123 * pib_lock held.
124 * Returns either zero, or negative errno.
125 *
126 * set_cca_mode
127 * Sets the CCA mode used by the device. Called with pib_lock held.
128 * Returns either zero, or negative errno.
129 *
130 * set_cca_ed_level
131 * Sets the CCA energy detection threshold in dBm. Called with pib_lock
132 * held.
133 * Returns either zero, or negative errno.
134 *
135 * set_csma_params
136 * Sets the CSMA parameter set for the PHY. Called with pib_lock held.
137 * Returns either zero, or negative errno.
138 *
139 * set_frame_retries
140 * Sets the retransmission attempt limit. Called with pib_lock held.
141 * Returns either zero, or negative errno.
116 */ 142 */
117struct ieee802154_ops { 143struct ieee802154_ops {
118 struct module *owner; 144 struct module *owner;
@@ -129,6 +155,15 @@ struct ieee802154_ops {
129 unsigned long changed); 155 unsigned long changed);
130 int (*ieee_addr)(struct ieee802154_dev *dev, 156 int (*ieee_addr)(struct ieee802154_dev *dev,
131 u8 addr[IEEE802154_ADDR_LEN]); 157 u8 addr[IEEE802154_ADDR_LEN]);
158 int (*set_txpower)(struct ieee802154_dev *dev, int db);
159 int (*set_lbt)(struct ieee802154_dev *dev, bool on);
160 int (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
161 int (*set_cca_ed_level)(struct ieee802154_dev *dev,
162 s32 level);
163 int (*set_csma_params)(struct ieee802154_dev *dev,
164 u8 min_be, u8 max_be, u8 retries);
165 int (*set_frame_retries)(struct ieee802154_dev *dev,
166 s8 retries);
132}; 167};
133 168
134/* Basic interface to register ieee802154 device */ 169/* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index b52bda8d13b1..10ab0fc6d4f7 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -37,15 +37,22 @@ struct wpan_phy {
37 struct mutex pib_lock; 37 struct mutex pib_lock;
38 38
39 /* 39 /*
40 * This is a PIB according to 802.15.4-2006. 40 * This is a PIB according to 802.15.4-2011.
41 * We do not provide timing-related variables, as they 41 * We do not provide timing-related variables, as they
42 * aren't used outside of driver 42 * aren't used outside of driver
43 */ 43 */
44 u8 current_channel; 44 u8 current_channel;
45 u8 current_page; 45 u8 current_page;
46 u32 channels_supported[32]; 46 u32 channels_supported[32];
47 u8 transmit_power; 47 s8 transmit_power;
48 u8 cca_mode; 48 u8 cca_mode;
49 u8 min_be;
50 u8 max_be;
51 u8 csma_retries;
52 s8 frame_retries;
53
54 bool lbt;
55 s32 cca_ed_level;
49 56
50 struct device dev; 57 struct device dev;
51 int idx; 58 int idx;
@@ -54,6 +61,14 @@ struct wpan_phy {
54 const char *name, int type); 61 const char *name, int type);
55 void (*del_iface)(struct wpan_phy *phy, struct net_device *dev); 62 void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
56 63
64 int (*set_txpower)(struct wpan_phy *phy, int db);
65 int (*set_lbt)(struct wpan_phy *phy, bool on);
66 int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
67 int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
68 int (*set_csma_params)(struct wpan_phy *phy, u8 min_be, u8 max_be,
69 u8 retries);
70 int (*set_frame_retries)(struct wpan_phy *phy, s8 retries);
71
57 char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); 72 char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
58}; 73};
59 74
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
index cee4425b9956..6cbc8965be91 100644
--- a/net/ieee802154/ieee802154.h
+++ b/net/ieee802154/ieee802154.h
@@ -53,6 +53,7 @@ int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info);
53int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb); 53int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb);
54int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info); 54int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info);
55int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info); 55int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info);
56int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info);
56 57
57enum ieee802154_mcgrp_ids { 58enum ieee802154_mcgrp_ids {
58 IEEE802154_COORD_MCGRP, 59 IEEE802154_COORD_MCGRP,
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 43f1b2bf469f..67c151bf4b91 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -115,6 +115,7 @@ static const struct genl_ops ieee8021154_ops[] = {
115 ieee802154_dump_phy), 115 ieee802154_dump_phy),
116 IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), 116 IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),
117 IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), 117 IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),
118 IEEE802154_OP(IEEE802154_SET_PHYPARAMS, ieee802154_set_phyparams),
118 /* see nl-mac.c */ 119 /* see nl-mac.c */
119 IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), 120 IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
120 IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), 121 IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 89b265aea151..c9dfd6f59e34 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -55,7 +55,15 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
55 mutex_lock(&phy->pib_lock); 55 mutex_lock(&phy->pib_lock);
56 if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || 56 if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
57 nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) || 57 nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
58 nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel)) 58 nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) ||
59 nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) ||
60 nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt) ||
61 nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode) ||
62 nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, phy->cca_ed_level) ||
63 nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES, phy->csma_retries) ||
64 nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE, phy->min_be) ||
65 nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE, phy->max_be) ||
66 nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES, phy->frame_retries))
59 goto nla_put_failure; 67 goto nla_put_failure;
60 for (i = 0; i < 32; i++) { 68 for (i = 0; i < 32; i++) {
61 if (phy->channels_supported[i]) 69 if (phy->channels_supported[i])
@@ -354,3 +362,191 @@ out_dev:
354 362
355 return rc; 363 return rc;
356} 364}
365
366static int phy_set_txpower(struct wpan_phy *phy, struct genl_info *info)
367{
368 int txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
369 int rc;
370
371 rc = phy->set_txpower(phy, txpower);
372 if (rc < 0)
373 return rc;
374
375 phy->transmit_power = txpower;
376
377 return 0;
378}
379
380static int phy_set_lbt(struct wpan_phy *phy, struct genl_info *info)
381{
382 u8 on = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
383 int rc;
384
385 rc = phy->set_lbt(phy, on);
386 if (rc < 0)
387 return rc;
388
389 phy->lbt = on;
390
391 return 0;
392}
393
394static int phy_set_cca_mode(struct wpan_phy *phy, struct genl_info *info)
395{
396 u8 mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
397 int rc;
398
399 if (mode > 3)
400 return -EINVAL;
401
402 rc = phy->set_cca_mode(phy, mode);
403 if (rc < 0)
404 return rc;
405
406 phy->cca_mode = mode;
407
408 return 0;
409}
410
411static int phy_set_cca_ed_level(struct wpan_phy *phy, struct genl_info *info)
412{
413 s32 level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]);
414 int rc;
415
416 rc = phy->set_cca_ed_level(phy, level);
417 if (rc < 0)
418 return rc;
419
420 phy->cca_ed_level = level;
421
422 return 0;
423}
424
425static int phy_set_csma_params(struct wpan_phy *phy, struct genl_info *info)
426{
427 int rc;
428 u8 min_be = phy->min_be;
429 u8 max_be = phy->max_be;
430 u8 retries = phy->csma_retries;
431
432 if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
433 retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
434 if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
435 min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
436 if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
437 max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
438
439 if (retries > 5 || max_be > 8 || min_be > max_be ||
440 retries < -1 || retries > 7)
441 return -EINVAL;
442
443 rc = phy->set_csma_params(phy, min_be, max_be, retries);
444 if (rc < 0)
445 return rc;
446
447 phy->min_be = min_be;
448 phy->max_be = max_be;
449 phy->csma_retries = retries;
450
451 return 0;
452}
453
454static int phy_set_frame_retries(struct wpan_phy *phy, struct genl_info *info)
455{
456 s8 retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
457 int rc;
458
459 rc = phy->set_frame_retries(phy, retries);
460 if (rc < 0)
461 return rc;
462
463 phy->frame_retries = retries;
464
465 return 0;
466}
467
468int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
469{
470 struct wpan_phy *phy;
471 const char *name;
472 int rc = -ENOTSUPP;
473
474 pr_debug("%s\n", __func__);
475
476 if (!info->attrs[IEEE802154_ATTR_PHY_NAME] &&
477 !info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
478 !info->attrs[IEEE802154_ATTR_CCA_MODE] &&
479 !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
480 !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
481 !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
482 !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
483 !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
484 return -EINVAL;
485
486 name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
487 if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0')
488 return -EINVAL; /* phy name should be null-terminated */
489
490 phy = wpan_phy_find(name);
491 if (!phy)
492 return -ENODEV;
493
494 if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) ||
495 (!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
496 (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) ||
497 (!phy->set_cca_ed_level &&
498 info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]))
499 goto out;
500
501 mutex_lock(&phy->pib_lock);
502
503 if (info->attrs[IEEE802154_ATTR_TXPOWER]) {
504 rc = phy_set_txpower(phy, info);
505 if (rc < 0)
506 goto error;
507 }
508
509 if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) {
510 rc = phy_set_lbt(phy, info);
511 if (rc < 0)
512 goto error;
513 }
514
515 if (info->attrs[IEEE802154_ATTR_CCA_MODE]) {
516 rc = phy_set_cca_mode(phy, info);
517 if (rc < 0)
518 goto error;
519 }
520
521 if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) {
522 rc = phy_set_cca_ed_level(phy, info);
523 if (rc < 0)
524 goto error;
525 }
526
527 if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
528 info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
529 info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) {
530 rc = phy_set_csma_params(phy, info);
531 if (rc < 0)
532 goto error;
533 }
534
535 if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) {
536 rc = phy_set_frame_retries(phy, info);
537 if (rc < 0)
538 goto error;
539 }
540
541 mutex_unlock(&phy->pib_lock);
542
543 wpan_phy_put(phy);
544
545 return 0;
546
547error:
548 mutex_unlock(&phy->pib_lock);
549out:
550 wpan_phy_put(phy);
551 return rc;
552}
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index 6adda4d46f95..fd7be5e45cef 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -52,5 +52,15 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
52 [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, 52 [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, },
53 [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, 53 [IEEE802154_ATTR_ED_LIST] = { .len = 27 },
54 [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, 54 [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, },
55
56 [IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, },
57 [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, },
58 [IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
59 [IEEE802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
60 [IEEE802154_ATTR_CSMA_RETRIES] = { .type = NLA_U8, },
61 [IEEE802154_ATTR_CSMA_MIN_BE] = { .type = NLA_U8, },
62 [IEEE802154_ATTR_CSMA_MAX_BE] = { .type = NLA_U8, },
63
64 [IEEE802154_ATTR_FRAME_RETRIES] = { .type = NLA_S8, },
55}; 65};
56 66
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index 4dd37615a749..edd0962d55f9 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -44,9 +44,7 @@ static DEVICE_ATTR_RO(name);
44 44
45MASTER_SHOW(current_channel, "%d"); 45MASTER_SHOW(current_channel, "%d");
46MASTER_SHOW(current_page, "%d"); 46MASTER_SHOW(current_page, "%d");
47MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB", 47MASTER_SHOW(transmit_power, "%d +- 1 dB");
48 ((signed char) (phy->transmit_power << 2)) >> 2,
49 (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1);
50MASTER_SHOW(cca_mode, "%d"); 48MASTER_SHOW(cca_mode, "%d");
51 49
52static ssize_t channels_supported_show(struct device *dev, 50static ssize_t channels_supported_show(struct device *dev,
@@ -171,6 +169,12 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size)
171 phy->current_channel = -1; /* not initialised */ 169 phy->current_channel = -1; /* not initialised */
172 phy->current_page = 0; /* for compatibility */ 170 phy->current_page = 0; /* for compatibility */
173 171
172 /* defaults per 802.15.4-2011 */
173 phy->min_be = 3;
174 phy->max_be = 5;
175 phy->csma_retries = 4;
176 phy->frame_retries = -1; /* for compatibility, actual default is 3 */
177
174 return phy; 178 return phy;
175 179
176out: 180out:
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 52ae6646a411..b75bb01e5c6b 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -165,6 +165,67 @@ err:
165 return ERR_PTR(err); 165 return ERR_PTR(err);
166} 166}
167 167
168static int mac802154_set_txpower(struct wpan_phy *phy, int db)
169{
170 struct mac802154_priv *priv = wpan_phy_priv(phy);
171
172 if (!priv->ops->set_txpower)
173 return -ENOTSUPP;
174
175 return priv->ops->set_txpower(&priv->hw, db);
176}
177
178static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
179{
180 struct mac802154_priv *priv = wpan_phy_priv(phy);
181
182 if (!priv->ops->set_lbt)
183 return -ENOTSUPP;
184
185 return priv->ops->set_lbt(&priv->hw, on);
186}
187
188static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
189{
190 struct mac802154_priv *priv = wpan_phy_priv(phy);
191
192 if (!priv->ops->set_cca_mode)
193 return -ENOTSUPP;
194
195 return priv->ops->set_cca_mode(&priv->hw, mode);
196}
197
198static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
199{
200 struct mac802154_priv *priv = wpan_phy_priv(phy);
201
202 if (!priv->ops->set_cca_ed_level)
203 return -ENOTSUPP;
204
205 return priv->ops->set_cca_ed_level(&priv->hw, level);
206}
207
208static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
209 u8 max_be, u8 retries)
210{
211 struct mac802154_priv *priv = wpan_phy_priv(phy);
212
213 if (!priv->ops->set_csma_params)
214 return -ENOTSUPP;
215
216 return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries);
217}
218
219static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries)
220{
221 struct mac802154_priv *priv = wpan_phy_priv(phy);
222
223 if (!priv->ops->set_frame_retries)
224 return -ENOTSUPP;
225
226 return priv->ops->set_frame_retries(&priv->hw, retries);
227}
228
168struct ieee802154_dev * 229struct ieee802154_dev *
169ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) 230ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
170{ 231{
@@ -242,6 +303,12 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
242 303
243 priv->phy->add_iface = mac802154_add_iface; 304 priv->phy->add_iface = mac802154_add_iface;
244 priv->phy->del_iface = mac802154_del_iface; 305 priv->phy->del_iface = mac802154_del_iface;
306 priv->phy->set_txpower = mac802154_set_txpower;
307 priv->phy->set_lbt = mac802154_set_lbt;
308 priv->phy->set_cca_mode = mac802154_set_cca_mode;
309 priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
310 priv->phy->set_csma_params = mac802154_set_csma_params;
311 priv->phy->set_frame_retries = mac802154_set_frame_retries;
245 312
246 rc = wpan_phy_register(priv->phy); 313 rc = wpan_phy_register(priv->phy);
247 if (rc < 0) 314 if (rc < 0)